在进行算子NPU域的运行验证时,实际数据和真值数据不一致,算子存在精度问题。
算子出现精度问题,一般是由于算子的实现逻辑有误。
Ascend C提供孪生调试的功能,通过CPU域的功能验证、gdb单步调试、printf数值打印来定位算子的实现逻辑问题。本样例仅展示了可能会出现的场景,便于演示定位步骤。实际使用过程中,请根据代码情况进行调试。
参考Kernel直调章节,编写CPU侧的运行验证代码,并进行运行验证,发现CPU域的精度比对也存在不一致的问题。
观察打屏日志中是否有报错信息,可搜索关键词"failed"。比如,下图的报错示例指示,错误出现在代码中调用LeakyRelu接口的地方。
1 | leakyrelu_custom_cpu: /usr/local/Ascend/CANN-7.0/x86_64-linux/tikcpp/tikcfw/interface/kernel_operator_vec_binary_scalar_intf.h:447: void AscendC::LeakyRelu(const AscendC::LocalTensor<T>&, const AscendC::LocalTensor<T>&, const T&, const int32_t&) [with T = float16::Fp16T; int32_t = int]: Assertion `false && "check vlrelu instr failed"' failed |
通过上述报错日志,一般只能定位到报错的代码行,无法明确具体错误,接下来需要通过gdb调试的方式或者printf打印的方式进一步精确定位。
gdb leakyrelu_custom_cpu
(gdb) set follow-fork-mode child
(gdb) r
(gdb) bt
(gdb) f 5 #5 0x000055555555d364 in KernelLeakyRelu::Compute (this=0x7fffffffd7d0, progress=0) at /root/AscendC_DemoCode-master/precision-error/vector/leakyrelu_custom.cpp:59 59 LeakyRelu(yLocal, xLocal, scalar, tileLength); (gdb) p tileLength $1 = 1024 (gdb) p xLocal $1 = {<AscendC::BaseTensor<float16::Fp16T>> = {<No data fields>}, address_ = {logicPos = 9 '\t', bufferHandle = 0x7fffffffd930 "\003\005\377\377", dataLen = 1024,bufferAddr = 0,absAddr = ...}
1 2 | printf("xLocal size: %d\n", xLocal.GetSize()); printf("tileLength: %d\n", tileLength); |
可以看到有如下打屏日志输出,打印了tileLength为1024,该程序中表示需要处理1024个half类型的数;输入Tensor xLocal的size大小,为512,表示只能计算512个half类型的数。可以看出两者的长度不匹配,由此可以定位问题。
1 2 | xLocal size: 512 tileLength: 1024 |