---
title: 核函数运行验证时算子存在精度问题
description: "在进行算子NPU域的运行验证时，实际数据和真值数据不一致，算子存在精度问题。"
url: https://www.hiascend.com/document/detail/zh/canncommercial/latest/programug/Ascendcopdevg/atlas_ascendc_10_0106.html
sourcePath: /source/zh/canncommercial/900/programug/Ascendcopdevg/atlas_ascendc_10_0106.html
indexId: 1ddce9e2ef72afda3f0b837fd0ae5635d8dbd3cce67408135bceb1ff58dba4ce80
---
# 核函数运行验证时算子存在精度问题

#### 现象描述

在进行算子NPU域的运行验证时，实际数据和真值数据不一致，算子存在精度问题。


#### 问题根因

算子出现精度问题，一般是由于算子的实现逻辑有误。


#### 定位步骤

Ascend C提供孪生调试的功能，通过CPU域的功能验证、gdb单步调试、printf数值打印来定位算子的实现逻辑问题。本样例仅展示了可能会出现的场景，便于演示定位步骤。实际使用过程中，请根据代码情况进行调试。

1. 进行CPU域的功能验证，观察是否有日志报错。
  参考基于样例工程完成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打印的方式进一步精确定位。

2. gdb调试。下面的样例展示了拉起leakyrelu算子CPU侧运行程序的样例，该样例程序会直接抛出异常，直接gdb运行，查看调用栈信息分析定位即可。其他场景下您可以使用gdb打断点等基本操作进行调试。使用gdb调试Ascend C程序的详细内容请参考CPU域孪生调试。
  a. 使用gdb拉起待调试程序，进入gdb界面进行debug。

```
gdb leakyrelu_custom_cpu
```


  b. 单独调试一个子进程。

```
(gdb) set follow-fork-mode child
```


  c. 运行程序。

```
(gdb) r
```


  d. 通过bt查看程序调用栈。

```
(gdb) bt
```


  e. 查看具体层的堆栈信息，打印具体变量的值。本示例中，打印了tileLength为1024，该程序中表示需要处理1024个half类型的数，大小为1024*sizeof(half)=2048字节；输入Tensor xLocal的值，其中dataLen表示LocalTensor的size大小为1024字节，只能计算1024字节的数据。可以看出两者的长度不匹配，由此可以定位问题。

```
(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 = ...}
```


3. printf打印。在合适的位置增加变量打印。样例代码如下：
  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
