当前位置: 首页 > news >正文

CANN/ops-nn PReLU反向传播

aclnnPreluBackward

【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-nn

📄 查看源码

产品支持情况

产品是否支持
Ascend 950PR/Ascend 950DT
Atlas A3 训练系列产品/Atlas A3 推理系列产品
Atlas A2 训练系列产品/Atlas A2 推理系列产品
Atlas 200I/500 A2 推理产品×
Atlas 推理系列产品×
Atlas 训练系列产品

功能说明

接口功能:完成aclnnPreluBackward的反向计算。

gradInput的计算公式如下:

$$ gradInput_{i,j,...}= \begin{cases} gradOutput_{i,j,...}, & if\ self_{i,j,...} > 0 \ gradOutput_{i,j,...} * weight_{i}, & if\ self_{i,j,...} <= 0 \end{cases} $$

gradWeight的计算公式如下:

$$ gradWeight_{j}=\sum_{i,...} \begin{cases} 0, & if\ self_{i,j,...} > 0 \ gradOutput_{i,j,...} * self_{i,j,...}, & if\ self_{i,j,...} <= 0 \end{cases} $$

函数原型

每个算子分为两段式接口,必须先调用“aclnnPreluBackwardGetWorkspaceSize”接口获取计算所需workspace大小以及包含了算子计算流程的执行器,再调用“aclnnPreluBackward”接口执行计算。

aclnnStatus aclnnPreluBackwardGetWorkspaceSize( const aclTensor* gradOutput, const aclTensor* self, const aclTensor* weight, aclTensor* gradInput, aclTensor* gradWeight, uint64_t* workspaceSize, aclOpExecutor** executor)
aclnnStatus aclnnPreluBackward( void* workspace, uint64_t workspace_size, aclOpExecutor* executor, aclrtStream stream)

aclnnPreluBackwardGetWorkspaceSize

  • 参数说明:

    参数名输入/输出描述使用说明数据类型数据格式维度(shape)非连续Tensor
    gradOutput(aclTensor*)输入反向传播的梯度值。公式中的gradOutput。
    • 支持空Tensor。
    • dtype需要与self相同。
    • shape需要与self满足broadcast关系,且Broadcast后shape与self的shape相等。
    FLOAT16、FLOAT32、BFLOAT16ND0-8
    self(aclTensor*)输入prelu的正向输入值。公式中的self。支持空Tensor。FLOAT16、FLOAT32、BFLOAT16ND0-8
    weight(aclTensor*)输入prelu的权重,公式中的weight。
    • 支持空Tensor。
    • dtype需要与self相同。
    • 当self的shape维度大于1维时,weight的shape维度可以与self的shape维度相同且第2维度的值保持一致,同时weight的shape其他维度的值为1;或者weight是1维Tensor,元素个数为self的shape的第2维度。
    • 否则,weight元素个数为1。
    FLOAT16、FLOAT32、BFLOAT16ND0-8
    gradInput(aclTensor*)输出为self的梯度值。
    • dtype需要与self相同。
    • shape需要与gradOutput满足broadcast关系。
    • gradInput的shape和数据类型与self的相同。
    FLOAT、FLOAT16、BFLOAT16ND0-8
    gradWeight(aclTensor*)输出为weight的梯度值。
    • dtype需要与self相同。
    • 需要与weight的数据类型相同。
    • gradWeight的shape与weight的shape保持一致。
    FLOAT、FLOAT16、BFLOAT16ND0-8
    workspaceSize(uint64_t*)输出返回需要在Device侧申请的workspace大小。-----
    executor(aclOpExecutor**)输出返回op执行器,包含了算子计算流程。-----
    • Atlas 训练系列产品 :数据类型支持FLOAT16、FLOAT32。
  • 返回值:

    aclnnStatus:返回状态码,具体参见aclnn返回码。

    第一段接口会完成入参校验,出现以下场景时报错:

    返回码错误码描述
    ACLNN_ERR_PARAM_NULLPTR161001传入的gradOutput、self、weight、gradInput、gradWeight是空指针。
    ACLNN_ERR_PARAM_INVALID161002gradOutput、self、weight、gradInput、gradWeight的数据类型不在支持的范围之内。
    gradOutput、self、weight、gradInput、gradWeight的数据类型不同。
    gradOutput、self、weight、gradInput、gradWeight大于8维。
    weight的元素个数不等于self的通道数或者1。
    weight的元素个数为1时,gradWeight的shape与weight不相同。
    gradOutput和self的shape不满足条件broadcastshape条件。

aclnnPreluBackward

  • 参数说明:

    参数名输入/输出描述
    workspace输入在Device侧申请的workspace内存地址。
    workspaceSize输入在Device侧申请的workspace大小,由第一段接口aclnnPreluBackwardGetWorkspaceSize获取。
    executor输入op执行器,包含了算子计算流程。
    stream输入指定执行任务的Stream。
  • 返回值:

    aclnnStatus:返回状态码,具体参见aclnn返回码。

约束说明

  • 确定性计算:
    • aclnnPreluBackward默认确定性实现。

调用示例

示例代码如下,仅供参考,具体编译和执行过程请参考编译与运行样例。

#include <iostream> #include <vector> #include "acl/acl.h" #include "aclnnop/aclnn_prelu_backward.h" #define CHECK_RET(cond, return_expr) \ do { \ if (!(cond)) { \ return_expr; \ } \ } while (0) #define LOG_PRINT(message, ...) \ do { \ printf(message, ##__VA_ARGS__); \ } while (0) int64_t GetShapeSize(const std::vector<int64_t>& shape) { int64_t shape_size = 1; for (auto i : shape) { shape_size *= i; } return shape_size; } int Init(int32_t deviceId, aclrtStream* stream) { // 固定写法,资源初始化 auto ret = aclInit(nullptr); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); ret = aclrtSetDevice(deviceId); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); ret = aclrtCreateStream(stream); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); return 0; } template <typename T> int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, aclDataType dataType, aclTensor** tensor) { auto size = GetShapeSize(shape) * sizeof(T); // 调用aclrtMalloc申请device侧内存 auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); // 计算连续tensor的strides std::vector<int64_t> strides(shape.size(), 1); for (int64_t i = shape.size() - 2; i >= 0; i--) { strides[i] = shape[i + 1] * strides[i + 1]; } // 调用aclCreateTensor接口创建aclTensor *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); return 0; } int main() { // 1. (固定写法)device/stream初始化, 参考acl API手册 // 根据自己的实际device填写deviceId int32_t deviceId = 0; aclrtStream stream; auto ret = Init(deviceId, &stream); // check根据自己的需要处理 CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); // 2. 构造输入与输出,需要根据API的接口自定义构造 std::vector<int64_t> selfShape = {4, 2}; std::vector<int64_t> weightShape = {2}; std::vector<int64_t> gradOutputShape = {4, 2}; std::vector<int64_t> gradInputShape = {4, 2}; std::vector<int64_t> gradWeightShape = {2}; void* selfDeviceAddr = nullptr; void* gradOutputDeviceAddr = nullptr; void* weightDeviceAddr = nullptr; void* gradInputDeviceAddr = nullptr; void* gradWeightDeviceAddr = nullptr; aclTensor* self = nullptr; aclTensor* weight = nullptr; aclTensor* gradOutput = nullptr; aclTensor* gradInput = nullptr; aclTensor* gradWeight = nullptr; std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; std::vector<float> weightHostData = {0.5, 0.5}; std::vector<float> gradOutputHostData = {1, 1, 1, 1, 1, 1, 1, 1}; std::vector<float> gradInputHostData = {0, 0, 0, 0, 0, 0, 0, 0}; std::vector<float> gradWeightHostData = {0, 0}; // 创建weight aclTensor ret = CreateAclTensor(weightHostData, weightShape, &weightDeviceAddr, aclDataType::ACL_FLOAT, &weight); CHECK_RET(ret == ACL_SUCCESS, return ret); // 创建self aclTensor ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); CHECK_RET(ret == ACL_SUCCESS, return ret); // 创建gradOutput aclTensor ret = CreateAclTensor(gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, aclDataType::ACL_FLOAT, &gradOutput); CHECK_RET(ret == ACL_SUCCESS, return ret); // 创建gradInput aclTensor ret = CreateAclTensor(gradInputHostData, gradInputShape, &gradInputDeviceAddr, aclDataType::ACL_FLOAT, &gradInput); CHECK_RET(ret == ACL_SUCCESS, return ret); // 创建gradWeight aclTensor ret = CreateAclTensor(gradWeightHostData, gradWeightShape, &gradWeightDeviceAddr, aclDataType::ACL_FLOAT, &gradWeight); CHECK_RET(ret == ACL_SUCCESS, return ret); // 3. 调用CANN算子库API,需要修改为具体的API uint64_t workspaceSize = 0; aclOpExecutor* executor; // 调用aclnnPreluBackward第一段接口 ret = aclnnPreluBackwardGetWorkspaceSize(gradOutput, self, weight, gradInput, gradWeight, &workspaceSize, &executor); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnPreluBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); // 根据第一段接口计算出的workspaceSize申请device内存 void* workspaceAddr = nullptr; if (workspaceSize > 0) { ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); } // 调用aclnnPreluBackward第二段接口 ret = aclnnPreluBackward(workspaceAddr, workspaceSize, executor, stream); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnPreluBackward failed. ERROR: %d\n", ret); return ret); // 4. (固定写法)同步等待任务执行结束 ret = aclrtSynchronizeStream(stream); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 auto gradInputSize = GetShapeSize(gradInputShape); std::vector<float> gradInputResultData(gradInputSize, 0); ret = aclrtMemcpy(gradInputResultData.data(), gradInputResultData.size() * sizeof(gradInputResultData[0]), gradInputDeviceAddr, gradInputSize * sizeof(float), ACL_MEMCPY_DEVICE_TO_HOST); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); for (int64_t i = 0; i < gradInputSize; i++) { LOG_PRINT("gradInput[%ld] is: %f\n", i, gradInputResultData[i]); } auto gradWeightSize = GetShapeSize(gradWeightShape); std::vector<float> gradWeightResultData(gradWeightSize, 0); ret = aclrtMemcpy(gradWeightResultData.data(), gradWeightResultData.size() * sizeof(gradWeightResultData[0]), gradWeightDeviceAddr, gradWeightSize * sizeof(float), ACL_MEMCPY_DEVICE_TO_HOST); CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); for (int64_t i = 0; i < gradWeightSize; i++) { LOG_PRINT("gradWeight[%ld] is: %f\n", i, gradWeightResultData[i]); } // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 aclDestroyTensor(gradOutput); aclDestroyTensor(self); aclDestroyTensor(weight); aclDestroyTensor(gradInput); aclDestroyTensor(gradWeight); // 7. 释放device资源, 需要根据具体API的接口定义修改 aclrtFree(selfDeviceAddr); aclrtFree(gradOutputDeviceAddr); aclrtFree(weightDeviceAddr); aclrtFree(gradInputDeviceAddr); aclrtFree(gradWeightDeviceAddr); if (workspaceSize > 0) { aclrtFree(workspaceAddr); } aclrtDestroyStream(stream); aclrtResetDevice(deviceId); aclFinalize(); return 0; }

【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-nn

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

http://www.jsqmd.com/news/783404/

相关文章:

  • 2026江苏 上海环氧地坪源头厂家怎么选?哪家好 推荐 - 奔跑123
  • 用友财报深度解读:2025亏损13亿,即将触底反弹?
  • 基于图神经网络与可视分析的慢性肾病临床决策支持系统构建
  • CANN/pyasc昇腾SoftMax算子API文档
  • 工程教育中基于角色的AI能力框架:从认知到协同的整合路径
  • 多模态大模型赋能港口,从视频孪生迈向空间原生智能
  • 2026年半导体超纯水夹钳流量传感器推荐:五家优选深度对比 - 科技焦点
  • 【图像处理】基于数学形态学的数字视网膜图像血管提取 (DRIVE) 数据集分割方法附matlab代码
  • 多智能体协作框架设计:从需求到交付的自动化产品开发实践
  • 2026年亦缇玻尿酸综合评测:品牌现状与市场表现 - 江湖评测
  • CANN/pto-isa通信测试问题诊断手册
  • AI赋能敏捷开发:从需求到部署的智能化实践与效率革命
  • cann/runtime初始化指南
  • 包头就近入学政策解读:昆区城区小学教学水平究竟如何? - 品牌推荐大师
  • AI智能增长如何影响其自我设计能力?比例论与收益递减论之争
  • 构建企业级MLOps平台:从数据湖到实验管理的全流程实践
  • AI赋能非洲农业:技术落地挑战与可持续路径实践
  • 集成学习在濒危语言文本分类中的实践:小样本场景下的NLP解决方案
  • pH计(酸度计)选型参考:2026年5月国内外笔式pH 计,台式pH 计,实验室pH 计知名品牌与正规生产厂家汇总 - 品牌推荐大师1
  • 内容创作团队如何利用Taotoken多模型能力提升稿件生成效率
  • 强化学习在精准健康干预中的应用:从多臂老虎机到个性化策略优化
  • HarmonyOS 6 实战:首页标题栏右上角智能体入口接入指南
  • CANN DeepSeek-V3.2-Exp推理优化实践
  • CANN MXFP4量化矩阵乘算子
  • 体验Taotoken多模型聚合端点的低延迟与高稳定性连接
  • CANN/graph-autofusion SuperKernel开发指南
  • 图片翻译高精度软件有哪些?高精度的AI图片翻译工具盘点 - 三年美工五年设计
  • AI赋能复合材料声发射源定位:从物理模型到数据驱动的毫米级精度突破
  • 从簧下质量优化看极氪9X性能重构:碳陶制动系统的工程逻辑 - RF_RACER
  • 江西安羿环境科技:南昌灭蟑螂怎么联系 - LYL仔仔