十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ATVOSS Exp 指数运算符:从表达式模板到昇腾硬件的一元运算实践指南

ATVOSS Exp 指数运算符:从表达式模板到昇腾硬件的一元运算实践指南 ATVOSS Exp 指数运算符从表达式模板到昇腾硬件的一元运算实践指南【免费下载链接】atvossATVOSSAscend C Templates for Vector Operator Subroutines是一套基于Ascend C开发的Vector算子库致力于为昇腾硬件上的Vector类融合算子提供极简、高效、高性能、高拓展的编程方式。项目地址: https://gitcode.com/cann/atvossExp 是 ATVOSSAscend C Templates for Vector Operator Subroutines面向 Vector 算子编程提供的一元运算符接口用于在 Compute 表达式中直接表达以自然常数 e 为底的指数运算。本文以 docs/api/Exp.md 为骨架结合仓库源码与测试用例完整讲解 Exp 的函数原型、参数语义、张量/标量两种调用方式并深入其表达式模板机制与 AscendC 底层映射原理帮助读者在昇腾硬件上写出正确、可运行的指数运算算子。功能说明Exp 运算符完成数学上的指数运算out[i] e ^ in[i]即以自然常数 e约 2.71828为底对输入张量的每个元素或标量求指数。在算子开发中Exp 是 softmax、sigmoid、指数加权平均等经典融合算子的基础计算单元也是 ATVOSS 官方接口列表见 docs/api/README.md 表 2 Operator 接口列表中明确列出的内置运算符之一。所属头文件与声明机制Exp 的声明位于 include/operators/math_expression.h该文件集中定义了 ATVOSS 的算术与超越函数运算符Add、Sub、Mul、Div、Power、Divs、Sqrt、Exp、Abs、Cast、Max 等。与 Power、Divs 等带标量模板参数的运算符采用手写定义不同Exp、Sqrt、Abs 这类纯一元运算统一通过DeclareUnaryOp宏声明DeclareUnaryOp(Sqrt); DeclareUnaryOp(Exp); DeclareUnaryOp(Abs);宏的完整定义位于 include/expression/expr_template.h展开后等价于生成以下三部分// 1) 运算符结构体继承一元运算符基类 template typename T struct OpExp : UnaryOpT { OpExp() default; constexpr OpExp(T t) : UnaryOpT(t) {} }; // 2) 张量重载输入是 ExpressionT 表达式对象 template typename T __host_aicore__ constexpr auto Exp(ExpressionT lhs) { return ExpressionOpExpT{{lhs.data}}; } // 3) 标量/通用重载输入是普通值 template typename T __host_aicore__ constexpr auto Exp(T lhs) { return ExpressionOpExpT{{std::forwardT(lhs)}}; }从源码结构可以推断__host_aicore__与constexpr的标注使得该函数既可在 Host 侧编译期求值也可在 AI Core 侧运行这是 ATVOSS 表达式系统能够在编译期完成类型推导与参数收集的基础。函数原型Exp 对外暴露三类接口templatetypename T struct OpExp : UnaryOpT templatetypename T __host_aicore__ constexpr auto Exp(ExpressionT lhs) templatetypename T __host_aicore__ constexpr auto Exp(T lhs)其中OpExp是表达式树中的运算节点类型用户一般不直接构造而是通过调用Exp(...)工厂函数自动生成。参数说明参数名称参数类型输入/输出数据类型参数说明默认值T模板参数输入NAExp 操作数数据类型NAlhs函数形参输入NAExp 左操作数当类型是ExpressionT时是张量当类型是T时是标量NA参数语义与仓库实现一一对应T模板参数决定操作数的数据类型。结合 tests/st/test_op_exp.cpp 可知实际测试中 T 为float由于底层映射到AscendC::Exp输入与输出类型应保持一致测试中以Runfloat, float()调用即输入、输出均为 float。lhs函数形参接受张量表达式或标量。当传入Atvoss::PlaceHolder生成的ExpressionParam...时走张量路径当传入普通数值如5.0f时走标量路径。该二元分发正是通过上述两个同名重载函数实现。返回值说明返回值数据类型返回值说明ExpressionOpExpT返回一个 OpExp 的表达式对象返回的ExpressionOpExpT并不会立即执行计算而是作为表达式树的一个节点等待被赋值运算符接入计算图。关于Expression模板的完整语义不可赋值给同类型对象、RetType/TensorType推导等可参考 docs/api/UnaryOp.md 与 include/expression/expr_template.h。底层工作原理从表达式到 AscendC 内核指令Exp 的表达式节点最终需要被翻译成昇腾硬件指令这一过程由求值器Evaluator完成。关键实现位于 include/operators/math_evaluator.h1. Tile 层的 ExpAssign直接映射 AscendC::Exp/*! * \brief dst[i] exp(src[i]) * \param[in] src, Input LocalTensor * \param[out] dst, Output LocalTensor */ template typename OperationShape, typename T __aicore__ inline void ExpAssign( AscendC::LocalTensorT dst, const AscendC::LocalTensorT src, OperationShape operationShape) { AscendC::Exp(dst, src, operationShape.axis0); }见 include/operators/math_evaluator.h可以看到ATVOSS 将AscendC::Exp向量指令封装为ExpAssign一次调用即对整段连续数据长度为operationShape.axis0执行指数运算。2. Evaluator 特化OpAssign 与 OpExp 的组合求值template typename T, typename U struct EvaluatorOpAssignT, OpExpU { using Type void; template typename Context __aicore__ inline auto operator()(const OpAssignT, OpExpU op, Context context) const { using Dtype Dtype_tT; OperationShape operationShape GetShapeOperation::Unary(context.argsTensors); return Atvoss::Tile::ExpAssignOperationShape, Dtype( EvaluatorT{}(op.GetLhs(), context).GetUbTensor(), EvaluatorU{}(op.GetRhs().GetData(), context).GetUbTensor(), operationShape); } };见 include/operators/math_evaluator.h该特化展示了完整的调用链GetShapeOperation::Unary从运行时参数中取出本次参与运算的数据长度左操作数op.GetLhs()即outPlaceHolder通过EvaluatorT解析出目标 UB Tensor右操作数op.GetRhs().GetData()即Exp(in)中的in解析出源 UB Tensor最后交给ExpAssign执行AscendC::Exp。同理OpExp节点本身继承自UnaryOpT其DataType、TensorType、RetType等类型元信息由 include/expression/expr_template.h 中UnaryOp基类提供供表达式编译期分析与参数收集使用。使用示例原文档给出了张量与标量两种等价写法二者仅在PlaceHolder声明的参数类型上不同计算表达式均为一行(out Exp(...))。示例一张量输入template typename InputDtype, typename OutputDtype struct Config { struct Compute { template template typename class Tensor __host_aicore__ constexpr auto Compute() const { auto in Atvoss::PlaceHolder1, TensorInputDtype, Atvoss::ParamUsage::IN(); auto out Atvoss::PlaceHolder2, TensorOutputDtype, Atvoss::ParamUsage::OUT(); // 使用示例 return (out Exp(in)); // 使用示例 }; }; };示例二标量输入template typename InputDtype, typename OutputDtype struct Config { struct Compute { template template typename class Tensor __host_aicore__ constexpr auto Compute() const { auto scalar Atvoss::PlaceHolder1, InputDtype, Atvoss::ParamUsage::IN(); auto out Atvoss::PlaceHolder2, TensorOutputDtype, Atvoss::ParamUsage::OUT(); // 使用示例 return (out Exp(scalar)); // 使用示例 }; }; };两处代码的使用要点PlaceHolder 位序PlaceHolderN, T, U中的N必须与运行时ArgumentsBuilder::inputOutput()传入实参的顺序一一对应、从 1 开始编号详见 docs/api/PlaceHolder.md标量声明方式标量 PlaceHolder 的第二模板参数直接传数据类型如float而非TensorDtype见示例二中的Atvoss::PlaceHolder1, InputDtype, Atvoss::ParamUsage::IN()返回表达式Compute()返回out Exp(in)这一赋值表达式对象ATVOSS 后续会据此自动推导输入输出参数集合与求值顺序。端到端可运行验证基于测试用例仓库提供了 Exp 的完整可运行测试 tests/st/test_op_exp.cpp展示了从 ACL 初始化到结果校验的完整流程。其核心结构如下template typename T1, typename T2 struct ExpConfig { struct ExpCompute { template template typename class Tensor __host_aicore__ constexpr auto Compute() const { auto in Atvoss::PlaceHolder1, TensorT1, Atvoss::ParamUsage::IN(); auto out Atvoss::PlaceHolder2, TensorT2, Atvoss::ParamUsage::OUT(); return (out Exp(in)); }; }; using ArchTag Atvoss::Arch::DAV_3510; using BlockOp Atvoss::Ele::BlockBuilderExpCompute, ArchTag; using KernelOp Atvoss::Ele::KernelBuilderBlockOp; using DeviceOp Atvoss::DeviceAdapterKernelOp; };ExpConfig展示了 ATVOSS 的分层组装方式Compute表达计算逻辑 →BlockBuilder生成 block 层 →KernelBuilder生成 kernel 层 →DeviceAdapter生成 device 层可运行对象。运行时流程对应测试中Runfloat, float()的十个步骤aclInit初始化 ACL 运行时注册aclFinalize释放守卫aclrtSetDevice(0)绑定设备创建 Context 与 Stream通过aclrtMalloc为输入输出分配设备内存各 8 个元素aclrtMemcpy将 Host 数据拷入设备构造Atvoss::TensorT与ArgumentsBuilder{}.inputOutput(t1, t2).build()实例化DeviceOp并调用deviceOp.Run(arguments, stream)执行同步 Stream 后将结果拷回 Host与 golden 数据比对输入为 0期望exp(0) 1打印验证结果。该测试验证了 Exp 的数值正确性当输入张量元素全为 0 时输出应为全 1即VerifyResults(golden, hostOutput)判定通过。同时它也证明了 Exp 表达式经 Block/Kernel/Device 三层构建后可以直接在昇腾设备上运行。约束与注意事项原文档中 Exp 的约束说明为 NA但结合仓库源码实际使用时仍应注意以下几点类型一致性ExpAssign底层调用AscendC::Exp(dst, src, count)要求源与目标 LocalTensor 的数据类型一致如均为 float跨类型使用应先在表达式中插入Cast参考 docs/api/Cast.md禁止存储右值引用ExpressionT与UnaryOpT内部均有static_assert(!std::is_rvalue_reference_vT, ...)编译期检查禁止将右值引用存入表达式对象见 include/expression/expr_template.h 与 include/expression/expr_template.h标量/张量混用Exp 是单操作数运算输入只能有一个张量或标量不存在二元运算中的双标量限制对比 Add/Mul 的OpAdds inputs not accepts all scalar types断言宏展开命名DeclareUnaryOp(Exp)会同时生成OpExp结构体与Exp工厂函数命名空间为Atvoss使用时应保持Atvoss::Exp前缀或using namespace Atvoss。总结本文围绕 docs/api/Exp.md 完整梳理了 ATVOSS Exp 指数运算符接口层面Exp提供张量、标量两种重载统一返回ExpressionOpExpT与PlaceHolder、ParamUsage配合即可在Compute()中一行表达指数运算实现层面DeclareUnaryOp宏生成表达式节点EvaluatorOpAssignT, OpExpU特化将表达式树翻译为AscendC::Exp向量指令完成从模板元编程到昇腾硬件的落盘验证层面tests/st/test_op_exp.cpp 提供了从 ACL 初始化、参数构建、算子执行到精度校验的完整参考实现。对于需要在昇腾硬件上实现 softmax、sigmoid 等含指数运算的融合算子开发者Atvoss::Exp是开箱即用的基础运算单元可在此基础上继续叠加 Add、Mul、Div 等运算符组合出任意复杂度的计算表达式。更多接口可查阅 docs/api/README.md 中的完整接口列表。【免费下载链接】atvossATVOSSAscend C Templates for Vector Operator Subroutines是一套基于Ascend C开发的Vector算子库致力于为昇腾硬件上的Vector类融合算子提供极简、高效、高性能、高拓展的编程方式。项目地址: https://gitcode.com/cann/atvoss创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表