pytorch自定义算子 native_functions.yaml

本文档详细介绍了如何在PyTorch中自定义运算符myrelu,通过模仿relu和hardsigmoid的实现,从编辑native_functions.yaml到实现CPU kernel,再到注册反向传播函数,最后在本地编译并验证myrelu的正确性。
摘要由CSDN通过智能技术生成

pytorch自定义算子 native_functions.yaml

在pytorch的文件夹中搜索native_functions.yaml,可以看到,所有pytorch原生的函数都是在这里注册的

在同文件夹下,存在一个README.md,这是官方教程,教我们怎么用native_functions.yaml注册自己自定义的算子

下面我仿照pytorch原生的relu算子,写一个自己的myrelu

首先,找到native_functions.yaml,有几个函数是我们可以参考的

- func: relu(Tensor self) -> Tensor
  use_c10_dispatcher: full
  variants: function, method
  dispatch:
    CPU, CUDA: relu
    MkldnnCPU: mkldnn_relu
    QuantizedCPU: relu_quantized_cpu

这里除了dispatch其他可以照搬。dispatch主要是针对不同的backend调用不同的kernel,比如GPU上的调用CUDA的kernel。这里展示的是CPU的,在native_functions.yaml加上

- func: myrelu(Tensor self) -> Tensor
  use_c10_dispatcher: full
  variants: function, method
  dispatch:
    CPU: myrelu

接下来,找到原生relu的实现,在pytorch/aten/src/ATen/native/Activation.cpp里面
relu的实现调用了同文件下的threshold,threshold的功能是实现 x > thresh ? x : result
模仿写这个调用太复杂了,而且如果在c++段调用函数的话,真正执行的时候每次调用函数都会经过dispatch,会浪费挺多时间的。因此,我参考另外一个激活函数写自己的myrelu

Tensor hardsigmoid(const Tensor& self) {
   
  Tensor result;
  auto iter = TensorIterator::unary_op(result, self);
  hardsigmoid_stub(iter.device_type(), iter);
  return iter.output();
}

hardsigmoid是用直线去近似sigmoid函数,它在这个文件中的实现和我们对relu的实现需求很像。这里大致做的事情是,创建一个空的返回对象,然后创建一个TensorIterator,对象类型是单操作数,然后调用hardsigmoid_stub进行具体的实现,最后返回。
在刚刚的activation.cpp中加入

Tensor myrelu(const Tensor& self) {
   
  Tensor result;
  auto iter = TensorIterator::unary_op(result, self);
  myrelu_stub(iter.device_type(), iter);
  return iter.output();
}

接下来,我们要知道还需要加上什么使得myrelu_stub也能像hardsigmoid_stub一样可以用。搜索hardsigmoid_stub,发现文件中还存在一个地方

DEFINE_DISPATCH(hardsigmoid_stub);

这段根据字面意思是说,这是一个分发的对象。
加上

DEFINE_DISPATCH(myrelu_stub);

理论上,activation.h也要看一下,activation.cpp和.h是一个整体
在h文件中存在

using hardsigmoid_fn = void(*)(TensorIterator&);
DECLARE_DISPATCH(hardsigmoid_fn, hardsigmoid_stub);

仿照,在对应的地方分别加上

using myrelu_fn = void(*)(TensorIterator&);
DECLARE_DISPACTH(myrelu_fn, myrelu_stub);

这样感觉算是告一段落,那么问题来了,myrelu_stub应该在哪里实现呢
在刚才activation.cpp的文件夹下,还有一个叫做cpu的文件夹,里面存在

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值