使用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 ...
随机推荐
- 椭圆曲线密码学(ECC)加解密,附带python代码
想起来很久没写博客了,刚好今天要写实验报告,随便把之前的也完成吧 1.椭圆曲线概念 椭圆曲线在经过化解后,可以用这条式子表达:E:y²=x³+ax+b 其背后的密码学原理,是基于椭圆曲线离散对数问题, ...
- 如何使用Node.js、TypeScript和Express实现RESTful API服务
Node.js是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Express是一个保持最小规模的灵 ...
- 日常Bug排查-MVCC和for update混用导致读数据不一致
日常Bug排查-MVCC和for update混用导致读数据不一致 前言 日常Bug排查系列都是一些简单Bug的排查.笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材. Bug现场 又是喜闻 ...
- idea 使用 mvn clean package 报错 Could not create local repository at
使用 mac 版本的 idea 打包使用打包命令 mvn clean package 总是报错: [ERROR] Could not create local repository at /Repos ...
- WXS 模块
https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxs/01wxs-module.html 2.1.概述 WXS(Wei ...
- LeetCode 699. Falling Squares 掉落的方块 (Java)
题目: On an infinite number line (x-axis), we drop given squares in the order they are given. The i-th ...
- C#.NET 使用HttpWebRequest发送JSON
方法: public static string HttpPostJson(string url, string postStr, int timeOut, string charset) { Htt ...
- 说一下 session 的工作原理?
session 的工作原理是客户端登录完成之后,服务器会创建对应的 session,session 创建完之后,会把 session 的 id 发送给客户端,客户端再存储到浏览器中.这样客户端每次访问 ...
- 三月二十一日 安卓app个人作业开发
已经完成了 登录 和 注册逻辑 目前还有 提交打卡记录 的 开始时间 和 结束时间没有弄好 还有个人打卡记录的显示问题 并且我希望增加 修改个人密码 显示个人信息 退出登录 返回页面 删除打卡记录 的 ...
- 【译】向您介绍改版的 Visual Studio 资源管理器
随着最近 Visual Studio 的资源管理器的改进,开发人员将得到一种全新的享受!我们非常激动地宣布重新设计的 Visual Studio 资源管理器,相信我们,它将改变游戏规则. 在 Visu ...