CANN opbase aclOpExecutor 算子执行器接口全面解析:从 Tensor 分配到任务执行与 cache 优化
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
导读
本文聚焦 CANN opbase 算子库基础框架中的aclOpExecutor算子执行器接口族,系统讲解 L2 阶段 aclnn 算子实现中如何通过该执行器申请 device/host 侧 Tensor、构造标量与数组、组织输入输出、计算 workspace、最终在指定 stream 上执行算子任务,以及如何通过AbandonCache关闭 aclnn cache 达到特殊场景下的性能控制。读完本文,你将掌握aclOpExecutor全部公开接口的函数原型、参数语义、数据类型约束与调用规范,并能结合 op_executor.cpp 源码理解其底层实现,直接应用于自定义算子的 host 侧 API 开发。
一、aclOpExecutor 是什么:L2 阶段算子实现的上下文枢纽
aclOpExecutor是 CANN opbase 中用于记录整个 host 侧 API 运行信息的上下文结构,host 侧 API 中几乎所有操作都以该数据结构为媒介(详见 预留接口 中对aclOpExecutor()构造函数的说明)。
从调用层次看,aclnn 算子对外暴露的接口分为两个阶段:
- L2 一阶段(
aclnnXxxGetWorkspaceSize):负责根据输入参数构造执行上下文、申请算子所需的输入输出资源、执行 infer shape,并输出所需workspaceSize和aclOpExecutor指针。一阶段内部会调用各种L0 接口(如AllocTensor、CreatAiCoreKernelLauncher等)完成资源与任务的登记; - L2 二阶段(
aclnnXxx):用户申请好 workspace 后,调用二阶段接口在指定 stream 上真正执行算子任务。
aclOpExecutor正是贯穿这两个阶段的上下文对象:一阶段通过CREATE_EXECUTOR()宏创建UniqueExecutor并在其上调用来登记任务与资源,二阶段则通过CommonOpExecutorRun根据其中记录的任务队列完成执行。在 op_executor.cpp 中,aclOpExecutor的各个成员方法均有对应实现,例如AllocTensor、AllocHostTensor、ConvertToTensor、AbandonCache等。
二、Tensor 资源申请:AllocTensor 与 AllocHostTensor
2.1 AllocTensor:申请 device 侧 Tensor
AllocTensor用于申请一个 device 侧 tensor,提供多个重载函数以指定不同的属性:
aclTensor* AllocTensor(const op::Shape& shape, op::DataType dataType, op::Format format = op::Format::FORMAT_ND) aclTensor* AllocTensor(const op::Shape& storageShape, const op::Shape& originShape, op::DataType dataType, op::Format storageFormat, op::Format originFormat) aclTensor* AllocTensor(op::DataType dataType, op::Format storageFormat, op::Format originFormat)参数说明
| 参数 | 输入/输出 | 说明 |
|---|---|---|
| shape | 输入 | 将 aclTensor 的 StorageShape 和 OriginShape 都设置为指定的 shape。 |
| dataType | 输入 | 指定 aclTensor 的数据类型。 |
| format | 输入 | 将 aclTensor 的 StorageFormat 和 OriginFormat 都设置为指定的 format。 |
| storageShape | 输入 | 将 aclTensor 的 StorageShape 设置为指定 shape。 |
| originShape | 输入 | 将 aclTensor 的 OriginShape 设置为指定 shape。 |
| storageFormat | 输入 | 将 aclTensor 的 StorageFormat 设置为指定 format。 |
| originFormat | 输入 | 将 aclTensor 的 OriginFormat 设置为指定 format。 |
返回值:返回申请得到的 aclTensor,申请失败则返回nullptr。
约束:入参指针不能为空。
调用示例:申请一个 int64 类型、shape 为[1, 2, 3, 4, 5]的 ND tensor:
void Func(aclOpExecutor *executor) { gert::Shape newShape; for (int64_t i = 1; i <= 5; i++) { newShape.AppendDim(i); } aclTensor *tensor = executor->AllocTensor(newShape, DT_INT64, ge::FORMAT_ND); }从源码看(op_executor.cpp),三个重载均会构造 tensor 对象并登记到执行器上下文,当申请失败时会记录OP_LOGE(ACLNN_ERR_INNER, "aclOpExecutor::AllocTensor failed.")错误日志并释放已创建对象后返回nullptr。值得说明的是:第一个重载的默认参数format = op::Format::FORMAT_ND表明不显式指定 format 时默认按 ND 格式申请;第二个重载允许将存储态 shape/format 与逻辑态 shape/format 分离设置,这是支撑算子内部格式转换(如 NCHW 与 5HD 等存储格式切换)的基础能力。
2.2 AllocHostTensor:申请 host 侧 Tensor
AllocHostTensor用于申请一个 host 侧 tensor,同样提供多个重载,分为两组:
组一:根据输入信息组合申请 host 侧 tensor
aclTensor *AllocHostTensor(const op::Shape &shape, op::DataType dataType, op::Format format = op::Format::FORMAT_ND) aclTensor *AllocHostTensor(const op::Shape &storageShape, const op::Shape &originShape, op::DataType dataType, op::Format storageFormat, op::Format originFormat)组二:申请 host 侧 tensor,并将指定数据类型的内存作为该 tensor 内容
aclTensor *AllocHostTensor(const int64_t *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const uint64_t *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const bool *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const char *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const int32_t *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const uint32_t *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const int16_t *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const uint16_t *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const int8_t *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const uint8_t *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const double *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const float *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const op::fp16_t *value, uint64_t size, op::DataType dataType) aclTensor *AllocHostTensor(const op::bfloat16 *value, uint64_t size, op::DataType dataType)参数说明
- 组一各参数语义与
AllocTensor一致,format默认FORMAT_ND; - 组二参数如下:
| 参数 | 输入/输出 | 说明 |
|---|---|---|
| value | 输入 | 指向不同数据类型的源数据。 |
| size | 输入 | 源数据的元素个数。 |
| dataType | 输入 | 将源数据转为 dataType 指定的数据类型后,写入 tensor。 |
返回值:返回申请得到的 aclTensor,申请失败则返回nullptr。
约束:入参指针不能为空。
调用示例:申请一个 host 侧 tensor,并将myArray中的数据拷贝到 tensor 中:
void Func(aclOpExecutor *executor) { int64_t myArray[10]; aclTensor *tensor = executor->AllocHostTensor(myArray, 10, DT_INT64); }从源码实现看(op_executor.cpp),组二为每种基础类型(含fp16_t、bfloat16等扩展浮点类型)都提供了专门的AllocHostTensor重载,实现时统一将源数据按dataType转换后写入 host tensor,并沿用“失败记录OP_LOGE(ACLNN_ERR_INNER)日志并返回nullptr”的统一错误处理路径。host 侧 tensor 通常用于算子中的常量输入(如权重初值、shape 参数等)以及需要在 host 侧完成的形状计算。
三、标量与数组资源申请:AllocScalar / AllocIntArray / AllocFloatArray / AllocBoolArray / 列表接口
除了 Tensor,算子入参还可能是标量(scalar)与数组(array)。opbase 为这些非 tensor 输入提供了统一的申请接口,返回值在申请失败时统一为nullptr,约束均为“入参指针不能为空”。
3.1 AllocScalar:申请并赋值标量
aclScalar *AllocScalar(const void *data, op::DataType dataType) aclScalar *AllocScalar(float value) aclScalar *AllocScalar(double value) aclScalar *AllocScalar(op::fp16_t value) aclScalar *AllocScalar(op::bfloat16 value) aclScalar *AllocScalar(int32_t value) aclScalar *AllocScalar(int64_t value) aclScalar *AllocScalar(int16_t value) aclScalar *AllocScalar(int8_t value) aclScalar *AllocScalar(uint32_t value) aclScalar *AllocScalar(uint64_t value) aclScalar *AllocScalar(uint16_t value) aclScalar *AllocScalar(uint8_t value) aclScalar *AllocScalar(bool value)| 参数 | 输入/输出 | 说明 |
|---|---|---|
| data | 输入 | 源数据指针。 |
| dataType | 输入 | 源数据的数据类型。 |
| value | 输入 | 将 aclScalar 的内容指定为 value。 |
调用示例:初始化一个值为 5、数据类型为 int64 的 aclScalar 对象:
void Func(aclOpExecutor *executor) { int64_t val = 5; aclScalar *scalar = executor->AllocScalar(val); scalar = executor->AllocScalar(&val, DT_INT64); }3.2 数组申请:AllocIntArray / AllocFloatArray / AllocBoolArray
aclIntArray *AllocIntArray(const int64_t *value, uint64_t size) aclFloatArray *AllocFloatArray(const float *value, uint64_t size) aclBoolArray *AllocBoolArray(const bool *value, uint64_t size)| 参数 | 输入/输出 | 说明 |
|---|---|---|
| value | 输入 | 源数据,用于初始化对应的 Array 对象。 |
| size | 输入 | 源数据的元素个数。 |
调用示例(三者结构一致,以 AllocIntArray 为例):
// 申请一个长度为10的aclIntArray void Func(aclOpExecutor *executor) { int64_t myArray[10]; aclIntArray *array = executor->AllocIntArray(myArray, 10); }3.3 列表申请:AllocTensorList / AllocScalarList
当算子的某个入参是一组 tensor 或一组 scalar(如 concat、gather 类算子)时,需要使用列表接口:
aclTensorList *AllocTensorList(const aclTensor *const *tensors, uint64_t size) aclScalarList *AllocScalarList(const aclScalar *const *scalars, uint64_t size)| 参数 | 输入/输出 | 说明 |
|---|---|---|
| tensors / scalars | 输入 | 源数据,用于初始化对应的 List 对象。 |
| size | 输入 | 源数据的元素个数。 |
调用示例:初始化 5 个 aclTensor 并将其组装为一个 aclTensorList:
void Func(aclOpExecutor *executor) { gert::Shape newShape; for (int64_t i = 1; i <= 5; i++) { newShape.AppendDim(i); } std::vector<aclTensor *> tensors; for (int64_t i = 1; i <= 5; i++) { aclTensor *tensor = executor->AllocTensor(newShape, DT_INT64, ge::FORMAT_ND); tensors.push_back(tensor); } aclTensorList *tensorList = executor->AllocTensorList(tensors.data(), tensors.size()); }调用示例:初始化 5 个 aclScalar 并将其组装为一个 aclScalarList:
void Func(aclOpExecutor *executor) { int64_t val = 5; std::vector<aclScalar *> scalars; for (int64_t i = 1; i <= 5; i++) { aclScalar *scalar = executor->AllocScalar(val); scalars.push_back(scalar); } aclScalarList *scalarList = executor->AllocScalarList(scalars.data(), scalars.size()); }四、类型转换:ConvertToTensor
ConvertToTensor将不同数据类型的 host 侧数据转换为一个 host 侧 aclTensor 对象,提供 7 个重载(前 6 个为非模板重载,最后 1 个为模板重载):
const aclTensor *ConvertToTensor(const aclIntArray *value, DataType dataType) const aclTensor *ConvertToTensor(const aclBoolArray *value, DataType dataType) const aclTensor *ConvertToTensor(const aclFloatArray *value, DataType dataType) const aclTensor *ConvertToTensor(const aclFp16Array *value, DataType dataType) const aclTensor *ConvertToTensor(const aclBf16Array *value, DataType dataType) const aclTensor *ConvertToTensor(const aclScalar *value, DataType dataType) template<typename T> const aclTensor *ConvertToTensor(const T *value, uint64_t size, DataType dataType)| 参数 | 输入/输出 | 说明 |
|---|---|---|
| value | 输入 | host 侧源数据。 |
| size | 输入 | 源数据的元素个数。 |
| dataType | 输入 | 将源数据转换为指定数据类型后,写入 aclTensor。 |
返回值:返回转换后的 host 侧 tensor。约束:入参指针不能为空。
各接口参数数据类型约束
各重载对源数据与目标dataType的支持范围如下(这些约束直接决定了调用时允许的取值组合):
| 接口 | value 类型约束 | dataType 支持范围 |
|---|---|---|
接口1ConvertToTensor(const aclIntArray*, DataType) | aclIntArray 类型,内部存储 int64_t 数据 | DT_FLOAT、DT_FLOAT16、DT_BF16、DT_INT8、DT_INT16、DT_UINT16、DT_UINT8、DT_INT32、DT_INT64、DT_UINT32、DT_UINT64、DT_BOOL、DT_DOUBLE |
接口2ConvertToTensor(const aclBoolArray*, DataType) | aclBoolArray 类型,内部存储 bool 数据 | 同上 |
接口3ConvertToTensor(const aclFloatArray*, DataType) | aclFloatArray 类型,内部存储 float 数据 | 同上 |
接口4ConvertToTensor(const aclFp16Array*, DataType) | aclFp16Array 类型,内部存储 fp16_t 数据 | 同上 |
接口5ConvertToTensor(const aclBf16Array*, DataType) | aclBf16Array 类型,内部存储 bfloat16 数据 | 同上 |
接口6ConvertToTensor(const aclScalar*, DataType) | aclScalar 类型,支持 DT_BOOL、DT_INT8、DT_UINT8、DT_INT16、DT_UINT16、DT_INT32、DT_UINT32、DT_INT64、DT_UINT64、DT_FLOAT、DT_DOUBLE、DT_FLOAT16、DT_BF16、DT_COMPLEX64、DT_COMPLEX128、DT_FLOAT8_E5M2、DT_FLOAT8_E4M3FN、DT_FLOAT8_E8M0、DT_FLOAT6_E3M2、DT_FLOAT6_E2M3、DT_FLOAT4_E2M1、DT_FLOAT4_E1M2、DT_HIFLOAT8 | 与 value 相同的数据类型全集 |
接口7ConvertToTensor(const T*, uint64_t, DataType) | 模板类型 T 支持:int64_t、uint64_t、int32_t、uint32_t、int8_t、uint8_t、int16_t、uint16_t、float、double、bool、char、op::bfloat16、op::fp16_t;size 为 uint64_t,表示元素个数 | DT_FLOAT、DT_FLOAT16、DT_BF16、DT_INT8、DT_INT16、DT_UINT16、DT_UINT8、DT_INT32、DT_INT64、DT_UINT32、DT_UINT64、DT_BOOL、DT_DOUBLE |
从数据类型全集可以看出,接口 6(aclScalar 来源)对目标类型支持最广,覆盖了 opbase 中定义的低精度浮点扩展类型(FP8、FP6、FP4、HIFLOAT8 等,对应仓库中的 float8_e4m3fn.h、float8_e5m2.h、float6_e3m2.h、float4_e2m1.h 等头文件),适合将标量常量转换为 host tensor 参与 shape 相关计算。
调用示例:分别将一个 aclScalar 和 int64_t 转为 host 侧 tensor:
void Func(aclOpExecutor *executor) { int64_t val = 5; aclScalar *scalar = executor->AllocScalar(val); const aclTensor *tensor = executor->ConvertToTensor(scalar, DT_INT64); tensor = executor->ConvertToTensor(&val, 1, DT_INT64); }五、workspace 计算与任务执行:GetWorkspaceSize / ReleaseTo / CommonOpExecutorRun
这三个接口构成 aclnn 算子两阶段 API 的骨架,在aclnnXxxGetWorkspaceSize与aclnnXxx中几乎固定出现,属于 L2 接口的标准写法。
5.1 GetWorkspaceSize:计算一阶段所需 workspace
根据 L2 一阶段中调用的 L0 接口,计算需要的 workspace 大小:
uint64_t GetWorkspaceSize()无入参;返回 L2 接口在运行中需要的 workspace 大小。典型用法(aclnn 固定写法):
void aclnnAddGetWorkspaceSize(..., uint64_t *workspaceSize, aclOpExecutor **executor) { auto uniqueExecutor = CREATE_EXECUTOR(); ...... *workspaceSize = uniqueExecutor->GetWorkspaceSize(); }5.2 ReleaseTo:输出 executor 指针
将UniqueExecutor中保存的aclOpExecutor指针,传递到 L2 一阶段输出的executor中:
void ReleaseTo(aclOpExecutor **executor)| 参数 | 输入/输出 | 说明 |
|---|---|---|
| executor | 输出 | 出参,将 UniqueExecutor 中的 aclOpExecutor 指针赋值给*executor。 |
约束:executor非空。典型用法:
void aclnnAddGetWorkspaceSize(..., uint64_t *workspaceSize, aclOpExecutor **executor) { auto uniqueExecutor = CREATE_EXECUTOR(); ...... uniqueExecutor.ReleaseTo(executor); }5.3 CommonOpExecutorRun:二阶段执行任务队列
根据 workspace、stream,执行算子 executor 上下文中的所有任务:
aclnnStatus CommonOpExecutorRun(void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream)| 参数 | 输入/输出 | 说明 |
|---|---|---|
| workspace | 输入 | 根据 L2 一阶段接口计算出的 workspaceSize,在 device 侧申请的片上内存指针。 |
| workspaceSize | 输入 | L2 一阶段接口计算出的 workspaceSize。 |
| executor | 输入 | L2 一阶段接口调用后生成的 op 执行器对象。 |
| stream | 输入 | 指定流执行 executor 中的算子任务。 |
返回值:执行成功返回ACLNN_SUCCESS,否则返回 aclnn 错误码。
约束:executor 不能为空;workspaceSize 大于 0 时,workspace 不能为空。
调用示例(aclnnAdd 的二阶段函数,执行 executor 任务队列中的算子):
aclnnStatus aclnnAdd(void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream) { return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); }从执行器的内部结构看(详见 预留接口),aclOpExecutor内部维护了任务执行队列,通过AddToKernelLauncherList系列接口登记 AI Core 任务、DVPP 任务、数据拷贝类任务与 AI CPU 任务,Run()负责运行执行队列中的任务,GetStream()/SetStream()负责读写当前执行流。CommonOpExecutorRun本质上就是基于传入的 workspace 与 stream 触发这一任务队列的完整执行。
六、aclnn cache 与 AbandonCache
AbandonCache用于关闭 aclnn cache 缓存功能:
void AbandonCache(bool disableRepeat = false)| 参数 | 输入/输出 | 说明 |
|---|---|---|
| disableRepeat | 输入 | 设置 aclOpExecutor 是否支持复用。默认为 false,不复用。 |
该功能背景是:首次调用 aclnn 算子后,框架会记录 cache 缓存,后续再次调用时跳过一阶段aclnnXxxGetWorkspaceSize函数,从而提升性能。当应用场景要求一阶段aclnnXxxGetWorkspaceSize必须每次都执行时,需要在该函数中显式调用AbandonCache关闭缓存:
void aclnnAddGetWorkspaceSize(..., uint64_t *workspaceSize, aclOpExecutor **executor) { auto uniqueExecutor = CREATE_EXECUTOR(); ...... uniqueExecutor.get()->AbandonCache(); }从源码实现看(op_executor.cpp),AbandonCache由OpExecutorImpl提供实现,默认参数disableRepeat = false表示默认仅关闭缓存但保持不可复用语义。与之配套的执行器缓存机制还包括:FinalizeCache()(完成 cache 最终数据保存)、RepeatRunWithCache()(复用场景下尝试利用 cache 完成任务执行)、AddCache()/DeleteCache()/GetOpExecCache()(cache 的全局保存、删除与获取)以及IsRepeatable()/SetRepeatable()(可复用状态查询与设置)等接口(见 预留接口)。
七、预留接口一览:理解执行器内部能力边界
以下接口为预留接口,后续可能变更或废弃,官方不建议开发者直接使用,但理解其语义有助于掌握aclOpExecutor的完整能力边界(完整说明见 预留接口):
| 接口定义 | 功能说明 |
|---|---|
| aclOpExecutor() | 记录整个 host 侧 API 运行信息的上下文结构,host 侧 API 中几乎所有操作都以该数据结构为媒介。 |
| CreateView(const aclTensor *tensor, const op::Shape &shape, int64_t offset) | 针对已有 aclTensor 创建 view 类 tensor,两者共享 device 内存,可指定后者的 shape 和 offset。 |
| CreateView(const aclTensor *tensor, const op::Shape &oriShape, const op::Shape &storageShape, const op::Strides &oriStride, int64_t offset) | 创建 view 类 tensor,可指定 originShape、storageShape、originStride 和 offset。 |
| UpdateTensorAddr(void *workspaceAddr, const size_t size) | 在 workspace 地址分配后,刷新每个 workspace 的地址。 |
| GetWorkspaceAddr() / GetWorkspaceSize() / GetWorkspaceOffsets() | 获取 workspace 起始指针、大小与 offset 列表。 |
| SetWorkspaceOffsets(const op::FVector<uint64_t> &workspaceOffsets) | 设置要记录的 workspace offset 列表。 |
| Run() | 运行 aclOpExecutor 执行队列中的任务。 |
| GetStream() / SetStream(aclrtStream stream) | 获取/设置当前执行流。 |
| GetInputTensors() / GetOutputTensors() | 获取 host 侧 API 接口中的输入/输出 aclTensor。 |
| GetLogInfo() / SetLogInfo(const op::internal::OpLogInfo &logInfo) | 获取/设置日志相关信息。 |
| GetOpConfigInfo() / SetOpConfigInfo(const op::OpConfigInfo &opConfigInfo) | 获取/设置算子运行时相关配置信息。 |
| AddTensorRelation(const aclTensor *tensorOut, const aclTensor *tensorMiddle) | 记录两个 aclTensor 间的地址等价关系,用于 aclnn cache。 |
| UpdateStorageAddr() | 在 aclOpExecutor 复用场景中刷新 aclTensor 地址。 |
| SetRepeatable() / IsRepeatable() | 设置/判断当前 aclOpExecutor 是否可复用。 |
| FinalizeCache() | 完成 aclnn cache 最终的数据保存工作。 |
| RepeatRunWithCache(void *workspaceAddr, const aclrtStream stream) | 复用场景下尝试利用 aclnn cache 完成任务执行。 |
| CheckLauncherRepeatable() | 判断任务列表中的每个任务都允许 aclOpExecutor 复用。 |
| AddCache() / DeleteCache() / GetOpExecCache() | aclnn cache 的保存、删除与获取。 |
| SetIOTensorList() | 记录 host 侧 API 的输入/输出 aclTensor。 |
| GetGraph() | 获取 host 侧 API 的执行图。 |
| GetMagicNumber() | 获取 magic number,用于不同对象的区分。 |
| UniqueExecutor(const char *funcName) / UniqueExecutor() / get() | UniqueExecutor 是 aclOpExecutor 的构造工厂;get() 获取其中的 aclOpExecutor 指针。 |
| ReleaseTo(aclOpExecutor **executor) | 将 UniqueExecutor 中的 aclOpExecutor 指针传递给目标 aclOpExecutor 指针。 |
| GetOpExecCacheFromExecutor(aclOpExecutor *) | 尝试将外部 aclOpExecutor 转为 aclnn cache 对象。 |
| InitL2Phase1Context / InitL2Phase2Context / InitL0Context | 初始化 host 侧 API 一阶段、二阶段及 L0 接口中的部分 DFX 变量值。 |
| CreatAiCoreKernelLauncher / CreatDSAKernelLauncher | 创建 AI Core 任务对象 / DSA 任务对象。 |
| InferShape(uint32_t optype, op::OpArgList &inputs, op::OpArgList &outputs, op::OpArgList &attrs) | 执行指定算子的 infer shape。 |
| AddToKernelLauncherList / AddToKernelLauncherListDvpp / AddToKernelLauncherListCopyTask / AddToKernelLauncherListAiCpu | 分别向执行队列添加 AI Core、DVPP、数据拷贝、AI CPU 任务。 |
| CommonOpExecutorRun(void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream) | 根据外部给出的 aclOpExecutor 及 workspace、stream,执行上下文中的所有任务。 |
八、组合使用:一段完整的 L2 一阶段接口范式
综合上述接口,一个典型的 aclnn 算子 L2 一阶段函数会按如下顺序组织:创建UniqueExecutor→ 用AllocTensor/AllocHostTensor/AllocScalar等申请资源 → 调用InferShape等完成形状推导 → 通过GetWorkspaceSize输出 workspace 大小 → 通过ReleaseTo输出 executor 指针(必要时调用AbandonCache)。伪代码结构如下:
aclnnStatus aclnnXxxGetWorkspaceSize(..., uint64_t *workspaceSize, aclOpExecutor **executor) { auto uniqueExecutor = CREATE_EXECUTOR(); // 1. 申请输入/输出 tensor 与标量、数组资源 aclTensor *in = uniqueExecutor->AllocTensor(inShape, DT_FLOAT, FORMAT_ND); aclTensor *out = uniqueExecutor->AllocTensor(outShape, DT_FLOAT, FORMAT_ND); aclScalar *alpha = uniqueExecutor->AllocScalar(1.0f); // 2. 登记算子任务(AI Core / AI CPU 等),执行 infer shape // 3. 输出 workspace 大小与 executor *workspaceSize = uniqueExecutor->GetWorkspaceSize(); uniqueExecutor.ReleaseTo(executor); return ACLNN_SUCCESS; }九、源码与文档定位速查
- 接口头文件:include/nnopbase/opdev/op_executor.h(
aclOpExecutor声明) - 核心实现:op_executor.cpp(
AllocTensor、AllocHostTensor、AbandonCache等实现) - 接口文档目录:docs/zh/api/nnopbase/opdev/op_executor
- 关联类型接口(StorageShape/OriginShape/Format 等访问器):docs/zh/api/nnopbase/opdev/common_types
- 数据类型定义(
op::DataType及 FP8/FP6/FP4 等扩展类型):include/nnopbase/opdev/data_type_utils.h 及 include/nnopbase/opdev 下各浮点类型头文件 - 英文版接口文档:docs/en/api/nnopbase/opdev/op_executor
说明:本文所介绍的接口面向 CANN 算子 host 侧 API(aclnn 算子)开发场景,其使用形态为在算子实现源码中调用,具体可用性与行为以当前仓库及配套 CANN 工具链版本为准。
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考