news 2026/5/9 15:32:48

CANN opbase算子数据Dump接口

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANN opbase算子数据Dump接口

aclDumpOpTensors

【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase

功能说明

模型执行过程中支持Dump算子输入/输出Tensor数据,方便算子输入/输出异常数据的问题定位和分析。

函数原型

aclnnStatus aclDumpOpTensors(const char *opType, const char *opName, aclTensor **tensors, size_t inputTensorNum, size_t outputTensorNum, aclrtStream stream)

参数说明

参数名输入/输出说明
opType输入字符串,表示算子类型,例如“Add”。
opName输入字符串,表示算子名称,例如“add_custom”。
tensors输入一维张量,表示待Dump的输入/输出Tensor对象指针。注意Tensor顺序,输入Tensor在前,输出Tensor在后。
inputTensorNum输入表示待Dump的输入Tensor个数。
outputTensorNum输入表示待Dump的输出Tensor个数。
stream输入指定执行任务的Stream。

返回值说明

返回0表示成功,返回其他值表示失败,返回码列表参见公共接口返回码。

约束说明

本接口需要在开启算子Dump功能时有效,您可以通过aclInit接口开启Dump,也可以通过aclmdlInitDump、aclmdlSetDump、aclmdlFinalizeDump系列接口开启Dump,接口介绍请参见《Runtime运行时 API》。

调用示例

关键代码示例如下(仅供参考,不支持直接拷贝运行)。

  1. 通过aclInit接口开启算子Dump功能。关键代码如下:

    // 资源初始化 aclInit("./acl.json"); aclrtSetDevice(0); aclrtStream stream = nullptr; aclrtCreateStream(&stream);

    acl.json示例如下(具体参见aclInit接口文档中模型Dump配置、单算子Dump配置示例):

    { "dump": { "dump_path": "./", "dump_list": [], "dump_mode": "all", "dump_data": "tensor" } }
  2. 调用本接口关键伪代码(以torch算子为例)如下:

    #include <torch/extension.h> #include "torch_npu/csrc/core/npu/NPUStream.h" #include "torch_npu/csrc/core/npu/NPUFunctions.h" #include "torch_npu/csrc/framework/OpCommand.h" #include "torch_npu/csrc/framework/interface/AclOpCompileInterface.h" #include "torch_npu/csrc/core/npu/register/OptionsManager.h" #include "torch_npu/csrc/aten/NPUNativeFunctions.h" #include "torch_npu/csrc/flopcount/FlopCount.h" #include "torch_npu/csrc/flopcount/FlopCounter.h" #include "torch_npu/csrc/core/npu/NpuVariables.h" #include "kernel_operator.h" #include <acl/acl_base.h> #include <aclnn/acl_meta.h> constexpr int32_t BUFFER_NUM = 2; constexpr int64_t MAX_DIM_NUM = 5; constexpr int64_t NCL_DIM_NUM = 3; constexpr int64_t NCHW_DIM_NUM = 4; constexpr int64_t NCDHW_DIM_NUM = 5; // 生成待Dump算子的输入/输出Tensor对象指针一维张量。 #define INIT_ACL_TENSOR_ARRAY(tensors, ...) aclTensor* tensors[] = {__VA_ARGS__} // at::Tensor对象转换成aclTensor对象。本函数简化了处理过程,具体以实际算子为准。 aclTensor *ConvertTensor(const at::Tensor &at_tensor) { aclDataType acl_data_type = ACL_FLOAT16; c10::SmallVector<int64_t, MAX_DIM_NUM> storageDims; const auto dimNum = at_tensor.sizes().size(); aclFormat format = ACL_FORMAT_ND; switch (dimNum) { case NCL_DIM_NUM: format = ACL_FORMAT_NCL; break; case NCHW_DIM_NUM: format = ACL_FORMAT_NCHW; break; case NCDHW_DIM_NUM: format = ACL_FORMAT_NCDHW; break; default: format = ACL_FORMAT_ND; } // if acl_data_type is ACL_STRING, storageDims is empty. if (acl_data_type != ACL_STRING) { storageDims.push_back(at_tensor.storage().nbytes() / at_tensor.itemsize()); } auto acl_tensor = aclCreateTensor(at_tensor.sizes().data(), at_tensor.sizes().size(), acl_data_type, at_tensor.strides().data(), at_tensor.storage_offset(), format, storageDims.data(), storageDims.size(), const_cast<void *>(at_tensor.storage().data())); return acl_tensor; } // 自定义算子实现。具体以实际算子为准。 class KernelAdd { public: __aicore__ inline KernelAdd() {} __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, GM_ADDR z, uint32_t totalLength) { this->blockLength = totalLength / AscendC::GetBlockNum(); this->tileNum = 8; this->tileLength = this->blockLength / this->tileNum / BUFFER_NUM; xGm.SetGlobalBuffer((__gm__ half *)x + this->blockLength * AscendC::GetBlockIdx(), this->blockLength); yGm.SetGlobalBuffer((__gm__ half *)y + this->blockLength * AscendC::GetBlockIdx(), this->blockLength); zGm.SetGlobalBuffer((__gm__ half *)z + this->blockLength * AscendC::GetBlockIdx(), this->blockLength); pipe.InitBuffer(inQueueX, BUFFER_NUM, this->tileLength * sizeof(half)); pipe.InitBuffer(inQueueY, BUFFER_NUM, this->tileLength * sizeof(half)); pipe.InitBuffer(outQueueZ, BUFFER_NUM, this->tileLength * sizeof(half)); } __aicore__ inline void Process() { int32_t loopCount = this->tileNum * BUFFER_NUM; for (int32_t i = 0; i < loopCount; i++) { CopyIn(i); Compute(i); CopyOut(i); } } private: __aicore__ inline void CopyIn(int32_t progress) { AscendC::LocalTensor<half> xLocal = inQueueX.AllocTensor<half>(); AscendC::LocalTensor<half> yLocal = inQueueY.AllocTensor<half>(); AscendC::DataCopy(xLocal, xGm[progress * this->tileLength], this->tileLength); AscendC::DataCopy(yLocal, yGm[progress * this->tileLength], this->tileLength); inQueueX.EnQue(xLocal); inQueueY.EnQue(yLocal); } __aicore__ inline void Compute(int32_t progress) { AscendC::LocalTensor<half> xLocal = inQueueX.DeQue<half>(); AscendC::LocalTensor<half> yLocal = inQueueY.DeQue<half>(); AscendC::LocalTensor<half> zLocal = outQueueZ.AllocTensor<half>(); AscendC::Add(zLocal, xLocal, yLocal, this->tileLength); outQueueZ.EnQue<half>(zLocal); inQueueX.FreeTensor(xLocal); inQueueY.FreeTensor(yLocal); } __aicore__ inline void CopyOut(int32_t progress) { AscendC::LocalTensor<half> zLocal = outQueueZ.DeQue<half>(); AscendC::DataCopy(zGm[progress * this->tileLength], zLocal, this->tileLength); outQueueZ.FreeTensor(zLocal); } private: AscendC::TPipe pipe; AscendC::TQue<AscendC::TPosition::VECIN, BUFFER_NUM> inQueueX, inQueueY; AscendC::TQue<AscendC::TPosition::VECOUT, BUFFER_NUM> outQueueZ; AscendC::GlobalTensor<half> xGm; AscendC::GlobalTensor<half> yGm; AscendC::GlobalTensor<half> zGm; uint32_t blockLength; uint32_t tileNum; uint32_t tileLength; }; __global__ __vector__ void add_custom(GM_ADDR x, GM_ADDR y, GM_ADDR z, uint32_t totalLength) { KernelAdd op; op.Init(x, y, z, totalLength); op.Process(); } namespace ascendc_ops { at::Tensor ascendc_add(const at::Tensor& x, const at::Tensor& y) { auto aclStream = c10_npu::getCurrentNPUStream().stream(false); at::Tensor z = at::empty_like(x); uint32_t numBlocks = 8; uint32_t totalLength = 1; for (uint32_t size : x.sizes()) { totalLength *= size; } add_custom<<<numBlocks, nullptr, aclStream>>>((uint8_t*)(x.mutable_data_ptr()), (uint8_t*)(y.mutable_data_ptr()), (uint8_t*)(z.mutable_data_ptr()), totalLength); // Dump算子输入/输出Tensor数据。 INIT_ACL_TENSOR_ARRAY(tensors, ConvertTensor(x), ConvertTensor(y), ConvertTensor(z)); aclDumpOpTensors("Add", "add_custom", tensors, 2, 1, aclStream); // 释放aclTensor对象。 for (size_t i = 0; i < 3; i++) { aclDestroyTensor(tensors[i]); } return z; } } // namespace ascendc_ops TORCH_LIBRARY(ascendc_ops, m) { m.def("ascendc_add(Tensor x, Tensor y) -> Tensor"); } TORCH_LIBRARY_IMPL(ascendc_ops, PrivateUse1, m) { m.impl("ascendc_add", TORCH_FN(ascendc_ops::ascendc_add)); }

【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 15:32:46

Cursor API本地代理:内网集成AI编程与自动化工作流实战

1. 项目概述&#xff1a;一个为开发者赋能的本地API代理工具如果你是一名重度使用Cursor的开发者&#xff0c;那么你一定对它的智能代码补全、对话式编程和代码重构能力印象深刻。但你是否也遇到过这样的场景&#xff1a;公司内网环境无法直接访问Cursor的云端服务&#xff0c;…

作者头像 李华
网站建设 2026/5/9 15:31:42

PCIe 5.0硬件设计避坑指南:从板材选择到玻纤效应的实战经验分享

PCIe 5.0硬件设计避坑指南&#xff1a;从板材选择到玻纤效应的实战经验分享 在服务器和高端显卡的硬件开发生态中&#xff0c;PCIe 5.0接口正迅速成为新一代性能瓶颈的突破口。32GT/s的传输速率带来的不仅是带宽翻倍的喜悦&#xff0c;更是一系列令人头痛的信号完整性挑战。本文…

作者头像 李华
网站建设 2026/5/9 15:30:31

淘金币自动化脚本:5分钟完成每日任务的高效解决方案

淘金币自动化脚本&#xff1a;5分钟完成每日任务的高效解决方案 【免费下载链接】taojinbi 淘宝淘金币自动执行脚本&#xff0c;包含蚂蚁森林收取能量&#xff0c;芭芭农场全任务&#xff0c;解放你的双手 项目地址: https://gitcode.com/gh_mirrors/ta/taojinbi 每天在…

作者头像 李华
网站建设 2026/5/9 15:24:52

大气层系统:为Switch玩家打造的安全定制化平台

大气层系统&#xff1a;为Switch玩家打造的安全定制化平台 【免费下载链接】Atmosphere-stable 大气层整合包系统稳定版 项目地址: https://gitcode.com/gh_mirrors/at/Atmosphere-stable 大气层系统&#xff08;Atmosphere&#xff09; 是专为Nintendo Switch设计的开源…

作者头像 李华