竞争检测
竞争检测工具是一个用于检测算子运行时,内部存储或外部存储同时访问风险的工具,该工具主要是帮助用户识别到内存数据的竞争访问风险。在昇腾芯片架构下,外部存储或内部存储可以被多个流水访问,通常被用作临时缓冲区保存正在处理的数据。由于这些数据可以同时被多个流水访问,算子程序没有正确处理流水同步时就可能会导致数据竞争的问题。
竞争异常类型
竞争异常是指两个内存事件(其中至少有一个为写事件)尝试访问同一块内存时,出现不符合基于预期执行顺序的结果。这种异常会导致数据竞争,从而使程序的运行或输出取决于内存事件的实际执行顺序。竞争检测工具能够识别以下三种典型的竞争异常:
异常名 |
描述 |
位置 |
支持地址空间 |
---|---|---|---|
Write-After-Write(WAW) |
当两个内存事件尝试向同一块内存写入时,可能存在这种异常,导致内存结果值取决于两个内存事件的实际访问顺序。 |
kernel |
GM, UB, L0{A,B,C}, L1 |
Write-After-Read(WAR) |
当两个内存事件(一个事件执行读取操作,另一个事件执行写入操作)尝试访问同一块内存时,可能存在这种异常,即写操作事件实际在读操作事件之前执行完毕,并导致读取到的内存值并非预期起始值。 |
||
Read-After-Write(RAW) |
当两个内存事件(一个事件执行读取操作,另一个事件执行写入操作)尝试访问同一块内存时,可能存在这种异常,即读操作事件实际在写操作事件之前执行完毕,并导致读取到的内存值还未更新。 |
当竞争检测工具识别出异常,用户就可以修改程序以确保该异常不再存在。在出现先写后读或先读后写的情况下,会根据serialNo大小顺序确定先后顺序,serialNo小的在PIPE_S上先执行。
启用竞争检测
mssanitizer --tool=racecheck ./<kernel_name>_npu
./<kernel_name>_npu为NPU侧可执行文件所在路径,可配置为相对路径或绝对路径。
竞争检测报告解析
竞争检测工具会输出一系列信息,详细说明有关算子各 PIPE 之间存在的内存数据竞争访问风险。
====== ERROR: Potential RAW hazard detected at UB : // 竞争事件类型、异常内存块信息 ====== PIPE_MTE2 Write at RAW()+0x0 in block 0 (aiv) at pc current 0xa98 (serialNo:14) // 竞争事件的详细信息,包含该事件所在的PIPE、操作类型、内存访问起始地址、核类型、AICore信息以及代码执行的pc指针和调用api行为的序列号 ====== #0 ${ASCEND_HOME_PATH}/compiler/tikcpp/tikcfw/impl/dav_c220/kernel_operator_data_copy_impl.h:58:9 // 以下为异常发生代码的调用栈,包含文件名、行号和列号 ====== #1 ${ASCEND_HOME_PATH}/compiler/tikcpp/tikcfw/inner_interface/inner_kernel_operator_data_copy_intf.cppm:58:9 ====== #2 ${ASCEND_HOME_PATH}/compiler/tikcpp/tikcfw/inner_interface/inner_kernel_operator_data_copy_intf.cppm:443:5 ====== #3 Racecheck/raw_error_kernel.cpp:17:5 ====== PIPE_MTE3 Read at RAW()+0x0 in block 0 (aiv) at pc current 0xad4 (serialNo:17) ====== #0 ${ASCEND_HOME_PATH}/compiler/tikcpp/tikcfw/impl/dav_c220/kernel_operator_data_copy_impl.h:103:9 ====== #1 ${ASCEND_HOME_PATH}/compiler/tikcpp/tikcfw/inner_interface/inner_kernel_operator_data_copy_intf.cppm:155:9 ====== #2 ${ASCEND_HOME_PATH}/compiler/tikcpp/tikcfw/inner_interface/inner_kernel_operator_data_copy_intf.cppm:461:5 ====== #3 Racecheck/raw_error_kernel.cpp:22:5
以上示例中表示了AICore 0的vector核内部中存在对UB的先写后读竞争风险,PIPE_MTE2 流水中存在对“0x0”地址的写入操作事件,该操作对应算子实现文件raw_error_kernel.cpp中的第17行,PIPE_MTE3流水中存在对“0x0”地址的读取操作事件,该操作对应算子实现文件raw_error_kernel.cpp中的第22行。