目前,该文档共描述了三种 C to python module 的方法,三种方法用法都不一样,注意辨别。工作还是以第三种方法为主: c_to_pytorch
该 demo 演示了怎么使用 pycuda 调用 kernel,类似的 cupy 也可以写 kernel, 但是没有 pycuda 灵活,numba 使用装饰器 cuda.jit 也可以写 kernel,但是需要根据 numba 的语法来写, numba 的语法就不再展示如果 kernel 的参数是基本数据类型,需要用 np 修饰,或者其他方式修饰,因为 python 的 int/float 是一个类
- 首先需要使用 nvcc 编译生成 ptx/cubin 二进制文件
nvcc -arch=sm_80 -cubin c.cu -o kernel.cubin
or
nvcc -ptx -arch=sm_80 c.cu -o kernel.ptx- 然后使用 pycuda 调用
- 这个地方注意,这个地方只是注册 kernel,没有编译生成 python module,所以不能直接使用 import
- 有三个地方的定义必须一致:
- PyModuleDef:模块名称
- PyInit_xxxx:xxxx (函数名)必须和模块名称一致
- Extension:py 文件中的 Extension 类的 name 必须和模块名称一致
- c 代码输出的是 module, python 可以直接 import module,但注意 python 定义的包名不能和 module 名一样,否则两个符号的名字就一样了,会出现歧义,某种意义上讲 module 和 package 是等价的
- 包(package)可以简单的理解为包含 _init_.py 的文件夹,或者说是 C++ 的头文件(即 .h)
该目录演示了怎么为 pytorch 添加一个拓展,需要用到 PYBIND11_MODULE
- 具体用法参考 : pybind11
同时,注意 .cpp 和 .cu 文件不要同名,如下面的编译方法会报错,因为 add.cpp/add.cu 编译都会生成 add.o,上一个文件的符号会被覆盖,所以会有一些奇奇怪怪的错误,推荐使用 make 编译,而且文件命名的时候最好也体现出他的功能,算是一种开发规范
# 错误代码演示
no_make = CUDAExtension(
name="my_add",
sources=["./my_add/add.cpp", "./my_add/add.cu"],
include_dirs=["./my_add"]
)
setup(
name ="my_add",
ext_modules = [no_make],
cmdclass = {"build_ext": BuildExtension}
)参考 issues : 100253
pytorch 源码, 核心逻辑是:- Tensor:
- AutoGrad: pytorch/torch/csrc/autograd
- Cublas Handle: pytorch/aten/src/ATen/cuda/CublasHandlePool.cpp
- pytoch 的部分代码是需要通过 torchgen/ 目录中的文件生成, 生成指令如下:
PYTHONPATH=$(pwd) python torchgen/gen.py --install_dir build/aten/src
(学习的时候继续补充)
设计一个 log demo,用于 debug 错误,避免反复编译