ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

PyPTO TransMode 详解:FP32 矩阵乘使能 TF32 计算的舍入模式控制

PyPTO TransMode 详解:FP32 矩阵乘使能 TF32 计算的舍入模式控制 PyPTO TransMode 详解FP32 矩阵乘使能 TF32 计算的舍入模式控制【免费下载链接】pyptoPyPTO发音: pai p-t-oParallel Tensor/Tile Operation编程范式。项目地址: https://gitcode.com/cann/pypto导读TransMode 是 PyPTO 中用于控制矩阵乘matmul场景下 FP32 数据向 TF32 数据转换行为的枚举类型。当 matmul 的输入输出矩阵均为 FP32 时通过extend_params传入trans_mode即可使能 TF32 计算并选择转换舍入模式以更少的尾数位换取硬件计算量的降低。读完本文你将掌握 TransMode 的完整语义、支持的产品范围、舍入模式差异以及它在 PyPTO Python 前端、C 算子实现与代码生成层中的完整调用链路。产品支持情况TransMode 所控制的 TF32 计算能力与硬件架构强相关不同产品上的支持情况如下产品TransMode 支持情况Ascend 950PR / Ascend 950DT支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品不支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品不支持该支持范围与 Python 前端的运行时校验逻辑完全一致在 matmul.py 的__validate_trans_mode中当检测到 A2/A3 架构DAV_1001、DAV_2201时会直接抛出ValueError提示trans_mode参数仅在 Ascend 950 上受支持。因此在 A2/A3 平台上TransMode 只能保持默认值CAST_NONE即不使能 TF32 转换。功能说明在 matmul 的输入输出矩阵均为 FP32 数据类型的场景下TransMode 用于设置两件事是否使能 TF32 计算使能后矩阵乘计算过程中 FP32 数据会被转换为 TF32 数据类型参与运算使能 TF32 的舍入模式FP32 → TF32 的精度收窄过程需要确定舍入策略。为什么使用 TF32TF32Tensor Float 32采用1 个符号位 8 个指数位 10 个尾数位共 19 位参与计算。相比 FP32 的 23 位尾数TF32 的尾数位更少收益减少硬件计算量加速矩阵乘运算代价尾数位减少会带来精度损失。从实现上看TF32 保留了与 FP32 相同的 8 位指数因此其数值范围与 FP32 基本一致损失主要集中在尾数精度上。这使 TF32 成为大模型训练与推理中以少量精度换显著吞吐的常用手段。输入数据格式不变需要特别强调的是使能 TF32 后输入数据的存储格式仍然是 FP32TF32 转换发生在计算流水内部。TransMode 参数只决定 FP32 到 TF32 转换时的舍入模式而不会改变用户侧 Tensor 的数据类型声明。原型定义TransMode 在 PyPTO 中以 Python 枚举形式暴露完整定义如下与 TransMode.md 中的原型定义一致class TransMode(enum.Enum): CAST_NONE ... # 不使能float数据类型转换为TF32数据类型 CAST_RINT ... # 舍入到最近整数中间值时舍入到偶数 CAST_ROUND ... # 舍入到最近整数中间值时远离零舍入枚举值语义枚举值语义典型用途CAST_NONE不使能 float 类型到 TF32 的转换默认值FP32 matmul 按常规精度计算CAST_RINT舍入到最近整数中间值时舍入到偶数tie-to-even需要更小的系统性舍入偏差时选用遵循 IEEE 754 默认舍入语义CAST_ROUND舍入到最近整数中间值时远离零舍入tie-away-from-zero一般场景的推荐模式PyPTO matmul 官方示例默认使用其中CAST_ROUND是官方文档明确推荐的一般情况默认模式。从 matmul.py 的 TF32 示例可以看出PyPTO 在 TF32 矩阵乘的演示代码中默认采用pypto.TransMode.CAST_ROUND。使用方式TransMode 通过pypto.matmul的extend_params字典传入键名为trans_modeimport pypto # FP32 输入矩阵 a pypto.tensor((16, 32), pypto.DT_FP32, tensor_a) b pypto.tensor((32, 64), pypto.DT_FP32, tensor_b) # 使能 TF32采用 CAST_ROUND 舍入模式 extend_params {trans_mode: pypto.TransMode.CAST_ROUND} c pypto.matmul(a, b, pypto.DT_FP32, extend_paramsextend_params)该示例与 matmul.py 中的官方 TF32 示例一致输入输出均为DT_FP32通过extend_params{trans_mode: pypto.TransMode.CAST_ROUND}使能 TF32 计算。extend_params 中的默认值在 __convert_matmul_extend_params 中extend_params会执行统一的默认值补全extend_params.setdefault(trans_mode, pypto_impl.TransMode.CAST_NONE)即用户不传trans_mode时框架默认采用CAST_NONEFP32 matmul 不会发生 TF32 转换。校验规则Python 前端在 __validate_trans_mode 中对trans_mode施加两条硬性约束数据类型约束当trans_mode ! CAST_NONE时两个输入矩阵的数据类型必须为DT_FP32否则抛出RuntimeErrorThe trans_mode parameter is only supported when input data type is DT_FP32架构约束当trans_mode ! CAST_NONE且当前 NPU 架构为 A2/A3DAV_1001、DAV_2201时抛出ValueErrorThe trans_mode parameter is not supported on A2/A3 platforms, only supported on Ascend 950。这两条约束与文档中产品支持情况及FP32 输入输出场景的描述完全对应也意味着CAST_NONE是唯一在任意架构、任意输入类型下均合法的取值。舍入模式的精度语义CAST_RINT与CAST_ROUND均属于舍入到最近整数二者的差异仅在于中间值恰好落在两个可表示值正中的处理CAST_RINTtie-to-even中间值舍入到最近的偶数尾数。该模式不会引入系统性的单向偏差是 IEEE 754 默认的舍入方式CAST_ROUNDtie-away-from-zero中间值向远离零的方向舍入。该模式在中间值处理上更为直接但会引入微小的系统性偏差。具体到二进制舍入行为可参考仓库中 CastMode.md 对同类舍入模式的位级描述CAST_RINT若待舍入部分的第一位为 0则不进位若第一位为 1 且后续位不全为 0则进位若第一位为 1 且后续位全为 0当尾数最后一位为 0 则不进位、为 1 则进位CAST_ROUND若待舍入部分的第一位为 0则不进位否则进位。注意CastMode 是更通用的数据类型转换舍入枚举涵盖 FLOOR/CEIL/TRUNC/ODD 等更多模式而 TransMode 是 TF32 转换专用枚举仅开放CAST_NONE/CAST_RINT/CAST_ROUND三个取值两者不要混用。源码实现与调用链路Python 枚举的绑定TransMode 在 enum.py 中直接重导出底层绑定类型TransMode pypto_impl.TransMode底层 C 枚举通过 pybind11 绑定到 Python 层见 python/src/bindings/enum.cpppy::enum_Matrix::TransMode(m, TransMode) .value(CAST_NONE, Matrix::TransMode::CAST_NONE) .value(CAST_RINT, Matrix::TransMode::CAST_RINT) .value(CAST_ROUND, Matrix::TransMode::CAST_ROUND)C 侧的Matrix::TransMode定义于 tilefwk_op.h是算子扩展参数MatmulExtendParam的成员类型。算子侧的参数校验在 cube_operation_impl.cpp 中C 算子实现会再次校验void CheckTransModeParam(DataType inDtype, const MatmulExtendParam param {}) { if (param.transMode ! TransMode::CAST_NONE) { // 校验输入数据类型与架构支持 } }并在矩阵乘操作入口 cube_operation_impl.cpp 处调用与 Python 前端的校验形成前后端双重防线。代码生成层的映射最终trans_mode会被翻译为 tile 算子模板参数。在 codegen_cube.cpp 的PrintMatmulTileTensor中int64_t transModeNum 0; GetOpAttr(OpAttributeKey::transMode, transModeNum); TransMode transMode static_castTransMode(transModeNum); std::string transModeStr TransMode::CAST_NONE; if (transMode TransMode::CAST_RINT) { transModeStr TransMode::CAST_RINT; } else if (transMode TransMode::CAST_ROUND) { transModeStr TransMode::CAST_ROUND; } // 生成形如 TMatmulzeroC, TransMode::CAST_ROUND, kAlignFlag(l0c, l0a, l0b)生成的目标代码为 tile 框架下的TMatmul模板调用例如 UT 用例 test_codegen_dyn_mm.cpp 中的 golden 输出TMatmulTransMode::CAST_NONE, 1(l0cTensor_0, l0aTensor_1, l0bTensor_2, btTensor_3);这也印证了 TransMode 的完整路径Python API → pybind11 枚举绑定 → C 扩展参数 → 算子属性 → 代码生成 → tile 模板参数。与 matmul 的完整配合TransMode 是extend_params的组成部分可与bias_tensor、scale、scale_tensor、relu_type等其他扩展能力同时使用。需要了解 matmul 的完整参数语义a_trans/b_trans/c_matrix_nz、批处理与广播规则、输出 dtype 支持表等可进一步阅读 pypto-matmul.md 与 matmul.py 的源码注释。小结TransMode 是 PyPTO 中 FP32 matmul 使能 TF32 计算的开关与舍入策略选择器仅 Ascend 950PR/950DT 支持三个取值中CAST_NONE为默认值不转换CAST_ROUND为官方推荐的一般舍入模式CAST_RINT提供 tie-to-even 的 IEEE 754 语义使用时必须保证输入输出为DT_FP32并通过extend_params{trans_mode: ...}传入从 Python 前端校验、C 算子校验到代码生成层的TMatmulTransMode::...模板映射整条调用链路在仓库源码中均有明确实现与 UT 用例佐证。【免费下载链接】pyptoPyPTO发音: pai p-t-oParallel Tensor/Tile Operation编程范式。项目地址: https://gitcode.com/cann/pypto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进