使用Cython调用CUDA Kernel函数
技术背景
前面写过一篇关于Cython和C语言混合编程的文章,在Cython中可以使用非常Pythonic的方法去调用C语言中的函数。另外我们也曾在文章中介绍过Python中使用CUDA计算的一种方案。其实从Python中去调用CUDA有很多种解决方案,例如直接使用MindSpore、PyTorch、Jax等成熟的框架进行GPU加速,也可以使用Numba的CUDA即时编译JIT来直接对Python函数进行GPU加速,还可以使用PyCuda或者Cupy来实现Python中的GPU加速。但是不论是哪一种方案,其实本质上都绕不开到C语言和Kernel函数的转换。这里提供了另外一个思路,允许我们给出Python的API接口,又可以同时使用熟悉的Python函数和C函数、CUDA函数,以达到不同的目的,这就是Python+Cython+C/CUDA的方案。
构建思路
随着Python语言在机器学习领域的大力推广,Python编程对于众多的科技工作者而言总是一个较为靠前的选项。所以不论使用何种方式构建自己的项目,一般我们都会选择面向用户开放一个Python的API接口。如果做一个项目,项目的本身对于程序性能的要求并不高的情况下,我们可以直接使用Python进行相关的计算。但如果对计算性能要求比较高,那么C/CUDA会是一个更好的选择。那么剩下一个待解决的问题就是,如何构建Python API与C/CUDA之间的交互。其实这里本身有两个方案:1. 直接把C/CUDA代码编译成*.so动态链接库,然后在Python中加载动态链接库的函数作为接口。2. 只用C/CUDA执行计算,把C/CUDA代码编译成*.so动态链接库,从Cython中对两者函数进行调度和管理。
从用户面的角度来说,第一个方案虽然可能性能还不错,但凡是需要新增一些功能模块,都需要去修改C/CUDA代码。如果只是功能模块还好说,如果涉及到任务调度和接口传输的问题,那门槛就更高了。第二个方案在性能上有可能略有衰减,但是因为接口传输和调度都是在Cython中完成的,即使是只会Python的开发者,也可以以Cython为入口来开发自己需要的模块。
案例演示
这里我们演示一个简单的Hello World程序,首先我们可以写一个hello.cu的CUDA文件:
#include<stdio.h>
__global__ void HelloKernel(void){
printf("Hello World From GPU!\n");
}
int main(){
HelloKernel<<<1,3>>>();
cudaDeviceReset();
return 1;
}
然后使用nvcc对这个CUDA项目进行编译:
$ nvcc -c ./hello.cu -Xcompiler -fPIC -o ./libhello.so
得到了一个libhello.so的动态链接文件。然后在hello.pyx中引入这个动态链接库:
# cythonize -i hello.pyx
import ctypes
libcuda = ctypes.CDLL('./libhello.so')
cpdef int run_cuda():
cdef int res
res = libcuda.main()
if res:
print ('Load cuda function successfully!')
else:
print ('Failed to load cuda function.')
return 1
这里我们可以使用cythonize指令编译pyx文件,也可以使用python的setup.py配置编译指令。为了方便我们就用cythonize演示一下这个案例:
$ cythonize -i hello.pyx
那么会得到一个hello.c文件和一个hello.cpython-37m-x86_64-linux-gnu.so动态链接文件。到这里相当于我们对CUDA文件中的main函数封装了一层cython的调用,然后就可以在python文件中调用这个cython的run_cuda()函数:
# $ python3 hello.py
from hello import run_cuda
run_cuda()
然后运行这个python文件,输出为:
$ python3 hello.py
Hello World From GPU!
Hello World From GPU!
Hello World From GPU!
Load cuda function successfully!
成功的从Python侧调用了CUDA Kernel函数。
总结概要
从Python接口调用GPU进行加速的方案有很多,包括Cupy和PyCuda以及之前介绍过的Numba,还可以使用MindSpore、PyTorch和Jax等成熟的深度学习框架,这里介绍了一种直接写CUDA Kernel函数的方案。为了能够做到CUDA-C和Python编程的分离,这里引入了Cython作为中间接口,这样一来Python开发者和C开发者可以去共同开发相应的高性能方法。
版权声明
本文首发链接为:https://www.cnblogs.com/dechinphy/p/cython-cuda.html
作者ID:DechinPhy
更多原著文章:https://www.cnblogs.com/dechinphy/
请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html
使用Cython调用CUDA Kernel函数的更多相关文章
- CUDA学习,第一个kernel函数及代码讲解
前一篇CUDA学习,我们已经完成了编程环境的配置,现在我们继续深入去了解CUDA编程.本博文分为三个部分,第一部分给出一个代码示例,第二部分对代码进行讲解,第三部分根据这个例子介绍如何部署和发起一个k ...
- VS2013 VC++的.cpp文件调用CUDA的.cu文件中的函数
CUDA 8.0在函数的调用中方便的让人感动.以下是从网上学到的VC++的.cpp文件调用CUDA的.cu文件中的函数方法,和一般的VC++函数调用的方法基本没差别. 使用的CUDA版本为CUDA 8 ...
- 如何在cuda内核函数中产生随机数(host端调用,device端产生)
最近,需要在kernel函数中调用浮点型的随机数.于是上网搜了下相关资料,一种方式是自己手动写一个随机数的__device__函数,然后在调用的时候调用这个函数.另一种,原来cuda在toolkit中 ...
- 【VS开发】【CUDA开发】如何在MFC中调用CUDA
如何在MFC中调用CUDA 有时候,我们需要在比较大的项目中调用CUDA,这就涉及到MFC+CUDA的环境配置问题,以矩阵相乘为例,在MFC中调用CUDA程序.我们参考罗振东iylzd@163.com ...
- C++使用类调用CUDA核函数
正如CUDA C所称,CUDA对C语言进行了很好的扩展,直接使用C语言可以非常简单方便的调用CUDA核函数.但是当想使用C++的类成员函数直接调用核函数是不可行的,第一,核函数不能作为类的成员函数,第 ...
- linux字符设备驱动中内核如何调用驱动入口函数 一点记录
/* 内核如何调用驱动入口函数 ? *//* 答: 使用module_init()函数,module_init()函数定义一个结构体,这个结构体里面有一个函数指针,指向first_drv_init() ...
- ASP.NET后台调用前台JS函数的三种常见方法
第一种:使用普通的添加控件中的Attributes属性进行调用 例如,像一般的普通的按钮:Button1.Attributes.Add("onclick","MyFun( ...
- unity中三种调用其他脚本函数的方法
第一种,被调用脚本函数为static类型,调用时直接用 脚本名.函数名()第二种,GameObject.Find("脚本所在的物体的名字").SendMessage(" ...
- MyEclipse调用Matlab打包函数
本文部分内容参考了http://www.360doc.com/content/15/1103/16/1180274_510463048.shtml 一.检查Java环境 对于已经装上JAVA环境的计算 ...
- C#调用Windows API函数截图
界面如下: 下面放了一个PictureBox 首先是声明函数: //这里是调用 Windows API函数来进行截图 //首先导入库文件 [System.Runtime.InteropServices ...
随机推荐
- C++笔记(2)拷贝构造函数
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象. 如果在类中没有定义拷贝构造函数,编译器会自行定义一个.如果类带有指针变量,并有动态内存分配,则它必 ...
- Advanced .Net Debugging 9:平台互用性
一.介绍 这是我的<Advanced .Net Debugging>这个系列的第九篇文章.这篇文章的内容是原书的第二部分的[调试实战]的第七章[互用性].互用性包含两个方面,第一个方面就是 ...
- monaco-editor 实现SQL编辑器
原文链接:https://www.yuque.com/sxd_panda/antv/editor 安装 yarn add monaco-editor 或 npm install monaco-edit ...
- .net framework 使用Apollo 配置中心
参照了:https://www.cnblogs.com/xichji/p/11324893.html Apollo默认有一个"SampleApp"应用,"DEV" ...
- 简单易懂的JSON框架
分享一个由本人编写的JSON框架. JSON反序列化使用递归方式来解析JSON字符串,不使用任何第三方JAR包,只使用JAVA的反射来创建对象(必须要有无参构造器),赋值,编写反射缓存来提升性 ...
- golang执行命令 && 实时获取输出结果
背景 golang可以获取命令执行的输出结果,但要执行完才能够获取. 如果执行的命令是ssh,我们要实时获取,并执行相应的操作呢? 示例 func main() { user := "roo ...
- HunggingFace的镜像加速站
方法一:使用huggingface 官方提供的 **huggingface-cli** 命令行工具.(1) 安装依赖pip install -U huggingface_hub (2) 基本命令示例: ...
- 使用Python爬取公众号的合集内容
使用Python爬取公众号的合集 前言 ...最近老是更新关于博客的文章,很久没更新其他的了,然后写一下如何爬取微信公众号里面的图片吧! 先看看微信公众号的样子吧: 我爬取的是公众号的合集内容 讲解 ...
- 【论文阅读】ICRA2021: VDB-EDT An Efficient Euclidean Distance Transform Algorithm Based on VDB Data Struct
参考与前言 Summary: 浩哥推荐的一篇 无人机下的建图 and planning实验 Type: ICRA Year: 2021 论文链接:https://arxiv.org/abs/2105. ...
- NXP i.MX 8M Plus工业开发板规格书(四核ARM Cortex-A53 + 单核ARM Cortex-M7,主频1.6GHz)
1 评估板简介 创龙科技TLIMX8MP-EVM是一款基于NXP i.MX 8M Plus的四核ARM Cortex-A53 + 单核ARM Cortex-M7异构多核处理器设计的高性能工业评估板 ...