PyTorch C++扩展用于AMD GPU

news2025/2/24 22:01:18

PyTorch C++ Extension on AMD GPU — ROCm Blogs

本文演示了如何使用PyTorch C++扩展,并通过示例讨论了它相对于常规PyTorch模块的优势。实验在AMD GPU和ROCm 5.7.0软件上进行。有关支持的GPU和操作系统的更多信息,请参阅系统要求(Linux)。

介绍

由于易用性和模型的广泛可用性,PyTorch已成为机器学习从业者和爱好者的首选开发框架。PyTorch还允许您通过创建`torch.nn.Module`的派生类来轻松定制模型,这减少了与可微性相关的重复代码的需要。简而言之,PyTorch提供了广泛的支持。
但如果您想加速自定义模型呢?PyTorch提供了C++扩展来加速您的工作负载。这些扩展有优势:
• 它们为源外操作(PyTorch中不可用的操作)提供了一个快速的C++测试台,并且可以轻松集成到PyTorch模块中。
• 它们可以快速编译模型,无论是在CPU还是GPU上,只需一个附加的构建文件来编译C++模块。

PyTorch的自定义C++和CUDA扩展教程由Peter Goldsborough编写,这篇文章解释了PyTorch C++扩展如何减少模型的编译时间。PyTorch建立在一个C++后端之上,实现快速的计算操作。然而,构建PyTorch C++扩展的方式与PyTorch本身的构建方式不同。您可以在您的C++文件中包含PyTorch的库(torch.h),以充分利用PyTorch的`tensor`和`Variable`接口,同时使用原生的C++库,如`iostream`。下面的代码片段是从PyTorch教程中取的使用C++扩展的例子:

#include <torch/extension.h>

#include <iostream>

torch::Tensor d_sigmoid(torch::Tensor z) {
  auto s = torch::sigmoid(z);
  return (1 - s) * s;
}

_d_sigmoid_函数计算了sigmoid函数的导数,并在后向传播中使用。您可以看到,实现是PyTorch的一个C++扩展。例如,`d_sigmoid`函数的返回值数据类型以及函数参数`z`是`torch::Tensor`。这是因为`torch/extension.h`头文件包含了著名的`ATen`张量计算库。让我们现在看看如何通过查看一个完整的示例来使用C++扩展来加速程序。

实现

在本节中,我们将在原生PyTorch和PyTorch C++中测试一个具有一个隐藏层的通用MLP网络。源代码受到了Peter的LLTM(长期记忆模型)示例的启发,我们为我们的MLP模型建立了类似的流程。
现在让我们在C++中实现_mlp_forward_和_mlp_backward_函数。PyTorch有`torch.autograd.Function`来在后台实现后向传递。PyTorch C++扩展要求我们在C++中定义后向传递,然后将它们绑定到PyTorch的`autograd`函数中。
如下所示,_mlp_forward_函数执行与MLP Python类中的计算相同,_mlp_backward_函数实现了输出相对于输入的导数。如果您对理解数学推导感兴趣,可以查看Prof. Tony Jebara的ML幻灯片中定义的_反向传播_部分中的后向传递方程。他代表了一个有两个隐藏层的MLP网络,并详细说明了后向传播的微分方程。为了简单起见,我们的示例中只考虑了一个隐藏层。请注意,在C++中编写自定义的微分方程是一项具有挑战性的任务,并且需要领域专家知识。

#include <torch/extension.h>
#include <vector>
#include <iostream>


torch::Tensor mlp_forward(  
    torch::Tensor input,  
    torch::Tensor hidden_weights,  
    torch::Tensor hidden_bias,  
    torch::Tensor output_weights,  
    torch::Tensor output_bias) {  
  // Compute the input/hidden layer  
  auto hidden = torch::addmm(hidden_bias, input, hidden_weights.t());  
  hidden = torch::relu(hidden);  
  
  // Compute the output layer  
  auto output = torch::addmm(output_bias, hidden, output_weights.t());   
  
  // Return the output  
  return output;  
    
}  
  
std::vector<torch::Tensor> mlp_backward(  
    torch::Tensor input,  
    torch::Tensor hidden_weights,  
    torch::Tensor hidden_bias,  
    torch::Tensor output_weights,  
    torch::Tensor output_bias,
    torch::Tensor grad_output) {  
  
  // Compute the input/hidden layer
  auto hidden = torch::addmm(hidden_bias, input, hidden_weights.t());
  hidden = torch::relu(hidden);  
  // Compute the output layer  
  auto output = torch::addmm(output_bias, hidden, output_weights.t());  
  // Compute the gradients for output layer
  auto grad_output_weights = torch::mm(grad_output.t(), hidden);
  auto grad_output_bias = torch::sum(grad_output, /*dim=*/0).unsqueeze(0); 
  // Compute the gradients for input/hidden layer using chain rule
  auto grad_hidden = torch::mm(grad_output, output_weights);
  // grad_hidden = grad_hidden
  auto grad_hidden_weights = torch::mm(grad_hidden.t(), input);
  auto grad_hidden_bias = torch::sum(grad_hidden, /*dim=*/0).unsqueeze(0);
  // Compute the gradients for input
  auto grad_input = torch::mm(grad_hidden , hidden_weights);
    
  // Return the gradients  
  return {grad_input, grad_hidden_weights, grad_hidden_bias, grad_output_weights, grad_output_bias};  
}

以下是将C++实现使用`ATen`的Python绑定函数封装起来的示例。`PYBIND11_MODULE`将关键字_forward_映射到`mlp_forward`函数的指针,以及_backward_映射到`mlp_backward`函数。这将C++实现绑定到Python定义。宏`TORCH_EXTENSION_NAME`将在构建时在setup.py文件中传递的名称定义。

PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
  m.def("forward", &mlp_forward, "MLP forward");
  m.def("backward", &mlp_backward, "MLP backward");
}

接下来,编写一个`setup.py`文件,导入`setuptools`库来帮助编译C++代码。要构建并安装C++扩展,运行`python setup.py install`命令。该命令会创建所有与`mlp.cpp`文件相关的构建文件,并提供一个可以导入到PyTorch模块中的模块`mlp_cpp`。

from setuptools import setup
from torch.utils.cpp_extension import BuildExtension, CppExtension

setup(
    name='mlp_cpp',
    ext_modules=[
        CppExtension('mlp_cpp', ['mlp.cpp']),
    ],
    cmdclass={
        'build_ext': BuildExtension
    })

现在,让我们使用`torch.nn.Module`和`torch.autograd.Function`的帮助,准备一个由C++函数驱动的PyTorch的MLP类。这允许以更符合PyTorch原生方式使用C++函数。在下面的示例中,_MLP_类的forward函数指向`MLPFunction`的forward函数,它又指向C++的`mlp_forward`函数。这个信息流建立了一个工作流程,可以无缝地作为常规的PyTorch模型运行。

import math
from torch import nn
from torch.autograd import Function
import torch

import mlp_cpp

torch.manual_seed(42)

class MLPFunction(Function):
    @staticmethod
    def forward(ctx, input, hidden_weights, hidden_bias, output_weights, output_bias):
        output = mlp_cpp.forward(input, hidden_weights, hidden_bias, output_weights, output_bias)
        variables = [input, hidden_weights, hidden_bias, output_weights, output_bias]
        ctx.save_for_backward(*variables)

        return output

    @staticmethod
    def backward(ctx, grad_output):
        grad_input, grad_hidden_weights, grad_hidden_bias, grad_output_weights, grad_output_bias =  mlp_cpp.backward( *ctx.saved_variables, grad_output)
        return grad_input, grad_hidden_weights, grad_hidden_bias, grad_output_weights, grad_output_bias


class MLP(nn.Module):
    def __init__(self, input_features=5, hidden_features=15):
        super(MLP, self).__init__()
        self.input_features = input_features
        self.hidden_weights = nn.Parameter(torch.rand(hidden_features,input_features))
        self.hidden_bias = nn.Parameter(torch.rand(1, hidden_features))
        self.output_weights = nn.Parameter(torch.rand(1,hidden_features))
        self.output_bias = nn.Parameter(torch.rand(1, 1))
        
        self.reset_parameters()

    def reset_parameters(self):
        stdv = 0.001
        for weight in self.parameters():
            weight.data.uniform_(-stdv, +stdv)

    def forward(self, input):
        return MLPFunction.apply(input, self.hidden_weights, self.hidden_bias, self.output_weights, self.output_bias)

现在,让我们使用 [trainer.py](PyTorch C++ Extension on AMD GPU — ROCm Blogs) 来测试前向和后向计算的速度,并将原生 PyTorch 实现与 C++ 实现进行比较。

注意:在某些情况下,在进行基准测试以期望看到速度提升的趋势之前,你可能需要多次运行程序。

python trainer.py py

Forward: 0.102 milliseconds (ms) | Backward 0.223 milliseconds (ms)

我们可以看到,在 100,000 次运行中,原生 PyTorch 模型的平均前向传递时间是 0.102 毫秒,而对于 C++ 模型,它只需要 0.0904 毫秒(提升约 8%)。如果后向传递没有遵循相同的趋势,其实现可能没有优化。如前所述,将数学微分方程转换为 C++ 代码是一项具有挑战性的任务。随着模型的复杂性和大小的增加,在两个实验之间我们可能会看到更大的差异,正如 Peter 的 LLTM 示例中所注释的。尽管有一些实现挑战,C++ 正在证明它的速度更快,而且与 PyTorch 集成也更方便。
完整代码可以在 [src](PyTorch C++ Extension on AMD GPU — ROCm Blogs) 文件夹中找到,它包含了以下结构:
- [setup.py](https://rocm.blogs.amd.com/_downloads/1e638f7ade5de8f2cc73cd9f4ca07e54/setup.py) - 编译 C++ 模块的构建文件
- [mlp.cpp](https://rocm.blogs.amd.com/_downloads/72080e8113297740e24fb96f8fe46b65/mlp.cpp) - C++ 模块
- [mlp_cpp_train.py](https://rocm.blogs.amd.com/_downloads/00f3258c26bf3c8838dc72eb3a6ded8a/mlp_cpp_train.py) - 将 C++ 扩展应用于 PyTorch 模型
- [mlp_train.py](https://rocm.blogs.amd.com/_downloads/65248a2373711bbdef8139c524f96a28/mlp_train.py) - 用于对比的原生 PyTorch 实现
- [trainer.py](https://rocm.blogs.amd.com/_downloads/0d2415a09361672c52a5736a414ff5eb/trainer.py) - 用于测试 PyTorch 与 PyTorch 的 C++ 扩展的训练文件。

结论

这个博客通过一个使用自定义 PyTorch C++ 扩展的例子逐步向你演示。我们观察到,与原生 PyTorch 实现相比,自定义 C++ 扩展提高了模型的性能。这些扩展易于实现,并且可以轻松地插入到 PyTorch 模块中,预编译的开销很小。

此外,PyTorch 的 Aten 库为我们提供了大量功能,可以导入到 C++ 模块中,并模仿 PyTorch 风格的代码。总的来说,PyTorch C++ 扩展易于实现,是测试自定义操作在 CPU 和 GPU 上的性能的一个很好的选择。

致谢

我们想要感谢 Peter Goldsborough,因为他写了一篇非常精彩的[文章](Custom C++ and CUDA Extensions — PyTorch Tutorials 2.3.0+cu121 documentation)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1824159.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue页面内容未保存时离开页面做弹框提示

一、背景 目标&#xff1a;如果当前页面中有正在编辑中的内容&#xff0c;那么此时切换组件、跳转路由、关闭标签页、刷新页面&#xff0c;都会有离开确认提示&#xff0c;防止用户因误触导致填写的内容白费。 后台管理系统中有许多需要填写的表单&#xff0c;弹窗方式的表单一…

Docker安装Nginx(各种错误版)

Docker安装-CSDN博客 安装启动Docker之后 docker run -d -p 81:81 --name nginx nginx 这样没有指定版本 docker run&#xff1a;启动一个新的容器。-d&#xff1a;以分离模式运行容器&#xff08;后台运行&#xff09;。-p 81:81&#xff1a;将主机的 81 端口映射到容器的 …

“论面向对象的建模及应用”必过范文,突击2024软考高项论文

论文真题 软件系统建模是软件开发中的重要环节&#xff0c;通过构建软件系统模型可以帮助系统开发人员理解系统&#xff0c;抽取业务过程和管理系统的复杂性&#xff0c;也可以方便各类人员之间的交流。软件系统建模是在系统需求分析和系统实现之间架起的一座桥梁&#xff0c;…

傲星一个在线工具箱源码附搭建教程

傲星工具箱源码是一款功能强大的在线工具箱程序&#xff0c;您可以通过安装扩展来增强其功能。同时&#xff0c;该程序还提供了插件模板的功能&#xff0c;让您可以将其作为网页导航使用。 1.PHP版本需不低于7.2.5。 2.Mysql版本需不低于5.7。 3.需要安装fileinfo扩展。 4.…

第〇篇:深入Docker的世界系列博客介绍

欢迎来到“深入Docker的世界”系列博客&#xff0c;这是一次旨在全面探索Docker容器化技术的冒险之旅。从基础原理到高级应用&#xff0c;再到实践案例分析&#xff0c;我们将深入挖掘Docker的每一个角落&#xff0c;帮助你不仅掌握这项技术的实用知识&#xff0c;还能了解其在…

从0到1:手动测试迈向自动化——手机web应用的自动化测试工具

引言&#xff1a; 在当今移动互联网时代&#xff0c;手机web应用已经成为人们生活中不可或缺的一部分。为了保证手机web应用的质量和稳定性&#xff0c;自动化测试工具变得十分重要。本文将介绍手机web应用自动化测试工具的选择和使用&#xff0c;提供一份超详细且规范的指南&a…

2024年6月15日 十二生肖 今日运势

小运播报&#xff1a;2024年6月15日&#xff0c;星期六&#xff0c;农历五月初十 &#xff08;甲辰年庚午月庚戌日&#xff09;&#xff0c;法定节假日。 红榜生肖&#xff1a;兔、马、虎 需要注意&#xff1a;牛、鸡、龙 喜神方位&#xff1a;西北方 财神方位&#xff1a;…

【国赛赛题详解】2024年数学建模国赛ABCDEF题(点个关注,后续会更新)

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的蓝色字体链接&#xff0c;那是获取资料的入口! 点击链接加入群聊【2024国赛资料合集】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&keQt5WRIvc5-fogZRrrahAhbqDa2nKfW8&authKey%2BqQfThTx…

博瓦科技产品亮相湖北安博会啦!!!

6月12日&#xff0c;第二十三届2024中国&#xff08;武汉&#xff09;社会公共安全产品暨数字城市产业展览会&#xff08;简称&#xff1a;湖北安博会&#xff09;在武汉国际会展中心隆重开幕。作为行业内最具影响力的展会之一&#xff0c;此次盛会将汇聚来自全球的顶尖企业、专…

《TCP/IP网络编程》(第十五章)套接字和标准I/O

之前数据通信时&#xff0c;使用的是read&write函数以及其他各种I/O函数&#xff0c;本章将使用标准I/O函数&#xff0c;例如C语言的fopen、fgetc、fputs等等&#xff1b;C语言的cout、cin等等 1.使用标准I/O函数的优点 ①跨平台兼容性&#xff1a; 标准I/O函数通常是跨平…

简单了解CPU的工作原理

目录 一、基本结构以及对应功能 &#xff08;1&#xff09;基本结构 &#xff08;2&#xff09;几个重要寄存器的详细介绍 操作码 (Opcode) 操作数 (Operands) 指令表 (Instruction Table) 第一个&#xff1a;程序计数器 (PC) 第二个&#xff1a;指令寄存器 (IR&#x…

STM32学习笔记(三)--EXTI外部中断详解

&#xff08;1&#xff09;配置步骤1.配置RCC 打开外设时钟2.配置GPIO 选择端口输入模式3.配置AFIO 选择要用的一路GPIO 连接至EXTI 4.配置EXTI 选择边沿触发方式 上升沿 下降沿 双边沿 选择触发响应方式 中断响应 事件响应 5.配置NVIC 选择一个合适的优先…

Uni-App中的u-datetime-picker时间选择器Demo

目录 前言Demo 前言 对于网页端的推荐阅读&#xff1a;【ElementUI】详细分析DatePicker 日期选择器 事情起因是两个时间选择器同步了&#xff0c;本身是从后端慢慢步入全栈&#xff0c;对此将这个知识点从实战进行提炼 通过Demo进行总结 Demo 用于选择日期和时间的组件&a…

宝藏速成秘籍(3)选择排序法

一、前言 1.1、概念 选择排序法&#xff08;Selection Sort&#xff09;是一种简单直观的排序算法。它的基本思想是&#xff1a;每次从待排序的数组中选择最小&#xff08;或最大&#xff09;的元素&#xff0c;将其放在已排序部分的末尾&#xff0c;直到所有元素都排序完毕。…

外网访问公司内网服务器?

【天联】组网天联可以解决不同地区电脑与电脑、设备与设备、电脑与设备之间的信息远程通信问题。在全国各主要节点部署加速服务器&#xff0c;实现在低带宽、跨运营商的网络环境下高速访问&#xff1b;这为公司内网服务器提供了一个可行的外网访问解决方案。 在现代办公环境中…

智能驾驶新高度:比亚迪无图城市领航夜闯城中村

在各种创新科技日新月异的今天&#xff0c;智能驾驶技术也给我们带来了越来越多的惊喜。 近日&#xff0c;比亚迪旗下的高端品牌腾势&#xff0c;凭借其全新车型腾势N7&#xff0c;在智能驾驶领域展现出了令人瞩目的实力。 在一场别开生面的“无图城市领航”实测中&#xff0c;…

Unet心电信号分割方法(Pytorch)

心血管疾病是一种常见病&#xff0c;严重影响人们的健康及日常生活。 近年来随着人们生活习惯的不断变化&#xff0c;心血管疾病对人们影响愈加明显&#xff0c;发病率呈现出逐年攀升的趋势&#xff0c;心血管疾病是中国城乡居民死亡的首要原因。心电图ECG已被广泛用于研究心跳…

跨境电商卖家入驻美国线下商超困难吗?

对于跨境电商卖家来说&#xff0c;入驻美国线下商超确实具有一定的挑战性&#xff0c;但并非不可能。成功的关键在于卖家是否具备必要的条件和资质&#xff0c;以及是否能够有效应对美国市场的挑战。 1、卖家需要满足美国相关法律法规的要求 需要拥有合法的经营执照、提供准确…

AI绘画入门教程(非常详细)从零基础入门到精通Midjourney提示词,咒语

Microorganisms infiltrating through brain-machine interfaces --v 6.0 Microorganisms infiltrating through brain-machine interfaces ,redpupil --v 6.0 Microorganisms infiltrating through brain-machine interfaces,billion girls dream --v 6.0 --niji 6 “动漫风”…

Kafka性能优化策略综述:提升吞吐量与可靠性

Kafka性能优化策略综述&#xff1a;提升吞吐量与可靠性 优化 Kafka 的性能可以从多个方面入手&#xff0c;包括配置调优、架构设计和硬件资源优化。下面详细介绍一些常用的优化策略&#xff1a; 1. 分区设计 增加分区数量&#xff1a;更多的分区意味着更高的并行处理能力&a…