热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python教程分享Pytorchmlu 实现添加逐层算子方法详解

目录1、注册算子2、算子分发3、修改opmethods基类4、下发算子5、添加wrapper6、添加wrapper7、算子测试本教程分享了在寒武纪设备上pytorch-mlu中添加
目录
  • 1、注册算子
  • 2、算子分发
  • 3、修改 opmethods 基类
  • 4、下发算子
  • 5、添加 wrapper
  • 6、添加 wrapper
  • 7、算子测试

本教程分享了在寒武纪设备上 pytorch-mlu 中添加逐层算子的方法。

pytorch-mlu 逐层模式中算子间数据传递和存储的基本单元是 tensor。pytorch-mlu 根据 tensor 中的 device 属性值将算子分发到不同设备。以 abs() 算子为例,在 dispatch 阶段会根据 input_tensor 的设备属性值将算子调用分发到具体设备,逻辑如下图所示:

Pytorch-mlu 实现添加逐层算子方法详解

catch 通过注册添加 mlu 算子方式与 pytorch 源码解耦,下面介绍在 catch 中添加 mlu 算子的具体步骤。

1、注册算子

catch/torch_mlu/csrc/generated/aten_mlu_type_default.cpp 中注册算子:

  .op(torch::registeroperators::options().schema("aten::add.tensor(tensor self, tensor other, *, scalar alpha=1) -> tensor")  // nolint       .impl_unboxedonlykernel(at::tensortypeid::mlutensorid)        aliasanalysis(c10::aliasanalysiskind::from_schema))  

2、算子分发

atenmlutype 和 atenmlucustomtype 是 catch 模块中算子的入口。atenmlutype 类主要包含框架中的标准算子;而 atenmlucustomtype 类包含客制化的算子。根据算子属性选择在 atenmlutype 还是 atenmlucustomtype 中添加相应算子声明和实现。

标准算子分发

catch/torch_mlu/csrc/aten/aten_mlu_type.hcatch/torch_mlu/csrc/aten/aten_mlu_type.cpp 中添加算子声明和实现:

  aten_mlu_type.h  static at::tensor add(const at::tensor& self, const at::tensor& other, at::scalar alpha);  aten_mlu_type.cpp  at::tensor atenmlutype::add(const at::tensor& self, const at::tensor& other, at::scalar alpha){    return op_dispatch(add, self, other, alpha);  }  

客制化算子分发

对于 mlu 特有算子,在 catch/torch_mlu/csrc/aten/aten_mlu_type.hcatch/torch_mlu/csrc/aten/aten_mlu_custom_type.cpp 中添加算子申明和实现:

  aten_mlu_type.h  static at::tensor linear(const at::tensor& input,                           const at::tensor& weight,                           const at::tensor& bias,                           const at::tensor& q_scale,                           const at::tensor& q_mode);  aten_mlu_custom_type.cpp  at::tensor atenmlucustomtype::linear(const at::tensor& input,                                       const at::tensor& weight,                                       const at::tensor& bias,                                       const at::tensor& q_scale,                                       const at::tensor& q_mode){      return op_dispatch(linear, input, weight, bias, q_scale, q_mode);  }  

3、修改 opmethods 基类

从 atenmlutype 和 atenmlucustomtype 中都会通过 opmethods 下发到推理算子或训练算子。在 catch/torch_mlu/csrc/aten/operators/op_methods.h catch/torch_mlu/csrc/aten/operators/op_methods.cpp 中添加算子申明和实现。opmethods 中的实现部分为该算子的 cpu 实现。

  op_methods.h  virtual at::tensor add(const at::tensor& self, const at::tensor& other, at::scalar alpha);  op_methods.cpp  at::tensor opmethods::add(const at::tensor& self,                            const at::tensor& other,                            at::scalar alpha){     auto input_cpu = self.cpu();     auto other_cpu = other.cpu();     auto output = at::add(input_cpu, other_cpu, alpha);     return output.to(at::device(at::device::type::mlu));  }  

4、下发算子

catch/torch_mlu/csrc/aten/operators/cnml_ops.hcatch/torch_mlu/csrc/aten/operators/cnml_ops.cpp 中添加推理算子申明和实现。

  cnml_ops.h  at::tensor add(const at::tensor& self, const at::tensor& other, at::scalar alpha);  cnml_ops.cpp  at::tensor cnmlops::add(const at::tensor& self, const at::tensor& other, at::scalar alpha){    cnml_dispatch(add, cnml_add, self, other, alpha);  // cnml_dispatch 宏第一个参数是该接口名,第二个参数是wrapper个名字,其余  }  

5、添加 wrapper

wrapper 是对算子 kernel 的封装,每个算子对应一个 wrapper。这里以 add 算子为例,添加 wrapper 如下所示:

  cnml_kernel.h  at::tensor cnml_add(const at::tensor& input, const at::tensor& other, at::scalar alpha);  add.cpp  at::tensor cnml_add(const at::tensor& input, const at::tensor& other, at::scalar alpha_scalar){    torch_check(input.dim() >= 0 || other.dim() >= 0, "dimension not support");    at::tensor input_ = input;    at::tensor other_ = other;    auto alpha_data = alpha_scalar.to();    if(alpha_data != 1){      // scale_t      other_ = cnml::ops::cnml_scale(other_, alpha_data, 0);    }    if(other_.dim() <1 && other_.device().type() == c10::devicetype::cpu){      auto other_scalar = other_.item();      return cnml_add_internal(input_, other_scalar);   // 调用kernel    }    if(input_.dim() <1 && input_.device().type() == c10::devicetype::cpu){      auto input_scalar = input_.item();      return cnml_add_internal(other_, input_scalar);   // 调用 kernel    }        bool broadcast = input_.sizes() != other_.sizes();    if(broadcast){      auto broadcast_size = at::infer_size(input.sizes(), other.sizes());      at::tensor broadcast1 = cnml::ops::cnml_expand(input_, broadcast_size, false);      at::tensor broadcast2 = cnml::ops::cnml_expand(other_, broadcast_size, false);      return cnml_add_internal(broadcast1, broadcast2);  // 调用 kernel    }else{      return cnml_add_internal(input_, other_);  //调用 kernel    }    return cnml_add_internal(input_, other_);   //调用 kernel  }  

6、添加 wrapper

wrapper 中通过调用 kernel 实现算子功能。示例中调用的是 cnml_add_internal。算子的具体实现主要通过调用 cnml 库的接口来完成,下面是 cnml 库的逻辑:

Pytorch-mlu 实现添加逐层算子方法详解

kernel 实现就是按照上述编程逻辑调用 cnml 库接口完成的,在 catch/torch_mlu/csrc/aten/operators/cnml/internal/cnml_internal.h catch/torch_mlu/csrc/aten/operators/cnml/internal/add_internal/cpp 中添加 kernel 函数的声明和实现。

  cnml_internal.h  at::tensor cnml_add_internal(const at::tensor& input1, const at::tensor& input2);  add_internal.cpp  at::tensor cnml_add_internal(const at::tensor& input1, const at::tensor& input2){    auto output = at::native::empty_like(input1);    // prepare input cnml tensor    auto* input1_impl = getmlutensorimpl(input1);  // 获取mlutensorimpl    auto input1_cnml = input1_impl->createcnmltensor(         cnml_tensor, tocnmldatatype(input1.dtype()));  // 类型自适应:tocnmldatatype()             auto* input2_impl = getmlutensorimpl(input2);    auto input2_cnml = input2_impl->createcnmltensor(        cnml_tensor, tocnmldatatype(input2.dtype()));            // prepare output cnml tensor    auto* output_impl = getmlutensorimpl(output);    auto output_cnml = output_impl->createcnmltensor(        cnml_tensor, tocnmldatatype(output.dtype()));            // end the execution flow if not mlu device    check_mlu_device(output);        // setup operator    cnmlbaseop_t add_op;    torch_cnml_check(cnmlcreateaddop(&add_op, input1_cnml, input2_cnml, output_cnml));        // return to jit if running mode is fuse    chexk_return_to_fuse(add_op, output);        // compile op    torch_cnml_check(cnmlcompilebaseop(add_op, get_core_version, get_core_number));        auto queue = getcurqueue();    torch_cnml_check(cnmlcomputeaddopforward_v4(add_op,                                                null,                                                input1_impl->raw_mutable_data(),                                                null,                                                input2_impl->raw_mutable_data(),                                                null,                                                output_impl->raw_mutable_data(),                                                queue,                                                null));     syncqueue(queue);     torch_cnml_check(cnmldestroybaseop(&add_op));         return output;  }  

对 mlu 不支持算子的处理

对于 mlu 暂不支持的操作,输入数据将会拷贝到 cpu 上,然后调用 cpu 相关操作,使其在 cpu 上运行,最后再将输出结果拷会到 mlu 上。具体实现,可以查询 op_methods.cp,该文件在 catch/torch_mlu/csrc/aten/operators/ 目录下。

  op_methods.cpp  at::tensor opmethods::add(const at::tensor& self,                            const at::tensor& other,                            at::scalar alpha){    auto input_cpu = self.cpu();    auto other_cpu = other.cpu();    auto output = at::add(input_cpu, other_cpu, alpha);    return output.to(at::device(at::device::type::mlu));  }  

对于新增的算子在执行过程中抛出异常时,如果 cpu 上没有对应的算子操作,那么该操作无法切换到 cpu 上运行;

wrapper一般以 cnml_算子名命名,kernel一般以cnml_算子名_internal命名

7、算子测试

使用基于 python 的 unittest 模块编写算子单元测试。测试时需提供相同的参数和输入数据,分别在 mlu 和 cpu 上执行算子,对比两者的输出结果。mlu 和 cpu 计算结果可能会有差异,一般情况下两者的相对误差在 2% 以内均是可以接受的。

  def test_add(self):    # "tensor + tensor" mode testing    for shape1, shape2 in [((1,3,224,224),(1,3,224,224)),((2,30,80),(2,30,80)),((3,20),(3,20)),((10),(10))]:      input1_cpu = torch.rand(shape1, dtype=torch.float)      input2_cpu = torch.rand(shape2, dtype=torch.float)      input1_mlu = input1_cpu.to(xm.mlu_device())      input2_mlu = input2_cpu.to(xm.mlu_device())      # 在 cpu 上计算      output_cpu = input1_cpu + input2_cpu      # 在 mlu 上计算      output_mlu = input1_mlu + input2_mlu      # 计算 mlu 的误差,并确保相对误差在 2% 以内      self.asserttensorsequal(output_cpu, output_mlu.cpu(), 0.02, use_mse=true) 

 以上分享了在寒武纪设备 pytorch-mlu 中添加逐层算子的方法,并以 add() 算子为例进行了示例编写,希望我的分享会对你的学习有一点帮助。

到此这篇关于pytorch-mlu 实现添加逐层算子方法详解的文章就介绍到这了,更多相关pytorch内容请搜索<编程笔记>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<编程笔记>!

需要了解更多python教程分享Pytorch-mlu 实现添加逐层算子方法详解,都可以关注python教程分享栏目&#8212;编程笔记


推荐阅读
  • 【图像分类实战】利用DenseNet在PyTorch中实现秃头识别
    本文详细介绍了如何使用DenseNet模型在PyTorch框架下实现秃头识别。首先,文章概述了项目所需的库和全局参数设置。接着,对图像进行预处理并读取数据集。随后,构建并配置DenseNet模型,设置训练和验证流程。最后,通过测试阶段验证模型性能,并提供了完整的代码实现。本文不仅涵盖了技术细节,还提供了实用的操作指南,适合初学者和有经验的研究人员参考。 ... [详细]
  • 本文提供了PyTorch框架中常用的预训练模型的下载链接及详细使用指南,涵盖ResNet、Inception、DenseNet、AlexNet、VGGNet等六大分类模型。每种模型的预训练参数均经过精心调优,适用于多种计算机视觉任务。文章不仅介绍了模型的下载方式,还详细说明了如何在实际项目中高效地加载和使用这些模型,为开发者提供全面的技术支持。 ... [详细]
  • 精选10款Python框架助力并行与分布式机器学习
    随着神经网络模型的不断深化和复杂化,训练这些模型变得愈发具有挑战性,不仅需要处理大量的权重,还必须克服内存限制等问题。本文将介绍10款优秀的Python框架,帮助开发者高效地实现分布式和并行化的深度学习模型训练。 ... [详细]
  • 高级缩放示例.就像谷歌地图一样.它仅缩放图块,但不缩放整个图像.因此,缩放的瓷砖占据了恒定的记忆,并且不会为大型缩放图像调整大小的图像.对于简化的缩放示例lookhere.在Win ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文详细介绍了 Java 中 org.w3c.dom.Node 类的 isEqualNode() 方法的功能、参数及返回值,并通过多个实际代码示例来展示其具体应用。此方法用于检测两个节点是否相等,而不仅仅是判断它们是否为同一个对象。 ... [详细]
  • 本文介绍了 JSON Schema 和 XML Schema 的基本概念,并详细讲解了如何使用 AJV 进行 JSON 数据校验。通过具体的示例和扩展方法,帮助读者更好地理解和应用这些工具。 ... [详细]
  • 目录预备知识导包构建数据集神经网络结构训练测试精度可视化计算模型精度损失可视化输出网络结构信息训练神经网络定义参数载入数据载入神经网络结构、损失及优化训练及测试损失、精度可视化qu ... [详细]
  • Spring Data JdbcTemplate 入门指南
    本文将介绍如何使用 Spring JdbcTemplate 进行数据库操作,包括查询和插入数据。我们将通过一个学生表的示例来演示具体步骤。 ... [详细]
  • 通过使用CIFAR-10数据集,本文详细介绍了如何快速掌握Mixup数据增强技术,并展示了该方法在图像分类任务中的显著效果。实验结果表明,Mixup能够有效提高模型的泛化能力和分类精度,为图像识别领域的研究提供了有价值的参考。 ... [详细]
  • 在Windows环境下离线安装PyTorch GPU版时,首先需确认系统配置,例如本文作者使用的是Win8、CUDA 8.0和Python 3.6.5。用户应根据自身Python和CUDA版本,在PyTorch官网查找并下载相应的.whl文件。此外,建议检查系统环境变量设置,确保CUDA路径正确配置,以避免安装过程中可能出现的兼容性问题。 ... [详细]
  • PyTorch 使用问题:解决导入 torch 后 torch.cuda.is_available() 返回 False 的方法
    在配置 PyTorch 时,遇到 `torch.cuda.is_available()` 返回 `False` 的问题。本文总结了多种解决方案,并分享了个人在 PyCharm、Python 和 Anaconda3 环境下成功配置 CUDA 的经验,以帮助读者避免常见错误并顺利使用 GPU 加速。 ... [详细]
  • 洛谷 P4009 汽车加油行驶问题 解析
    探讨了经典算法题目——汽车加油行驶问题,通过网络流和费用流的视角,深入解析了该问题的解决方案。本文将详细阐述如何利用最短路径算法解决这一问题,并提供详细的代码实现。 ... [详细]
  • 不用蘑菇,不拾金币,我通过强化学习成功通关29关马里奥,创造全新纪录
    《超级马里奥兄弟》由任天堂于1985年首次发布,是一款经典的横版过关游戏,至今已在多个平台上售出超过5亿套。该游戏不仅勾起了许多玩家的童年回忆,也成为强化学习领域的热门研究对象。近日,通过先进的强化学习技术,研究人员成功让AI通关了29关,创造了新的纪录。这一成就不仅展示了强化学习在游戏领域的潜力,也为未来的人工智能应用提供了宝贵的经验。 ... [详细]
  • 利用 PyTorch 实现 Python 中的高效矩阵运算 ... [详细]
author-avatar
mobiledu2502858945
这个家伙很懒,什么也没留下!