c++ pytorch自定义算子 c++如何为pytorch编写cuda op扩展

风晨君_7162

风晨君_7162

2026-03-24

740人浏览

原创

需通过torch::autograd::function封装cuda kernel并用torch.utils.cpp_extension.load编译加载,严格校验输入、管理cuda流、确保内存连续与设备一致,forward/backward须分离实现且梯度维度对齐。

c++ pytorch自定义算子 c++如何为pytorch编写cuda op扩展

怎么让 PyTorch 调用你写的 CUDA 函数

PyTorch 自定义 CUDA 算子不是“写个 .cu 文件就行”,核心在于用 torch::jit::Operator 或 torch::autograd::Function 将 CUDA kernel 封装成可被 Python 调用的 C++ 接口,并通过 torch.utils.cpp_extension.load 编译加载。没走通这三步,函数写得再快也进不了模型。

实操建议:

  • 必须用 AT_ASSERTM(而非 assert)做输入校验,否则在 release 模式下会静默失败
  • CUDA kernel 的 launch 参数(如 grid/block)别硬编码,用 at::cuda::getCurrentCUDAStream() 获取当前流,避免同步阻塞
  • 输入 tensor 必须调用 .contiguous() 和 .cuda() 显式确保内存布局和设备一致,tensor.data_ptr<float>()</float> 前不检查容易触发 RuntimeError: expected a CPU tensor

为什么 forward 和 backward 要拆成两个独立 kernel

PyTorch 的 autograd 引擎不会自动反向传播 CUDA kernel——它只认 torch::autograd::Function 的 forward 和 backward 方法。你写的 CUDA 函数只是普通 C 函数,不接入 autograd 图就等于没有梯度。

实操建议:

  • 不要试图在单个 kernel 里算完前向+反向,forward 返回中间变量(比如 input、weight、临时 buffer),backward 通过 ctx->saved_variables 取回它们
  • backward kernel 的输入梯度(如 d_output)和输出梯度(如 d_input)维度要严格对齐,shape 不匹配时错误信息是 Expected object of scalar type Float but got scalar type Double,其实只是 view 失败了
  • 如果 kernel 用到了 cuBLAS/cuDNN,记得在 backward 中也调对应反向接口(比如 cublasSgemm → cublasSgemm 的转置变体),不能复用 forward 的 call

编译时报错 “undefined symbol: _ZN3c104cuda17getCurrentCUDAStreamEv” 怎么办

这是链接时找不到 PyTorch 的 CUDA 运行时符号,本质是 C++ 编译器没正确链接 libtorch_cuda.so 或头文件路径混乱。常见于手动写 CMakeLists.txt 或混用 conda + system CUDA。

C++ Code Review Master
C++ Code Review Master

组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。

下载

实操建议:

  • 优先用 torch.utils.cpp_extension.load,它会自动注入 include_dirs 和 library_dirs;手写 CMake 时必须显式 add ${TORCH_LIBRARIES} 并 link torch_cuda、cudart、c10_cuda
  • 确认 nvcc 版本与 PyTorch 构建时用的一致(查 torch.__version__ 对应的 torch.version.cuda),比如 PyTorch 2.3 默认用 CUDA 12.1,但系统装了 12.4,就可能符号不兼容
  • Linux 下运行时报 libgomp.so.1: version `GOMP_4.0' not found,说明 GCC runtime 版本太低,用 conda install -c conda-forge gcc 升级或设 LD_LIBRARY_PATH

如何验证自定义 op 真正在 GPU 上跑、且没隐式同步

很多 op 表面调用了 CUDA,实际因 host-device 拷贝或 stream 同步卡在 CPU,性能反而比原生算子差。关键看是否真异步、是否零拷贝。

实操建议:

  • 用 nvidia-smi dmon -s u 观察 GPU 利用率,如果长期低于 10%,大概率有隐式同步;用 nsys profile --trace=cuda,nvtx python test.py 查 kernel launch 间隔
  • 在 kernel 开头加 cudaEventRecord(start, 0),结尾加 cudaEventRecord(stop, 0),用 cudaEventElapsedTime 测纯 kernel 时间,排除 memcpy 开销
  • 检查 tensor 是否用了 .to("cuda", non_blocking=True) 和 .pin_memory(),否则 tensor.cuda() 会触发同步拷贝

最易被忽略的是:自定义 op 的输入 tensor 如果来自 CPU 数据(比如 torch.tensor([...])),即使后续调用 .cuda(),PyTorch 也可能在第一次 kernel launch 前强制同步——务必从 dataloader 就用 pin_memory=True + non_blocking=True 链路打通。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

2024.04.28

6007

8

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

2025.10.23

684

4

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.29

3608

10

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

2025.10.23

684

4

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

2023.10.19

3088

3

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

4589

12

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2025.12.29

3729

9

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

2026.01.19

426

15

undefined是什么
undefined是什么

undefined是代表一个值或变量不存在或未定义的状态。它可以作为默认值来判断一个变量是否已经被赋值,也可以用于设置默认参数值。尽管在不同的编程语言中,undefined可能具有不同的含义和用法,但理解undefined的概念可以帮助我们更好地理解和编写程序。本专题为大家提供undefined相关的各种文章、以及下载和课程。

2023.07.31

11525

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Conan 2 Essentials 免费课程
Conan 2 Essentials 免费课程

共0课时 | 0人学习

CMake 与 Conan 集成实践
CMake 与 Conan 集成实践

共0课时 | 0人学习

Conan 2 高级依赖模型介绍
Conan 2 高级依赖模型介绍

共0课时 | 0人学习