MACHINE 组件错误码#
范围:F7-F8XXXX
本文档说明 MACHINE 组件的错误码定义、场景说明与排查建议。
错误码定义与使用说明#
相关错误码的统一定义,参见 machine_error.h 文件。
排查建议#
AIC ERROR/The aicore execution is abnormal#
注释 CallSubFuncTask 及相关代码排除 machine 框架调度问题
framework/src/interface/machine/device/tilefwk/aicore_entry.h
INLINE void ExecDynCoreFunctionKernel(ExecuteContext *ctx, uint32_t taskId) {
uint64_t t1 = get_sys_cnt();
SetStatus(ctx->args, ((uint64_t)taskId << 32) | STAGE_PRE_EXEC_COREFUNC_KERNEL); // high 32 bits used for taskId
auto funcData = &ctx->funcDataList[npu::tile_fwk::FuncID(taskId)];
auto opAttrs = &funcData->opAttrs[funcData->opAtrrOffsets[npu::tile_fwk::TaskID(taskId)]];
#if ENABLE_AICORE_PRINT
CoreFuncParam param = {funcData, opAttrs, funcData->exprTbl, taskId, ctx->logger.context()};
#else
CoreFuncParam param = {funcData, opAttrs, funcData->exprTbl, taskId, nullptr};
#endif
CallSubFuncTask(opAttrs[0] + funcData->exprTbl[0], ¶m, funcData->stackWorkSpaceAddr + ctx->blockIdx * funcData->stackWorkSpaceSize,
(__gm__ int64_t *)funcData->startArgs->commContexts);
SetStatus(ctx->args, STAGE_FINISH_EXEC_COREFUNC_KERNEL);
PipeSync();
...
}
INLINE void ExecDynCoreFunctionKernel(ExecuteContext *ctx, uint32_t taskId) {
uint64_t t1 = get_sys_cnt();
SetStatus(ctx->args, ((uint64_t)taskId << 32) | STAGE_PRE_EXEC_COREFUNC_KERNEL); // high 32 bits used for taskId
auto funcData = &ctx->funcDataList[npu::tile_fwk::FuncID(taskId)];
auto opAttrs = &funcData->opAttrs[funcData->opAtrrOffsets[npu::tile_fwk::TaskID(taskId)]];
// #if ENABLE_AICORE_PRINT
// CoreFuncParam param = {funcData, opAttrs, funcData->exprTbl, taskId, ctx->logger.context()};
// #else
// CoreFuncParam param = {funcData, opAttrs, funcData->exprTbl, taskId, nullptr};
// #endif
// CallSubFuncTask(opAttrs[0] + funcData->exprTbl[0], ¶m, funcData->stackWorkSpaceAddr + ctx->blockIdx * funcData->stackWorkSpaceSize,
// (__gm__ int64_t *)funcData->startArgs->commContexts);
SetStatus(ctx->args, STAGE_FINISH_EXEC_COREFUNC_KERNEL);
PipeSync();
...
}
重新编译安装,运行验证,若问题仍然复现, 则说明是 machine 调度框架的问题,停止后续步骤。若问题不复现,将上述修改恢复,继续后续步骤
启用追踪日志
framework/src/interface/configs/tile_fwk_config.json
"fixed_output_path": true,
"force_overwrite": false,
framework/src/interface/machine/device/tilefwk/aicore_print.h
#define ENABLE_AICORE_PRINT 1
framework/src/machine/utils/device_switch.h
#define ENABLE_COMPILE_VERBOSE_LOG 1
重新编译安装
清理日志并运行测试
(1)清理日志
rm -rf ./my_log/*
rm -rf ./kernel_aic*
(2)打开DEBUG日志,指定日志落盘路径
export ASCEND_GLOBAL_LOG_LEVEL=0
export ASCEND_PROCESS_LOG_PATH=./my_log
(3)执行用例
分析追踪日志并定位 CCE 文件
(1)查找 trace 日志、分析缺失 leaf index 并定位问题 CCE 文件
python3 .agents/skills/pypto-aicore-error-locator/scripts/analyze_trace.py ./my_log run_path/kernel_aicore
结果说明:此脚本会给出问题CCE文件路径,若输出多个问题CCE文件,需要验证哪个CCE文件才是问题CCE文件,执行第二步,若只输出一个CCE文件,需要check该CCE文件是否是问题文件,执行第二步
(2)测试验证 CCE 文件
python3 .agents/skills/pypto-aicore-error-locator/scripts/test_cce_file.py <cce_file> test_cmd run_path
结果说明:此脚本会给出判断,明确输入的CCE文件是否为问题文件
注:run_path为运行目录路径,test_cmd为运行测试命令
二分查找定位CCE文件问题代码行
(1)check错误是否在 T 操作中
python3 .agents/skills/pypto-aicore-error-locator/scripts/determine_error_scope.py <cce_file> test_cmd run_path
结果说明:此脚本会将所有的操作行(例如TLoad、TMatmul等)全部注释,进行测试,若不复现现象,则说明问题出现在操作行,输出ERROR_IN_T为True,否则ERROR_IN_T为False
(2)获取二分查找初始范围
python3 .agents/skills/pypto-aicore-error-locator/scripts/get_commentable_range.py <cce_file> ERROR_IN_T
结果说明:此脚本根据ERROR_IN_T的值给出二分查找的范围left值和right值,若ERROR_IN_T为True,则排查范围为全部操作行,若ERROR_IN_T为False,则排查范围为除了同步行的所有行
(3)执行二分查找迭代,直到找到CCE文件问题代码行
python3 .agents/skills/pypto-aicore-error-locator/scripts/binary_search_iteration.py <cce_file> test_cmd run_path <left> <right> ERROR_IN_T
结果说明:此脚本运行输出结果为新的left和right值,基于新的left和right值继续执行该脚本,直到出现 找到问题代码行 为止
关联 Skill:pypto-aicore-error-locator
怀疑和MACHINE内存处理有关的精度问题#
检查输入初始化: 保证输入/输出初始化
检查 Tensor 连续性: 部分 MACHINE 相关算子或接口要求输入/输出在指定内存布局下连续(
tensor.is_contiguous()为 True)。非连续 tensor(如某些 view、transpose、slice 结果)可能导致精度异常或运行错误。 eg:reshape/view、交换维度、索引/切片后的 tensor 可能非连续;若前序是 COPY_IN 或尾轴 reduce,需在前端或调用侧保证传入的 tensor 在对应格式下连续。扩大 workspace 大小:
python/pypto/frontend/parser/entry.py
workspace_tensor = torch.empty(workspace_size, dtype=torch.uint8, device=device)
workspace_tensor = torch.empty(workspace_size * 10, dtype=torch.uint8, device=device)
如果问题不复现,则是workspace计算问题
workspace从torch管理,改为内部自管理
framework/src/machine/runtime/device_launcher.cpp
static void PrepareDevProgArgs(DevAscendProgram *devProg, DeviceLauncherConfig &config,
[[maybe_unused]]bool isDevice) {
...
if (config.workspaceAddr) {
kArgs.workspace = (int64_t *)config.workspaceAddr;
} else if (kArgs.workspace == nullptr && (devProg->workspaceSize != 0)) {
kArgs.workspace = (int64_t *)devMem.AllocDev(devProg->workspaceSize, CachedOperator::GetWorkspaceDevAddrHolder(cachedOperator));
}
...
}
static void PrepareDevProgArgs(DevAscendProgram *devProg, DeviceLauncherConfig &config,
[[maybe_unused]]bool isDevice) {
...
if (0) {
kArgs.workspace = (int64_t *)config.workspaceAddr;
} else if (kArgs.workspace == nullptr && (devProg->workspaceSize != 0)) {
kArgs.workspace = (int64_t *)devMem.AllocDev(devProg->workspaceSize, CachedOperator::GetWorkspaceDevAddrHolder(cachedOperator));
}
...
}
如果问题不复现,则是workspace使用问题,存在内存踩踏等
leaf function粒度的内存重叠检测 (1)打开VERBOSE日志
framework/src/machine/utils/device_switch.h
#define ENABLE_COMPILE_VERBOSE_LOG 1
(2)打开DEBUG日志,指定日志落盘路径
export ASCEND_GLOBAL_LOG_LEVEL=0
export ASCEND_PROCESS_LOG_PATH=./my_log
(3)重新编pypto whl包并安装
(4)启动性能数据采集功能,保证生成 dyn_topo.txt
```python
@pypto.frontend.jit(
debug_options={"runtime_debug_mode": 1}
)
```
(5)执行用例
(6)执行内存检测脚本
命令格式:
python3 tools/schema/schema_memory_check.py -d <device_log_dir_absolute_path> -t <topo_file_absolute_path>
示例(请替换为实际绝对路径):
python3 tools/schema/schema_memory_check.py -d /path/to/my_log/debug/device-8/ -t /path/to/output/output_20260314_112655_964781_3025352/dyn_topo.txt
如无异常,提示device task 无内存重叠; 如存在异常,提示内存重叠的 device task 以及 leaf function。
注: (1)如果报错 emory reuse must happen for full match. 则两个需要内存复用的 rawtensor 范围不一致; (2)如果报错 memory reuse must happen for same dimension. 则两个内存复用的 rawtensor 的 shape 不一致; 上述两种情况非内存重叠,脚本内存检查依赖不会发生上述情况 ,因此脚本会断言,直接提示日志信息错误。
复杂特性排除: 使用
pypto-precision-debuggerskill,关闭unroll_list、合轴特性、配置submit_before_loop=True使loop串行执行、确定valid_shape配置正确性、+0.0等,缩小定位范围。
encode 阶段 actualRawMagic 断言触发#
问题特征:运行用例时在 encode 阶段触发断言,错误信息包含 Shape size mismatch 或 Data size mismatch,并伴随 rawTensor->actualRawmagic、rawShape、actualrawShape 等字段输出,报错位置为 framework/src/machine/utils/dynamic/dev_encode.cpp 中 InitRawTensorAndMemoryRequirement 函数。
问题背景:encode 阶段会对所有带有 actualRawmagic 的 RawTensor 进行内存复用一致性校验——即要求复用链两端(当前 rawTensor 与其 actualRawmagic 指向的 actualRaw)在 rawShapeSize(元素数乘积)或 rawDataSize(字节大小)上严格一致。涉及 reshape、assemble 等内存复用操作时,若 pass 侧未同步更新相关 tensor 的特征信息,就会触发此类断言。
定位步骤:
从报错第一现场获取基础信息:
触发断言时,错误日志中会包含以下关键字段(对应
dev_encode.cpp第 412~420 行):Shape size mismatch: <rawShapeSize> != <actualRawShapeSize>, rootMagic=<...>, rootHash=<...>, rawShape=<...>, actualrawShape=<...>, rawTensor->rawMagic=<...>, rawTensor->actualRawmagic=<...>, actualRaw->rawMagic=<...>
记录其中的
rawMagic、actualRawmagic、rawShape、actualrawShape,作为后续计算图定位的依据。若当前报错信息不够完整(缺少 rawMagic 等字段),可参考
dev_encode.cpp中该 ASSERT 的上下文,在断言前增加相关字段打印,重编 whl 包后复现。打开 pass 计算图 dump 开关:
修改
framework/src/interface/configs/tile_fwk_config.json,将global.pass.default_pass_configs下的dump_graph改为true:"default_pass_configs": { "print_graph": false, "print_program": false, "dump_graph": true, ... }重新编译 whl 包并安装。
复现用例,获取 pass 计算图:
再次执行用例,在
build/output/pass/目录下会生成各 pass 阶段的计算图文件。定位目标 pass 范围:
建议重点排查 pass4 ~ pass27 之间的 tilegraph:
pass4 ExpandFunction: 之前为 tensorgraph 阶段,尚未进入 pass 的tile展开 粒度分析
pass27 SubgraphToFunction: 之后框架开始切分 root function 为 leaf function,图结构较为分散,不便于整体定位
在该范围内,根据步骤 1 获取的
rawMagic/actualRawmagic,在计算图中定位对应 tensor 节点。结合计算图分析问题原因:
确定 tensor 节点后,沿数据流向分析其上下游操作,重点关注以下场景:
reshape 操作:reshape 会为输出 tensor 设置
actualRawmagic,使其复用输入 tensor 的内存地址assemble 操作:assemble 在图优化阶段会将输入 tensor 的 raw 指针替换为目标大 tensor 的 raw,若 reshape 在此之前已设置
actualRawmagic,该字段可能未随 raw 替换同步更新其他内存复用操作:view、inplace 等操作同样涉及
actualRawmagic的设置与传递
若复用链两端的 rawShapeSize 在某个 pass 之后出现不一致,说明该 pass 对其中一侧的 rawshape 进行了改写,但未同步另一侧。
判断问题归属:
(1)用例写法问题:检查用例中 reshape、assemble 等操作的组合方式是否满足 API 约束(如
inplace=True的限制、valid_shape 与 rawshape 的一致性要求等)。若存在不满足约束的写法,调整用例。(2)框架侧问题:若用例写法无误,联系 pass 同事进行进一步分析,排查框架在处理 actualRawmagic 传递时是否存在遗漏或错误更新的场景。
注:
actualRawmagic 断言失败本质是编译期一致性校验,去掉断言后若运行精度仍正确,说明该路径的运行时读写并未越界,属于校验口径过严或 pass 侧信息同步遗漏问题,需与 pass 同事联合分析
此类问题若在动态 shape(含负数维度)场景下触发,
dev_encode.cpp会跳过动态维度的校验(isDynamicShape分支),排查时需注意区分静态与动态 shape 场景
Workspace 内存异常偏大#
问题特征:运行用例时内存分配失败,报错信息为以下两类之一:
torch 申请失败:
torch.OutOfMemoryError: NPU out of memory. Tried to allocate 6.69 GiB (NPU 5; 60.96 GiB total capacity; ...)
device 内存申请失败:
rtMalloc failed. size:5254523547
问题背景:Workspace 内存分配由以下阶段组成:
图编译阶段:在
dev_encode.cpp的EncodeDevAscendProgram中估算各类内存池预算Launch 阶段(用户指定):通过
dynWorkspaceSize指定额外的动态内存(一般不会是此处问题)Launch 阶段(实际分配):在
device_launcher.h中通过devMem.AllocDev(devProg->workspaceSize, ...)一次性分配整个内存池Device 运行时:在
dev_workspace.h中按预算对内存池进行 suballocation
实际发生 malloc 的只有阶段 3。内存池超大说明阶段 1 的预算估算出了问题。
Workspace 的内存预算结构(定义于 dev_encode_program.h):
struct {
struct {
uint64_t rootInner; // Root Function Inner Tensor 内存
uint64_t devTaskInnerExclusiveOutcasts; // DeviceTask 内部 Exclusive Outcast 内存
uint64_t maxStaticOutcastMem; // 最大静态 Outcast 单体大小
uint64_t maxDynamicAssembleOutcastMem; // 最大动态 Assemble Outcast 单体大小
uint64_t devTaskBoundaryOutcastNum; // Boundary Outcast slot 数量
uint64_t MaxOutcastMem() const {
return std::max(maxStaticOutcastMem, maxDynamicAssembleOutcastMem);
}
uint64_t Total() const {
return rootInner + devTaskInnerExclusiveOutcasts +
MaxOutcastMem() * devTaskBoundaryOutcastNum;
}
} tensor;
uint64_t aicoreSpilled;
struct {
uint64_t general;
uint64_t stitchPool;
uint64_t Total() const { return general + stitchPool; }
} metadata;
struct {
uint64_t dumpTensor;
uint64_t leafDump;
} debug;
} memBudget;
定位步骤:
开启日志与计算图 dump:
(1)至少设置 INFO 日志级别:
export ASCEND_GLOBAL_LOG_LEVEL=1 export GLOBAL_LOG_LEVEL=1 export ASCEND_PROCESS_LOG_PATH=<日志落盘路径>
(2)打开计算图 dump(便于后续定位问题 tensor 在图中的位置):
framework/src/interface/configs/tile_fwk_config.json"dump_graph": true
(3)重新编译 whl 包并安装,执行用例。
查看 workspace 总体大小构成:
在日志路径
./debug下搜索[workspaceSize]关键字,可以看到如下格式的日志:[workspaceSize] Metadata=12062240, workspaceSize=599916544, tensor=592543744, aicoreSpillen=7372800, debug.DumpTensor=0, leafDumpWorkspace=0. [workspaceSize] Tensor:rootInner=182452224, devTaskInnerOutCasts=29360128, slotted=6144x61964(slots).
其中
workspaceSize为总大小,tensor、Metadata、aicoreSpillen、debug.DumpTensor、leafDumpWorkspace为各子项。通过对比可快速确定哪个大类占用最多。当前 workspace 大小类问题主要集中在 Tensor Workspace,metadata 在总量中占比通常不高。若出现 metadata 类报错(包含
"Memory not enough"且WsProperty:metadata、或包含"Slab alloc null"字样),建议直接联系 machine 同事分析。分析 Tensor Workspace 各项占比:
Tensor 日志格式
Tensor:rootInner=A, devTaskInnerOutCasts=B, slotted=CxD(slots)中:A=memBudget.tensor.rootInnerB=memBudget.tensor.devTaskInnerExclusiveOutcastsC=memBudget.tensor.MaxOutcastMem()(单个 Boundary Outcast 最大大小)D=memBudget.tensor.devTaskBoundaryOutcastNum(slot 数量)Boundary Outcast 总内存 = C × D
结合每个 Root Function 级别的日志进一步缩小范围:
[workspaceSize] MaxRootInnerMem is 182452224, maxDevTaskInnerExclusiveOutcastMem is 4194304. [workspaceSize] Rootfunction: TENSOR_LOOP_s2_Unroll8_PATH3_hiddenfunc0_root ->MaxRootInnerMem is 182452224, maxDevTaskInnerExclusiveOutcastMem is 4194304.
MaxRootInnerMem和maxDevTaskInnerExclusiveOutcastMem是经过 unroll 和 stitch 膨胀后的值。若多个 Root Function 中某一个的值远超其他,即为问题来源。情况一:rootInner / devTaskInnerOutCasts 均匀偏大
先确认是否为
stitch_function_max_num或unroll_list配置过大导致。内存膨胀关系大致为(近似,非精确公式):rootInner ≈ per_root_budget / unroll × WorkspaceRecyclePeriod devTaskInnerOutCasts ≈ per_root_budget / unroll × EstimatedStitchingCount
其中
WorkspaceRecyclePeriod ≈ stitch_function_max_num × MAX_UNROLL_TIMES。可通过降低stitch_function_max_num或unroll_list在牺牲并行度的前提下降低内存。若单个 loop 的内存需求已经偏高(原始rootInnerTensorWsMemoryRequirement超过 20MB),则需分析 pass 的内存复用策略及算子本身写法。情况二:Boundary Outcast 内存偏大(slotted 项中单体大小 C 异常大)
由于 Tiling 会将 Tensor 切至中等大小(如不超过 512×512),超大的
MaxOutcastMem()通常意味着未经 Tiling 的超大 Tensor 进入了子图。常见原因包括 Inplace 操作、Fixed Address Tensor、shmemData 等例外 case,通常为框架未正确处理所致。此时需进一步找到具体的问题 Tensor(见步骤 4)。定位问题 Tensor:
日志中会对 shape 超过 512×512 的 Tensor 打印警告:
[workspaceSize] Root=[TENSOR_LOOP_s2_Unroll8_PATH3_hiddenfunc0_root], symbol=[atten_out],rawmagic=[3066]: staticMemReq=[12582912] is too larger, which might indicate an error
每条记录包含 Root Function 名称、Tensor 符号名(匿名 Tensor 为空)、rawmagic 以及静态内存大小。结合步骤 3 中确定的异常 Root Function 名称和异常内存值进行匹配。
例如,若步骤 3 中 Boundary Outcast 单体大小为
12582912,在警告日志中搜索该值即可定位到具体 Tensor。结合计算图确认问题位置:
在步骤 1 打开
dump_graph后,pypto/output/pass/目录下会生成各 pass 阶段的计算图。根据步骤 4 获取的 Root Function 名称和 rawmagic,在计算图中搜索对应节点,确认该 Tensor 的上下游操作及 shape 来源,并能够跳转到对应代码段。定位到此即可联系相关组件同事介入分析。
影响 workspace 大小的关键配置项:
配置项
影响范围
说明
stitch_function_max_numrootInner、devTaskInnerOutCasts、Boundary slot 数
控制 stitch 并行数,直接影响 WorkspaceRecyclePeriod 和 EstimatedStitchingCount
unroll_list/ max_unrollrootInner、devTaskInnerOutCasts
控制 loop 展开次数,影响 CalcUnrolledRootBudget
注:
动态 shape 场景下
maxStaticMemReq为 0(无法从符号 shape 推算静态大小),此类 Tensor 不会出现在超大 Tensor 的警告中aicoreSpilled为 AICore 栈溢出到 workspace 的内存,若该项异常偏大,需检查算子的stackWorkSpaceSizedebug.DumpTensor和leafDumpWorkspace为调试模式下的额外内存开销,正常模式下为 0
F70006 HANDSHAKE_TIMEOUT#
确认设备与驱动:NPU 设备可用、驱动正常,
npu-smi info无异常。确认资源与负载:当前进程/容器内 NPU 占用是否过高,是否存在多进程争用同一设备。
确认超时配置:若存在握手/同步超时配置项,检查是否过短或与环境不符。
查日志上下文:结合同线程前后日志(如 “Schedule run init succ” 之后、AbnormalStop 相关)确认是首次握手失败还是运行中异常。
关联 Skill:pypto-environment-setup(环境与 NPU 设备诊断、npu-smi、驱动与编译运行)