背景
在 Ascend A5(Ascend950PR_9589)板卡上,对 examples/ascend_mhc 下的 MHC(Mixture-of-Hyper-Channel)算子测试集做 ascend 原生后端 vs PTO 后端的对比验证时,发现 PTO 后端 (TILELANG_TARGET=pto) 在多个测试文件上无法完成编译/运行。
本 issue 按会议要求重新组织:不以 test 文件为最小归类单位(不同 test 可能调用同类 Kernel,存在同类问题),改为以 Kernel 为粒度归类。包含两张表:
- 表1:每个 test 文件 → 调用的 Kernel 数量 + ascend 状态 + PTO 状态
- 表2:PTO 问题分类(按 Kernel 聚类)
本 issue 不预设责任归属,只汇总 ascend pass/fail + PTO 问题归类 + 复现步骤,供判断属于 PTOAS / tilelang-dsl / tile-kernels 哪一层。
环境
- 板卡:Ascend950PR_9589(A5),device 0(126112MB,
vector_core_num=64,cube_core_num=32);device 1 在连续负载下易 segfault,device 0 更稳定
- OS:aarch64 Linux
- conda env:
rp21-PT2.7(python 3.10,torch 2.7.1+cpu + torch_npu)
- CANN:
/home/wenquan/cann29/cann-9.0.0
- tilelang:
/home/wangmiao/tilelang-simtvf-pr9-buildable(dev build)
- ptoas:
/home/wangmiao/PTOAS-main-1df3fba/install/bin/ptoas
- LLVM:
/home/ptoas-board-monitor-a5/llvm-project-vpto-feature/build-shared
- tile-kernels:
/home/wangmiao/tile-kernels
- 测试目录:
/home/wangmiao/tilelang-simtvf-pr9-buildable/examples/ascend_mhc
复现步骤
source /home/anaconda3/etc/profile.d/conda.sh
conda activate rp21-PT2.7
source /home/wenquan/cann29/cann-9.0.0/aarch64-linux/bin/setenv.bash
export PYTHONPATH=/home/wangmiao/tilelang-simtvf-pr9-buildable/3rdparty/tvm/3rdparty/tvm-ffi/python:/home/wangmiao/tilelang-simtvf-pr9-buildable/3rdparty/tvm/python:/home/wangmiao:/home/wangmiao/tile-kernels:/home/wangmiao/tilelang-simtvf-pr9-buildable:${PYTHONPATH:-}
export LD_LIBRARY_PATH=/home/wangmiao/tilelang-simtvf-pr9-buildable/build/lib:/home/ptoas-board-monitor-a5/llvm-project-vpto-feature/build-shared/lib:/home/wangmiao/PTOAS-main-1df3fba/install/lib:${LD_LIBRARY_PATH:-}
export PATH=/home/wangmiao/PTOAS-main-1df3fba/build/tools/ptoas:/home/wangmiao/PTOAS-main-1df3fba/install/bin:${PATH}
export PTOAS_BIN=/home/wangmiao/PTOAS-main-1df3fba/install/bin/ptoas
export LLVM_HOME=/home/ptoas-board-monitor-a5/llvm-project-vpto-feature/build-shared
export ASCEND_RT_VISIBLE_DEVICES=0
export TORCH_DEVICE_BACKEND_AUTOLOAD=0
export PYTHONFAULTHANDLER=1
cd /home/wangmiao/tilelang-simtvf-pr9-buildable/examples/ascend_mhc
# ascend 后端(逐文件,带 transfer_to_npu)
export TILELANG_TARGET=ascend
export PYTEST_ADDOPTS="-p torch_npu.contrib.transfer_to_npu"
for f in test_*.py; do
python -c "import torch,torch_npu;torch.npu.set_device(0);torch.zeros(1,device=0);torch.npu.synchronize();from tile_kernels.config import get_device_num_sms,get_num_sms;get_device_num_sms.cache_clear();import pytest,sys;sys.exit(pytest.main(['-q','-p','no:cacheprovider']+sys.argv[1:]))" "$f"
done
# pto 后端(逐文件,同样带 transfer_to_npu)
export TILELANG_TARGET=pto
for f in test_*.py; do
python -c "import torch,torch_npu;torch.npu.set_device(0);torch.zeros(1,device=0);torch.npu.synchronize();from tile_kernels.config import get_device_num_sms,get_num_sms;get_device_num_sms.cache_clear();import pytest,sys;sys.exit(pytest.main(['-q','-p','no:cacheprovider']+sys.argv[1:]))" "$f"
done
注1:TILELANG_TARGET=pto 时必须带 -p torch_npu.contrib.transfer_to_npu,否则测试文件里硬编码的 device='cuda' 参考实现会因 torch_npu 未编 CUDA 而抛 AssertionError: Torch not compiled with CUDA enabled,掩盖真正的 PTO 编译错误。
注2:为避免 transfer_to_npu 启动早期 NPU runtime 未就绪时 tile_kernels.config.get_num_sms() 命中 aclrtGetDeviceInfo 507899 返回 None 导致 T.Kernel(None) segfault,需在同一进程内先做 NPU 预热 + get_device_num_sms.cache_clear() 再跑 pytest(故用 python -c 一起调,不能用 python -m pytest)。每个文件建议单独进程跑。
注3:device 1 在连续负载下存在 segfault 抖动(crash 帧在 tvm::tl::KernelLaunch,libtilelang.so)。device 0 更稳定,下表数字均为 device 0 实测;如复现时遇到 segfault,冷却后重试即可拿到真实结果,不影响 PTO 错误归类判定。
表1:每个 test 文件的 Kernel 数量与 ascend / PTO 状态
下表数字为 device 0(ASCEND_RT_VISIBLE_DEVICES=0)实测;device 1 在连续负载下易 segfault,device 0 更稳定。
| 测试文件 |
调用的 Kernel 数 |
调用的 Kernel |
ascend |
PTO |
| test_expand.py |
2 |
expand_to_mhc_fwd_tl_ascend / expand_to_mhc_bwd_tl_ascend |
✅ 36 passed |
❌ 36 failed(A) |
| test_head_compute_mix.py |
2 |
mhc_head_compute_mix_fwd_ascend / mhc_head_compute_mix_bwd_ascend |
✅ 4 passed |
❌ 4 failed(A) |
| test_pre_split_mixes.py |
2 |
mhc_pre_split_mixes_fwd_ascend / mhc_pre_split_mixes_bwd_ascend |
✅ 4 passed |
❌ 4 failed(A) |
| test_sinkhorn.py |
2 |
mhc_sinkhorn_fwd_ascend / mhc_sinkhorn_bwd_ascend |
✅ 6 passed |
❌ 6 failed(A) |
| test_pre_apply_mix.py |
2 |
mhc_pre_apply_mix_fwd_ascend / mhc_pre_apply_mix_bwd_ascend |
❌ 12 failed(ascend Bisheng 编译失败:__bfloat1622float2 类型不匹配,详见注¹) |
❌ 12 failed(A) |
| test_post.py |
2 |
mhc_post_fwd / mhc_post_bwd |
❌ 6 failed + 4 error(ascend 拒绝 threads=,详见注²) |
❌ 6 failed + 4 error(B) |
| test_norm_fn.py |
6 |
mhc_gemm_with_sqrsum_fwd_ascend / mhc_gemm_with_sqrsum_bwd / mhc_reduce_partials_and_rmsnorm_fwd / mhc_reduce_partials_and_rmsnorm_bwd / mhc_fn_normw_merge_fwd / mhc_fn_normw_merge_bwd |
❌ 48 failed(ascend:mhc_gemm_with_sqrsum_fwd_ascend 本身能过,失败来自 mhc_reduce_partials_and_rmsnorm_* 的 threads=,详见注³) |
❌ 48 failed(B + C) |
| test_pre_big_fuse.py |
3 |
mhc_gemm_with_sqrsum_fwd_ascend / mhc_gemm_with_sqrsum_bwd / mhc_pre_big_fuse_kernel |
❌ 12 failed(ascend Bisheng compile failed + threads=) |
❌ 12 failed(C) |
| test_multilayer_recompute.py |
1 |
mhc_multilayer_recompute |
❌ 8 error(ascend TIR 构建阶段 TypeError:tir.Buffer 收到 ffi.Function,详见注¹) |
❌ 8 error(A) |
¹ test_pre_apply_mix.py 与 test_multilayer_recompute.py 的 ascend fail 均已抓到完整堆栈(绕开 pytest 的 -p transfer_to_npu segfault,直接调 wrapper 复现):
test_pre_apply_mix.py:mhc_pre_apply_mix_fwd_ascend 在 Bisheng 编译期失败,根因是 kernel body 中 float32 += float32 * cast(bf16→f32) 的 fused multiply-add,TileLang ascend lowering 向量化时生成了 __bfloat1622float2(*(uint1*)(...)),Bisheng 找不到匹配重载:
/tmp/tmpXXX.asc:24:99: error: no matching function for call to '__bfloat1622float2'
/tmp/tmpXXX.asc:31:38: error: assigning to 'uint1' from incompatible type 'bfloat16x2_t'
RuntimeError: Compilation Failed! [bisheng --npu-arch=dav-3510 ...]
归属:tilelang-dsl 的 ascend lowering(bf16→f32 vector cast 代码生成)。其余能过 kernel 均无此 bf16→f32+fma 混合 pattern。
test_multilayer_recompute.py:mhc_multilayer_recompute 是 ptr-list indirection kernel(T.Kernel(n, threads=n_thr),无 ascend 特化版),ascend 端在 TIR 构建阶段 抛 TypeError,非 Bisheng 编译失败:
TypeError: Mismatched type on argument #1 when calling tir.Buffer(...). Expected DataType but got ffi.Function
归属待确认(可能 tilelang-dsl 前端对 T.ptr/ptr-list tensor 的 TIR signature 构造)。
² test_post.py 的 ascend 与 PTO 均为 does not support threads= 前端拒绝(kernel.py:343),ascend / PTO 两侧一致。其余文件中的 benchmark_timer / benchmark_record 相关 error(未安装 pytest-benchmark)与后端能力无关,不计入 codegen 问题归类。
³ test_norm_fn.py ascend 归属更正:原表 1 将该行 ascend fail 标为 Bisheng compile failed + threads=,实测后发现归属需细分——带 _ascend 的 mhc_gemm_with_sqrsum_fwd_ascend 本身能在 ascend 编译通过(经 MHCGemmWithSqrsum.apply 实测 OK);真正报 threads= 错的是不带 _ascend 的 mhc_reduce_partials_and_rmsnorm_fwd/bwd(该 kernel 用了 T.Kernel(num_tokens, threads=n_thr),被前端拒绝)。
⁴ 下表「11 个带 _ascend 后缀的 Kernel 在 ascend 端的实测状态」按 Kernel 粒度复核,全部经原始 test body 真实调用绕开 pytest segfault 复现(device 0,2026-06-24)。两版本对比:pr9 版(issue 复现环境)与主线版 wenbo/asc 6ade682。
⁵ mhc_pre_apply_mix_bwd_ascend 的 no available layout found 详解(主线版 fwd 修好后暴露,pr9 版 bwd 单独调也报同错):
- 失败位置:
tilelang.transform.LayoutInference → LayoutInferencer::Substitute → BufferUseDefCollector::InferInFreeMode → src/transform/layout_inference.cc:1288 的 ICHECK(min_reg_num < INT64_MAX) "no available layout found"。
- 机制:
InferInFreeMode 遍历每个 fragment 作为 infer_root 候选,对每个候选尝试推导完整 layout,期间可能抛 LayoutConflictException(src/op/parallel.cc / src/op/reduce.cc)、LoopLayoutInjectiveException(src/op/parallel.cc:536)、NormalizeIterException(src/layout/layout.cc:630)三种之一;推导成功的才算 reg_num 选最小。所有候选都抛异常 → min_reg_num 保持 INT64_MAX → ICHECK 失败。
- 触发条件:bwd kernel(
pre_apply_mix_kernel.py:189-204)里 og_frag = T.alloc_fragment((h,), T.float32) 被3 个不同维度/访问模式的 T.Parallel 循环复用——①og_frag[i_h]=og_ub[i_h](1维写)、②mgl[i_mhc]+=og_frag[i_h]*...(2维 reduce 读)、③xg_ub[i_mhc,i_h]=mix[..]*og_frag[i_h](2维 elementwise 读)。三种访问对 fragment 的线程铺维要求互相矛盾,选任何 layout 都让某个循环触发冲突。
- 对比 fwd(能过):只有 1 个 fragment
ol,只在 1 个 T.Parallel 循环里访问,不存在跨循环复用冲突。
- 归属:tilelang-dsl 的
LayoutInference pass(src/transform/layout_inference.cc + src/op/parallel.cc + src/layout/layout.cc),是通用 pass(tilelang.transform. 前缀,非 ascend 特化),对"单 fragment 跨多循环、多维度访问模式复用"推导无解。kernel 写法本身是 Ascend 常见的寄存器复用优化(注释明说 "Fragment trick for og eliminates repeated UB loads"),属 DSL 能力限制而非 kernel 源码错误。两版本(pr9 / 主线)的 LayoutInference 实现一致,故 bwd 都挂。
表1.5:11 个带 _ascend 后缀的 Kernel 在 ascend 端的实测状态(pr9 版 vs 主线版)
注:以下 11 个是 tile_kernels/mhc/*_kernel.py 中 def *_ascend(...) 真正定义的 kernel(wrapper 层 _ascend 转发不算)。全部经原始 test body 真实调用、绕开 pytest -p transfer_to_npu 的 segfault、直接调 wrapper 复现(device 0,TILELANG_TARGET=ascend,2026-06-24)。
| # |
Kernel |
归属 test 文件 |
pr9 版 ascend |
主线版 ascend |
说明 |
| 1 |
expand_to_mhc_fwd_tl_ascend |
test_expand.py |
✅ |
✅ |
— |
| 2 |
expand_to_mhc_bwd_tl_ascend |
test_expand.py |
✅ |
✅ |
— |
| 3 |
mhc_head_compute_mix_fwd_ascend |
test_head_compute_mix.py |
✅ |
✅ |
— |
| 4 |
mhc_head_compute_mix_bwd_ascend |
test_head_compute_mix.py |
✅ |
✅ |
— |
| 5 |
mhc_pre_split_mixes_fwd_ascend |
test_pre_split_mixes.py |
✅ |
✅ |
— |
| 6 |
mhc_pre_split_mixes_bwd_ascend |
test_pre_split_mixes.py |
✅ |
✅ |
— |
| 7 |
mhc_sinkhorn_fwd_ascend |
test_sinkhorn.py |
✅ |
✅ |
— |
| 8 |
mhc_sinkhorn_bwd_ascend |
test_sinkhorn.py |
✅ |
✅ |
— |
| 9 |
mhc_gemm_with_sqrsum_fwd_ascend |
test_norm_fn.py |
✅ |
✅ |
走 MHCGemmWithSqrsum.apply 实测 OK;原表 1 误标为 ascend fail,已更正(见注³) |
| 10 |
mhc_pre_apply_mix_fwd_ascend |
test_pre_apply_mix.py |
❌ Bisheng 编译失败 |
✅ 编译+运行通过 |
测试方法:因跑完整 pytest test_pre_apply_mix.py 会 segfault、且 wrapper 是 fwd→bwd 顺序(fwd 挂就停),故用隔离 probe 单独验证——①直接调底层 mhc_pre_apply_mix_fwd_ascend(带 wrapper 真实参数 h_blk=256);②mhc_pre_apply_mix(x,mix) 在 torch.no_grad() 下只走 forward。两步均 OK(sum=655360)。结论:fwd 能过。pr9 失败原因:bf16→f32 vector cast 生成 __bfloat1622float2(*(uint1*)(...)),Bisheng 找不到重载(详见注¹)。主线版已修:codegen 改用 PrintVectorizedCast 显式约束 src 类型为 bfloat16x2_t(codegen_ascend.cc 从 src/target/ 重构到 src/ascend/) |
| 11 |
mhc_pre_apply_mix_bwd_ascend |
test_pre_apply_mix.py |
❌(pr9 fwd 先挂,bwd 走不到) |
❌ no available layout found |
测试方法:tilelang 的 @tilelang.jit 是每个 kernel 函数独立编译的(fwd/bwd 互不依赖),故用隔离 probe 单独调 mhc_pre_apply_mix_bwd_ascend(og,x,mix,xg,num_sms,n_thr=512,h_blk=512),完全不碰 fwd,3 次均确定性失败。另测"fwd 先跑成功→再调 bwd"结果仍 FAIL,证明 bwd 失败与 fwd 无关。结论:bwd 不能过。失败位置:LayoutInference pass 的 InferInFreeMode 对 og_frag 跨 3 个 T.Parallel 循环(1维写/2维reduce读/2维elementwise读)复用推导无解,min_reg_num 保持 INT64_MAX(详见注⁵)。两版本 bwd 均独立失败(pr9 单独调 bwd 也报同样 layout 错) |
结论:
- pr9 版:11 个中 9 个通过,2 个失败(
mhc_pre_apply_mix_fwd/bwd_ascend)——fwd 卡 Bisheng bf16 cast,bwd 卡 layout 推导(但 fwd 先挂,bwd 实际走不到)。
- 主线版:11 个中 10 个通过,仅
mhc_pre_apply_mix_bwd_ascend 1 个失败。主线版修好了 fwd 的 bf16 cast codegen 问题,但 bwd 的 layout 推导问题两版本都没修,是 tilelang-dsl LayoutInference pass 的能力限制(见注⁵)。
- 归属:fwd 问题(已修)在 tilelang-dsl ascend codegen;bwd 问题(未修)在 tilelang-dsl
tilelang.transform.LayoutInference(src/transform/layout_inference.cc + src/op/parallel.cc),非 PTOAS、非 tile-kernels kernel 源码。
表2:PTO 问题分类(按 Kernel 聚类)
类别 A:CodeGenPTO 不支持 tir.shift_right
tvm.error.InternalError: Unsupported call: Op(tir.shift_right)
<unknown>:0: InternalError
in tvm::codegen::CodeGenPTO::VisitExpr_(tvm::tir::CallNode const*)
in tvm::codegen::CodeGenPTO::VisitStmt_(tvm::tir::AllocateNode / DeclBufferNode / AttrStmtNode / ForNode const*)
- 受影响 Kernel:
expand_to_mhc_fwd_tl_ascend / expand_to_mhc_bwd_tl_ascend
mhc_head_compute_mix_fwd_ascend / mhc_head_compute_mix_bwd_ascend
mhc_pre_split_mixes_fwd_ascend / mhc_pre_split_mixes_bwd_ascend
mhc_sinkhorn_fwd_ascend / mhc_sinkhorn_bwd_ascend
mhc_pre_apply_mix_fwd_ascend / mhc_pre_apply_mix_bwd_ascend
mhc_gemm_with_sqrsum_fwd_ascend / mhc_gemm_with_sqrsum_bwd(norm_fn 的 GEMM 部分)
mhc_multilayer_recompute
- 受影响 test 文件:test_expand.py / test_head_compute_mix.py / test_pre_split_mixes.py / test_sinkhorn.py / test_pre_apply_mix.py / test_norm_fn.py(部分)/ test_multilayer_recompute.py
- 复现:
TILELANG_TARGET=pto PYTEST_ADDOPTS="-p torch_npu.contrib.transfer_to_npu" python -c "import torch,torch_npu;torch.npu.set_device(0);torch.zeros(1,device=0);torch.npu.synchronize();from tile_kernels.config import get_device_num_sms,get_num_sms;get_device_num_sms.cache_clear();import pytest,sys;sys.exit(pytest.main(['-q','-p','no:cacheprovider']+sys.argv[1:]))" test_sinkhorn.py
- 关键观察:
shift_right 不在这些 kernel 的源码中直接出现,而是 TileLang lowering 阶段生成(索引计算 / 树形归约 lowering 产生 tir.shift_right),CodeGenPTO::VisitExpr_(CallNode) 未注册对应 handler。归属可能在 PTOAS(codegen 补 visitor)或 tilelang-dsl(lowering 避免生成 tir.shift_right)。
类别 B:PTO 后端不接受 T.Kernel(..., threads=)
ValueError: Ascend backend does not support `threads=` in `T.Kernel(...)`. Use `T.SimtVF(threads=...)` to define thread domains.
/home/wangmiao/tilelang-simtvf-pr9-buildable/tilelang/language/kernel.py:343: ValueError
- 受影响 Kernel:
mhc_post_fwd / mhc_post_bwd
mhc_reduce_partials_and_rmsnorm_fwd / mhc_reduce_partials_and_rmsnorm_bwd(norm_fn 的 reduce/RMSNorm 部分)
- 受影响 test 文件:test_post.py / test_norm_fn.py(reduce 部分)
- 复现:
TILELANG_TARGET=pto PYTEST_ADDOPTS="-p torch_npu.contrib.transfer_to_npu" python -c "import torch,torch_npu;torch.npu.set_device(0);torch.zeros(1,device=0);torch.npu.synchronize();from tile_kernels.config import get_device_num_sms,get_num_sms;get_device_num_sms.cache_clear();import pytest,sys;sys.exit(pytest.main(['-q','-p','no:cacheprovider']+sys.argv[1:]))" test_post.py
- 说明:错误信息已建议改用
T.SimtVF(threads=...)。需确认这是 PTO 后端能力边界(永远不支持 threads=),还是 tilelang-dsl/PTOAS 可放宽。
类别 C:CodeGenPTO 不支持 AllocateNode scope 'local.var'
tvm.error.InternalError: Check failed: (false) is false: AllocateNode scope 'local.var' not yet supported; only UB (shared/shared.dyn) is supported
<unknown>:0: InternalError
- 受影响 Kernel:
mhc_pre_big_fuse_kernel
mhc_reduce_partials_and_rmsnorm_fwd / mhc_reduce_partials_and_rmsnorm_bwd(norm_fn 的 reduce/RMSNorm 部分,实测 test_norm_fn.py pto 命中 local.var)
- 受影响 test 文件:test_pre_big_fuse.py / test_norm_fn.py(部分)
- 复现:
TILELANG_TARGET=pto PYTEST_ADDOPTS="-p torch_npu.contrib.transfer_to_npu" python -c "import torch,torch_npu;torch.npu.set_device(0);torch.zeros(1,device=0);torch.npu.synchronize();from tile_kernels.config import get_device_num_sms,get_num_sms;get_device_num_sms.cache_clear();import pytest,sys;sys.exit(pytest.main(['-q','-p','no:cacheprovider']+sys.argv[1:]))" test_pre_big_fuse.py
- 关键观察:
local.var 来自 fragment 级别内存分配的 lowering。错误信息表明 PTO 后端目前只支持 UB(shared/shared.dyn)scope,local.var 未支持。归属可能在 PTOAS(codegen 支持更多 buffer scope)或 tilelang-dsl(lowering 时将 local.var 提升到 UB)。
归属待确认的问题
| 类别 |
问题 |
可能归属 |
待确认 |
| A |
tir.shift_right 未支持 |
PTOAS(补 visitor)/ tilelang-dsl(lowering 避免) |
shift_right 是 lowering 生成还是 kernel 源码直接写? |
| B |
T.Kernel(threads=) 被前端拒绝 |
tilelang-dsl(语义边界)/ tile-kernels(改用 SimtVF)/ PTOAS(支持 threads=) |
PTO 是否计划支持 threads=? |
| C |
local.var scope 未支持 |
PTOAS(支持更多 scope)/ tilelang-dsl(lowering 提升到 UB)/ tile-kernels(改用 UB 分配) |
local.var 是否计划支持?(norm_fn reduce kernel 实测同时命中 B/C) |
期望
希望确认类别 A、B、C 属于哪一层:
- 类别 A:若属 PTOAS codegen 能力补齐,请指认需要补的 visitor;若属 tilelang-dsl lowering 应避免的 pattern,请转移。
- 类别 B:
threads= 是否 PTO 后端永远不支持、必须走 SimtVF?还是可放宽?
- 类别 C:
local.var 是否计划支持?或应改用 UB 分配?(实测 test_norm_fn.py pto 同时命中 threads= 与 local.var,说明 norm_fn 的 reduce kernel 既有 T.Kernel(threads=) 又有 fragment 分配。)
谢谢!
背景
在 Ascend A5(Ascend950PR_9589)板卡上,对
examples/ascend_mhc下的 MHC(Mixture-of-Hyper-Channel)算子测试集做 ascend 原生后端 vs PTO 后端的对比验证时,发现 PTO 后端 (TILELANG_TARGET=pto) 在多个测试文件上无法完成编译/运行。本 issue 按会议要求重新组织:不以 test 文件为最小归类单位(不同 test 可能调用同类 Kernel,存在同类问题),改为以 Kernel 为粒度归类。包含两张表:
本 issue 不预设责任归属,只汇总 ascend pass/fail + PTO 问题归类 + 复现步骤,供判断属于 PTOAS / tilelang-dsl / tile-kernels 哪一层。
环境
vector_core_num=64,cube_core_num=32);device 1 在连续负载下易 segfault,device 0 更稳定rp21-PT2.7(python 3.10,torch 2.7.1+cpu + torch_npu)/home/wenquan/cann29/cann-9.0.0/home/wangmiao/tilelang-simtvf-pr9-buildable(dev build)/home/wangmiao/PTOAS-main-1df3fba/install/bin/ptoas/home/ptoas-board-monitor-a5/llvm-project-vpto-feature/build-shared/home/wangmiao/tile-kernels/home/wangmiao/tilelang-simtvf-pr9-buildable/examples/ascend_mhc复现步骤
表1:每个 test 文件的 Kernel 数量与 ascend / PTO 状态
expand_to_mhc_fwd_tl_ascend/expand_to_mhc_bwd_tl_ascendmhc_head_compute_mix_fwd_ascend/mhc_head_compute_mix_bwd_ascendmhc_pre_split_mixes_fwd_ascend/mhc_pre_split_mixes_bwd_ascendmhc_sinkhorn_fwd_ascend/mhc_sinkhorn_bwd_ascendmhc_pre_apply_mix_fwd_ascend/mhc_pre_apply_mix_bwd_ascend__bfloat1622float2类型不匹配,详见注¹)mhc_post_fwd/mhc_post_bwdthreads=,详见注²)mhc_gemm_with_sqrsum_fwd_ascend/mhc_gemm_with_sqrsum_bwd/mhc_reduce_partials_and_rmsnorm_fwd/mhc_reduce_partials_and_rmsnorm_bwd/mhc_fn_normw_merge_fwd/mhc_fn_normw_merge_bwdmhc_gemm_with_sqrsum_fwd_ascend本身能过,失败来自mhc_reduce_partials_and_rmsnorm_*的threads=,详见注³)mhc_gemm_with_sqrsum_fwd_ascend/mhc_gemm_with_sqrsum_bwd/mhc_pre_big_fuse_kernelBisheng compile failed+threads=)mhc_multilayer_recomputetir.Buffer收到ffi.Function,详见注¹)表1.5:11 个带
_ascend后缀的 Kernel 在 ascend 端的实测状态(pr9 版 vs 主线版)expand_to_mhc_fwd_tl_ascendexpand_to_mhc_bwd_tl_ascendmhc_head_compute_mix_fwd_ascendmhc_head_compute_mix_bwd_ascendmhc_pre_split_mixes_fwd_ascendmhc_pre_split_mixes_bwd_ascendmhc_sinkhorn_fwd_ascendmhc_sinkhorn_bwd_ascendmhc_gemm_with_sqrsum_fwd_ascendMHCGemmWithSqrsum.apply实测 OK;原表 1 误标为 ascend fail,已更正(见注³)mhc_pre_apply_mix_fwd_ascendpytest test_pre_apply_mix.py会 segfault、且 wrapper 是 fwd→bwd 顺序(fwd 挂就停),故用隔离 probe 单独验证——①直接调底层mhc_pre_apply_mix_fwd_ascend(带 wrapper 真实参数h_blk=256);②mhc_pre_apply_mix(x,mix)在torch.no_grad()下只走 forward。两步均 OK(sum=655360)。结论:fwd 能过。pr9 失败原因:bf16→f32 vector cast 生成__bfloat1622float2(*(uint1*)(...)),Bisheng 找不到重载(详见注¹)。主线版已修:codegen 改用PrintVectorizedCast显式约束 src 类型为bfloat16x2_t(codegen_ascend.cc从src/target/重构到src/ascend/)mhc_pre_apply_mix_bwd_ascendno available layout found@tilelang.jit是每个 kernel 函数独立编译的(fwd/bwd 互不依赖),故用隔离 probe 单独调mhc_pre_apply_mix_bwd_ascend(og,x,mix,xg,num_sms,n_thr=512,h_blk=512),完全不碰 fwd,3 次均确定性失败。另测"fwd 先跑成功→再调 bwd"结果仍 FAIL,证明 bwd 失败与 fwd 无关。结论:bwd 不能过。失败位置:LayoutInferencepass 的InferInFreeMode对og_frag跨 3 个T.Parallel循环(1维写/2维reduce读/2维elementwise读)复用推导无解,min_reg_num保持 INT64_MAX(详见注⁵)。两版本 bwd 均独立失败(pr9 单独调 bwd 也报同样 layout 错)结论:
mhc_pre_apply_mix_fwd/bwd_ascend)——fwd 卡 Bisheng bf16 cast,bwd 卡 layout 推导(但 fwd 先挂,bwd 实际走不到)。mhc_pre_apply_mix_bwd_ascend1 个失败。主线版修好了 fwd 的 bf16 cast codegen 问题,但 bwd 的 layout 推导问题两版本都没修,是 tilelang-dslLayoutInferencepass 的能力限制(见注⁵)。tilelang.transform.LayoutInference(src/transform/layout_inference.cc+src/op/parallel.cc),非 PTOAS、非 tile-kernels kernel 源码。表2:PTO 问题分类(按 Kernel 聚类)
类别 A:
CodeGenPTO不支持tir.shift_rightexpand_to_mhc_fwd_tl_ascend/expand_to_mhc_bwd_tl_ascendmhc_head_compute_mix_fwd_ascend/mhc_head_compute_mix_bwd_ascendmhc_pre_split_mixes_fwd_ascend/mhc_pre_split_mixes_bwd_ascendmhc_sinkhorn_fwd_ascend/mhc_sinkhorn_bwd_ascendmhc_pre_apply_mix_fwd_ascend/mhc_pre_apply_mix_bwd_ascendmhc_gemm_with_sqrsum_fwd_ascend/mhc_gemm_with_sqrsum_bwd(norm_fn 的 GEMM 部分)mhc_multilayer_recomputeTILELANG_TARGET=pto PYTEST_ADDOPTS="-p torch_npu.contrib.transfer_to_npu" python -c "import torch,torch_npu;torch.npu.set_device(0);torch.zeros(1,device=0);torch.npu.synchronize();from tile_kernels.config import get_device_num_sms,get_num_sms;get_device_num_sms.cache_clear();import pytest,sys;sys.exit(pytest.main(['-q','-p','no:cacheprovider']+sys.argv[1:]))" test_sinkhorn.pyshift_right不在这些 kernel 的源码中直接出现,而是 TileLang lowering 阶段生成(索引计算 / 树形归约 lowering 产生tir.shift_right),CodeGenPTO::VisitExpr_(CallNode)未注册对应 handler。归属可能在 PTOAS(codegen 补 visitor)或 tilelang-dsl(lowering 避免生成tir.shift_right)。类别 B:PTO 后端不接受
T.Kernel(..., threads=)mhc_post_fwd/mhc_post_bwdmhc_reduce_partials_and_rmsnorm_fwd/mhc_reduce_partials_and_rmsnorm_bwd(norm_fn 的 reduce/RMSNorm 部分)TILELANG_TARGET=pto PYTEST_ADDOPTS="-p torch_npu.contrib.transfer_to_npu" python -c "import torch,torch_npu;torch.npu.set_device(0);torch.zeros(1,device=0);torch.npu.synchronize();from tile_kernels.config import get_device_num_sms,get_num_sms;get_device_num_sms.cache_clear();import pytest,sys;sys.exit(pytest.main(['-q','-p','no:cacheprovider']+sys.argv[1:]))" test_post.pyT.SimtVF(threads=...)。需确认这是 PTO 后端能力边界(永远不支持threads=),还是 tilelang-dsl/PTOAS 可放宽。类别 C:
CodeGenPTO不支持AllocateNode scope 'local.var'mhc_pre_big_fuse_kernelmhc_reduce_partials_and_rmsnorm_fwd/mhc_reduce_partials_and_rmsnorm_bwd(norm_fn 的 reduce/RMSNorm 部分,实测 test_norm_fn.py pto 命中local.var)TILELANG_TARGET=pto PYTEST_ADDOPTS="-p torch_npu.contrib.transfer_to_npu" python -c "import torch,torch_npu;torch.npu.set_device(0);torch.zeros(1,device=0);torch.npu.synchronize();from tile_kernels.config import get_device_num_sms,get_num_sms;get_device_num_sms.cache_clear();import pytest,sys;sys.exit(pytest.main(['-q','-p','no:cacheprovider']+sys.argv[1:]))" test_pre_big_fuse.pylocal.var来自 fragment 级别内存分配的 lowering。错误信息表明 PTO 后端目前只支持 UB(shared/shared.dyn)scope,local.var未支持。归属可能在 PTOAS(codegen 支持更多 buffer scope)或 tilelang-dsl(lowering 时将local.var提升到 UB)。归属待确认的问题
tir.shift_right未支持T.Kernel(threads=)被前端拒绝local.varscope 未支持期望
希望确认类别 A、B、C 属于哪一层:
threads=是否 PTO 后端永远不支持、必须走SimtVF?还是可放宽?local.var是否计划支持?或应改用 UB 分配?(实测 test_norm_fn.py pto 同时命中threads=与local.var,说明 norm_fn 的 reduce kernel 既有T.Kernel(threads=)又有 fragment 分配。)谢谢!