检测内核调用符方式的Ascend C算子

操作步骤

  1. 请参考内核调用符场景准备,完成使用前准备。
  2. 参考工具路径完成相关环境变量配置。
  3. 构建单算子可执行文件。

    Add算子可执行文件的构建命令示例如下:

    bash run.sh -r npu -v <soc_version> 

    一键式编译运行脚本完成后,在工程目录下生成NPU侧可执行文件<kernel_name>_npu

  4. 使用msSanitizer检测工具拉起单算子可执行文件(以add_npu为例)。

    • 内存检测执行以下命令,具体参数说明请参考表2表3,内存检测请参考内存检测示例说明
      mssanitizer --tool=memcheck ./add_npu   # 内存检测需指定 --tool=memcheck
    • 竞争检测执行以下命令,具体参数说明请参考表2,竞争检测请参考竞争检测示例说明
      mssanitizer --tool=racecheck ./add_npu  # 竞争检测需指定 --tool=racecheck

    单算子可执行文件所在路径可配置为绝对路径或相对路径,请根据实际环境配置。

内存检测示例说明

  1. 步骤1之前,需要在Add 算子中构造一个非法读写的场景,将DataCopy内存拷贝长度从TILE_LENGTH 改为2 * TILE_LENGTH ,此时最后一次拷贝会发生内存读写越界。
      __aicore__ inline void CopyOut(int32_t progress)
        {
            // deque output tensor from VECOUT queue
            LocalTensor<half> zLocal = outQueueZ.DeQue<half>();
            // copy progress_th tile from local tensor to global tensor
            // 构建非法读写场景
            DataCopy(zGm[progress * TILE_LENGTH], zLocal, 2 * TILE_LENGTH);
            // free output tensor for reuse
            outQueueZ.FreeTensor(zLocal);
        }
  2. 根据检测工具输出的报告,可以发现在add_custom.cpp的63行对GM存在 256 字节的非法读操作,与我们构造的异常场景对应。
    $ mssanitizer --tool=memcheck --leak-check=yes ./add_custom_npu
    [mssanitizer] logging to file: ./mssanitizer_20240124182331_37743.log
    ====== ERROR: illegal read of size 256
    ======    at 0x124080022f00 on GM
    ======    in block 7
    ======    code in add_custom.cpp:63

竞争检测示例说明

  1. 步骤1之前,需要在Add 算子中构造一个流水间竞争的场景,将CopyOut函数中的数据搬出逻辑直接写在Compute函数末尾,并注释zLocal的入队操作,此时会在zLocal内存上存在竞争。

        __aicore__ inline void Compute(int32_t progress)
        {
            LocalTensor<half> xLocal = inQueueX.DeQue<half>();
            LocalTensor<half> yLocal = inQueueY.DeQue<half>();
            LocalTensor<half> zLocal = outQueueZ.AllocTensor<half>();
            Add(zLocal, xLocal, yLocal, TILE_LENGTH);
            // outQueueZ.EnQue<half>(zLocal);
            inQueueX.FreeTensor(xLocal);
            inQueueY.FreeTensor(yLocal);
            // 计算完成后不通过 queue 保证同步,构造竞争异常场景
            DataCopy(zGm[progress * TILE_LENGTH], zLocal, TILE_LENGTH);
            outQueueZ.FreeTensor(zLocal);
        }
    ...
        __aicore__ inline void Process()
        {
            int32_t loopCount = TILE_NUM * BUFFER_NUM;
            for (int32_t i = 0; i < loopCount; i++) {
                CopyIn(i);
                Compute(i);
                // 不使用 CopyOut 函数,直接在 Compute 函数中做搬出
                // CopyOut(i);
            }
        }

  2. 根据检测工具输出的报告,可以发现在add_custom.cpp的58行和63行,PIPE_V和PIPE_MTE3流水在UB上存在先读后写竞争,符合我们构造的异常场景。

    $ mssanitizer --tool=racecheck ./add_npu
    ====== ERROR: Potential RAW hazard detected at UB :
    ======    PIPE_V Write at RAW()+0x400 in add_custom.cpp:58
    ======    PIPE_MTE3 Read at RAW()+0x400 in add_custom.cpp:63