Pull Request已成功合入, 合并人@CANN-robot
(感谢 xuyafei 的贡献)变更摘要
此 PR 主要围绕 CV Fusion(Cube-Vector 融合)场景下代码生成的 dtype 感知对齐 展开,核心是引入一套基于 IsCVFusionStage / GenBlockAlignNExpr / GetCVAlignedSize 的工具函数,在多个 API 调用生成路径(Compare、Where、LogicalNot、Cast、Unary 等)中,针对 CV 融合阶段将 actual_size 替换为按 32 字节对齐边界向上对齐后的表达式。同时,对 Tiling 代码生成进行了大规模重构,将 GenTilingFuncForInductor 拆分为多个子函数,引入共享 CV wrapper SO 的编译缓存机制,并为 V35 的 Register API Call 新增 CvApi2DParams 二维参数生成逻辑。
主要改动
-
新增 CV 融合对齐工具函数:在
api_call_utils.cpp/h中新增IsCVFusionStage、GenBlockAlignNExpr、GetCVAlignedSize等函数,根据 tensor 的 dtype 计算 32 字节对齐的 size 表达式(((n + align - 1) / align * align)),供各 API 调用生成路径复用。 -
Elewise API Call 对齐适配:
compare_api_call.cpp、where_api_call.cpp、logical_not_api_call.cpp、unary_api_tmp_call.cpp、unary_bitwidth_change_api_call.cpp等文件的Generate方法中,将原本直接使用的x.actual_size/tpipe.tiler.ActualSize(param.cal_count)替换为通过GetCVAlignedSize/GenBlockAlignNExpr计算的对齐表达式,仅在 CV 融合阶段生效。 -
Tiling 代码生成重构:在
codegen_tiling.cpp/h中将GenTilingFuncForInductor拆分为GenInductorShapeDim、GenCallCubeTilingForInductor、GenPlainInductorTilingTail等子函数;cube_kernel_tiling_wrapper.h大幅精简(+928/-1208 行);PrepareMatMulAttrs中opImplMode改为固定值1而非使用cube_info.enable_hf32。 -
Python 编译系统引入共享 CV Wrapper SO 缓存:
ascendc_compile.py新增is_cv_wrapper_source、ensure_shared_cv_wrapper_so、prepare_shared_cv_wrapper等函数,将cube_kernel_tiling_wrapper.cpp编译为独立的.so文件并基于内容哈希缓存至cv_tiling_wrapper_cache目录,支持文件锁并发的首次编译保护。 -
V35 Register API Call 新增 CV 融合 2D 参数生成:在
reg_api_call_utils.cpp/h中新增CvApi2DParams结构体及BuildCvApi2DParams、GenCvUint32Dims、GenCvUint16Stride等函数;cast_v2_api_call.cpp、compare_v2_api_call.cpp、floor_to_int_api_call.cpp、round_to_int_api_call.cpp、trunc_to_int_api_call.cpp新增 CV 融合分支,使用 2D dims/strides 替代原先的 1D 标量形式。


/lgtm


描述
一、主要解决的问题
1.1 CV tiling wrapper 重复编译
Inductor CV fusion 场景会生成主 tiling 源文件和 cube tiling wrapper 源文件。原流程在 host/device 链接链路中会随每次编译重新处理 wrapper 源文件,
AutofuseDoCubeMatMulTiling等 wrapper 实现会重复参与 host 编译,增加编译耗时。本次将 CV tiling wrapper 编译为可复用 shared object,并按 wrapper 源码、CANN 路径、平台架构、SoC、编译选项等生成缓存 key,避免相同 wrapper 在同一缓存根目录下重复编译。
1.2 非 CV 编译链路可能被 stale shared wrapper 状态污染
shared_cv_wrapper_so是 CV wrapper 复用流程的中间状态。如果同一个编译参数对象或流程边界中残留该字段,非 CV host/device 链接不应追加 CV wrapper so,也不应切换到 CV 专用链接库。本次补充非 CV 边界保护,确保 shared CV wrapper 只在
CVAutofuseTilingData相关编译中生效。1.3 CV wrapper cache 目录清理策略
static_shape_kernel_proc会清理临时目录。为了让 wrapper 编译产物可跨重编译阶段复用,需要保留cv_tiling_wrapper_cache,避免静态 shape 重编译阶段误删缓存。1.4 CV 融合位宽/精度转换
CV fusion 场景中,Cast、RoundToInt、TruncToInt、FloorToInt 等位宽转换算子需要同时处理
float16、bfloat16、float32、int32等不同输入/输出精度。原代码复用普通向量路径的一维actual_size和默认 stride,未按 CV stage 的二维curAivM/curAivN以及 dtype 位宽计算对齐,可能导致不同位宽转换链路中的 Cast 参数、DataCopy stride 或 RemovePad/GatherMask 处理不一致,进而影响转换精度和访存正确性。本次补齐 CV stage 下的 dtype-aware dims/stride 生成逻辑:统一按
curAivM/curAivN生成二维 Cast 参数,按 tensor dtype 计算 block-aligned N 方向 stride,并区分 UBFuse 与 fallback 路径处理 DataCopy。UBFuse 路径使用 dtype 对齐后的 load/store 参数并跳过不必要的 RemovePad;fallback 路径继续针对 1/2/4 字节类型生成 GatherMask 去 padding 逻辑,保证低位宽与高位宽数据在拷入、计算和拷出链路中的对齐语义一致。1.5 本次采用的性能优化手段
libautofuse_cv_tiling_wrapper_<hash>.so后,相同 wrapper 输入只在首次命中时编译一次,后续 host/device 链接直接复用缓存 so,减少重复 host 编译开销。cube_kernel_tiling_wrapper.cpp和 split 后的*_tiling_func_BCubeKernelTilingWrapperCpp.cpp,将 wrapper 从普通 host source 列表中剥离。主 tiling 文件继续按图编译,wrapper 走共享 so 链接,降低单次 host 编译需要处理的源码规模。.lock文件保护首次构建流程。只有一个任务负责编译并原子替换最终 so,其他任务等待后复用结果,避免并发场景下重复编译和部分写入风险。cv_tiling_wrapper_cache可以让首次编译生成的 wrapper so 在后续重编译阶段继续复用,避免 recompile 阶段再次构建相同 wrapper。prepare_shared_cv_wrapper和append_shared_cv_wrapper_so都以is_cv_fusion_compile(args)为边界。非 CV 编译不扫描、不编译、不链接 shared CV wrapper so,也不切换到nnopbase链接库,避免对普通 Autofuse 编译路径引入额外负担。二、修改方案
2.1 抽离并复用 CV tiling wrapper 编译产物
cube_kernel_tiling_wrapper.cpp和 split 后的*_tiling_func_BCubeKernelTilingWrapperCpp.cpp。get_shared_cv_wrapper_so_path,基于 wrapper 源码内容、CANN 安装路径、平台架构、SoC、编译选项、stage 生成稳定缓存文件名。ensure_shared_cv_wrapper_so,首次编译生成libautofuse_cv_tiling_wrapper_<hash>.so,后续命中缓存直接复用。CV_HOST_LINK_LIBRARIES,包含nnopbase。2.2 收敛 CV wrapper 对非 CV 流程的影响范围
prepare_shared_cv_wrapper仅在is_cv_fusion_compile(args)为 true 时拆出 wrapper 源文件。append_shared_cv_wrapper_so仅在 CV 编译中追加 shared wrapper so。HOST_LINK_LIBRARIES。2.3 补齐 opbase 头文件路径
pkg_inc根目录和 machine-specificpkg_inc根目录。pkg_inc/base优先于 genericpkg_inc/base,优先使用当前架构安装态头文件。2.4 保留 wrapper cache 目录
clean_before_modify保留cv_tiling_wrapper_cache,避免静态 shape 重编译清理缓存。三、代码修改流程图
flowchart LR A[host_files 输入] ==> B{是否 CV fusion} B ==>|否| C[按原流程编译全部 host 源文件] B ==>|是| D[识别 cube wrapper 源文件] D ==> E{缓存 so 是否存在} E ==>|是| F[复用 libautofuse_cv_tiling_wrapper_<hash>.so] E ==>|否| G[文件锁保护首次编译 wrapper so] F ==> H[主 tiling object + wrapper so 链接] G ==> H C ==> I[非 CV host/device 链接不追加 wrapper so]变更类型
关联的Issue
无。
如何测试
一、测试用例说明
1.1 Python 单元测试
test_compile_host_objs_skips_shared_cv_wrapper_source:验证 CV wrapper 源文件不再作为普通 host object 编译,改为生成 shared wrapper so。test_compile_host_objs_skips_split_shared_cv_wrapper_source:验证 split 文件名BCubeKernelTilingWrapperCpp也会走 shared wrapper 复用流程。test_ensure_shared_cv_wrapper_so_reuses_existing_so:验证命中缓存时不重复编译 wrapper。test_ensure_shared_cv_wrapper_so_serializes_concurrent_first_compile:验证并发首次编译通过文件锁串行化,只生成一次 wrapper so。test_build_device_so_ignores_shared_cv_wrapper_so_for_non_cv_compile:验证非 CV device 链接不会追加 stale shared CV wrapper so。test_link_host_target_ignores_shared_cv_wrapper_so_for_non_cv_compile:验证非 CV host 链接不会追加 stale shared CV wrapper so。test_clean_before_modify_keeps_shared_cv_wrapper_cache:验证静态 shape 重编译清理流程保留 wrapper cache。pkg_inc路径和 include 优先级。1.2 C++ codegen 单元测试
GenerateForInductorCvFusionShouldEmitCvTilingAndCubeWrapper:验证 CV fusion 仍生成主 tiling 和 cube wrapper 文件。GenerateForInductorCvFusionShouldCacheActualMatmulTilingBytes:验证 CV tiling 主流程仍保留 matmul tiling bytes 缓存逻辑。CubeWrapper*:验证 wrapper 源码结构、cache key、compile info、runtime shape fallback、tiling scratch 复用等关键行为。核对清单
其他信息
影响范围
注意事项