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

Ascend上开发自定义算子接入PyTorch有几种实现方式?

答案

首先回答问题,从官网资料看,当前有3种方式,分别是:

  • 基于OpPlugin算子适配开发
  • 基于C++ extensions算子适配开发 - 单算子API调用适配
  • 基于C++ extensions算子适配开发 - kernel直调算子适配

1 基于OpPlugin算子适配开发

首先,从测试脚本,看其调用方式:

import torch
import torch_npu
from torch_npu.testing.testcase import TestCase, run_teststorch.npu.config.allow_internal_format = False
torch.npu.set_compile_mode(jit_compile=False)class TestCustomAdd(TestCase):def test_add_custom(self):length = [8, 2048]x = torch.rand(length, device='cpu', dtype=torch.float16)y = torch.rand(length, device='cpu', dtype=torch.float16)print(x, '\n', y)output = torch_npu.npu_add_custom(x.npu(), y.npu()).cpu()print(output)self.assertRtolEqual(output, x + y)if __name__ == "__main__":run_tests()

这里可以看到,其调用方式:torch_npu.npu_add_custom(x.npu(), y.npu()).cpu()
PyTorch官方提供的native_functions.yaml文件定义了PyTorch Native Functions的具体算子定义和分发细节,定义则通过.cpp文件实现。OpPlugin仓库与原生类似,使用yaml文件定义了NPU适配的算子,算子具体适配则存放在.cpp文件中
在这里插入图片描述
需要关注的是,如上4个文件。
步骤一般是:算子yaml配置(op_plugin_functions.yaml/derivatives.yaml) -> 算子适配实现(AbsKernelNpuOpApi.cpp/AbsKernelNpu.cpp)
具体样例步骤,可参见:基于OpPlugin算子适配开发
该实现方式的特点是,实现了正向和方向的yaml配置,并通过源码编译安装的形式使用。这种方式是最古老的

2 基于C++ extensions算子适配开发 - 单算子API调用适配

基于C++ extensions方式,通过torch_npu来调用单算子API的适配开发过程。
先看调用方式:

class TestCustomAdd(TestCase):def test_add_custom(self):x_cpu = torch.randn([8, 2048], dtype=torch.float16)y_cpu = torch.randn([8, 2048], dtype=torch.float16)x_npu, y_npu = copy.deepcopy(x_cpu).npu(), copy.deepcopy(y_cpu).npu()x_cpu.requires_grad = Truey_cpu.requires_grad = Truex_npu.requires_grad = Truey_npu.requires_grad = True# calculate on npuoutput = custom_ops.add_custom(x_npu, y_npu)output.backward(output)# calculate on cpucpuout = torch.add(x_cpu, y_cpu)cpuout.backward(cpuout)# compare resultself.assertRtolEqual(output, cpuout)self.assertRtolEqual(x_npu.grad, x_cpu.grad)self.assertRtolEqual(y_npu.grad, y_cpu.grad)

这里可以看到,其调用方式:custom_ops.add_custom(x_npu, y_npu)custom_ops是python侧算子包的名字。
具体参考:https://gitee.com/ascend/samples/blob/master/operator/ascendc/0_introduction/1_add_frameworklaunch/CppExtensionInvocation/test/test_add_custom.py
另外,注意到其正向的实现:

// 前向实现
at::Tensor add_custom_impl_npu(const at::Tensor& self, const at::Tensor& other) {// 创建输出内存at::Tensor result = at::empty_like(self);// 调用aclnn接口计算EXEC_NPU_CMD(aclnnAddCustom, self, other, result);return result;
}

这中间,调用了异步执行宏定义:EXEC_NPU_CMD
该方式的特点是,通过标准的cpp_extention的方式实现torch算子的添加,使用到TORCH_LIBRARY、TORCH_LIBRARY_IMPL、PYBIND11_MODULE等接口

另外,这种方式下,也提供了图模式(NPU上图模式)相关的调用方式,如下图:

# 注意: meta_outputs形参名为固定写法,若写错会影响ge节点的输出dtype与shape推导
@register_fx_node_ge_converter(torch.ops.myops.add_custom.default)
def convert_npu_add_custom(x: Tensor, y: Tensor, z: Tensor = None, meta_outputs: Any = None):return torchair.ge.custom_op("AddCustom",inputs={"x": x, "y": y,},outputs=['z'])class TestTorchCompileCustomAdd(TestCase):def test_add_custom(self):x = torch.randn([8, 2048], device='npu', dtype=torch.float16)y = torch.randn([8, 2048], device='npu', dtype=torch.float16)from torchair.configs.compiler_config import CompilerConfigconfig = CompilerConfig()npu_backend = torchair.get_npu_backend(compiler_config=config)class Module(torch.nn.Module):def __init__(self):super().__init__()def forward(self, x, y):result = custom_ops.add_custom(x, y)return resultmod = torch.compile(Module().npu(), backend=npu_backend)output = mod(x, y)self.assertRtolEqual(output, (x + y))

具体请参考:https://gitee.com/ascend/samples/blob/master/operator/ascendc/0_introduction/1_add_frameworklaunch/CppExtensionInvocation/test/test_add_custom_graph.py

3 基于C++ extensions算子适配开发 - kernel直调算子适配

支持Ascend C实现自定义算子Kernel,并集成在PyTorch框架,通过PyTorch的API实现算子调用。
先看调用方式:

class TestCustomAdd(TestCase):def test_add_custom_ops(self):length = [8, 2048]x = torch.rand(length, device='cpu', dtype=torch.float16)y = torch.rand(length, device='cpu', dtype=torch.float16)x_npu = x.npu()y_npu = y.npu()output = torch.ops.npu.my_add(x_npu, y_npu)cpuout = torch.add(x, y)self.assertRtolEqual(output, cpuout)

可以看到,这里的调用方式是torch.ops.npu.my_add
通过调用样例可知,该方式的使用需要通过安装wheel包的形式完成

#LINK下载样例代码
git clone https://gitee.com/ascend/op-plugin.git
cd op-plugin
git checkout master
# 进入代码目录
cd examples/cpp_extension# 完成算子适配,具体可参考适配开发# 执行如下命令编译并安装wheel包
python setup.py bdist_wheel
cd dist
pip install *.whl

该方式的特点是,直接通过AscendC实现算子后,通过安装wheel包就可以在pytorch的工程中使用起来。

http://www.xdnf.cn/news/1435195.html

相关文章:

  • Higress云原生API网关详解 与 Linux版本安装指南
  • 企业数字安全守护神:IT运维管理系统全面解析,构建坚不可摧的防护体系
  • 实现自己的AI视频监控系统-第三章-信息的推送与共享3(重点)
  • 数据结构:闭散列 (Closed Hashing)-开放定址法 (Open Addressing)
  • react用useImages读取图片,方便backgroundImage
  • hikvision海康威视sdk调用失败,code为29解决办法
  • 集采与反腐双重压力下,医药销售的破局之道:从资源依赖到价值重构
  • 从结构化到多模态:RAG文档解析工具选型全指南
  • Portainer:Docker可视化管理神器部署与使用攻略
  • 不只是一台玩具车:开源燃料电池机器人HydroBot全揭秘
  • 怎么用redis lua脚本实现各分布式锁?Redisson各分布式锁怎么实现的?
  • Unity通过Object学习原型模式
  • ES6和CommonJS模块区别
  • GNU Make | C/C++项目自动构建入门
  • DevOps运维与开发一体化及Kubernetes运维核心详解
  • Aurobay EDI 需求分析:OFTP2 与 EDIFACT 驱动的汽车供应链数字化
  • DataAgent技术解析:数据智能的未来之路
  • LangGraph 上下文工程权威指南:构建智能、感知、有记忆的 AI 代理
  • Ubuntu平台查看.gz格式压缩文件内容以及利用grep命令过滤搜索内容
  • 《浪浪山小妖怪》知识竞赛来袭!测测你是几级影迷?
  • RL【1】:Basic Concepts
  • 情况三:已经 add ,并且也 commit 了
  • 机器人控制器开发(整体架构2 Lerobot介绍)
  • 佛山体彩第二届唱享之夜浪漫收官, 七夕音乐派对全场大合唱!
  • 使用 Gulp + Webpack 打造一个完整的 TypeScript 库构建流程
  • 社区医疗健康管理系统的设计与实现-(源码+LW+可部署)
  • Linux92 shell:倒计时,用户分类
  • [re_2] rpc|http|nginx|protobuf|
  • HBuilder X 4.76 开发微信小程序集成 uview-plus
  • 【Linux我做主】进程退出和终止详解