使用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 ...
随机推荐
- 阿里云ECS后台CPU占用100%,top却找不到
上周公司阿里云服务器后台报警,CPU占用瞬间飙升到100%: 首先想到使用top命令查询CPU占用详情: 发现进程占用CPU都比较低,在CPU占用一栏发现只有ni的占用比较高. 先了解一下CPU相关监 ...
- php基本语法与安装
// 什么是PHP // PHP 是 后端语言的一种 // 主要作用就是实现数据交互 // ...
- INFINI Console 与华为鲲鹏完成产品兼容互认证
何为华为鲲鹏认证 华为鲲鹏认证是华为云围绕鲲鹏云服务(含公有云.私有云.混合云.桌面云)推出的一项合作伙伴计划,旨在为构建持续发展.合作共赢的鲲鹏生态圈,通过整合华为的技术.品牌资源,与合作伙伴共享商 ...
- 项目管理--PMBOK 读书笔记(9)【项目资源管理】
1.团队成员的角色与职责: 1)层级结构(OBS):与 WBS 交叉确认部门的全部项目指责,项目组织结构图: 2)矩阵结构(RAM):工作包(活动)与项目团队的关系,主要用于明确角色与期望(职责) 3 ...
- vite+vue3+ts+elementPlus前端框架搭建 [三] router路由管理
路由包括动态路由.静态路由两种,本文中以静态路由的方式实现了动态路由. 1. 创建Router 在Src目录下创建router文件夹,并在router文件夹下创建index.ts文件. index.t ...
- uni-app apple store 上传新版本审核被拒绝 Guideline 5.1.1
- Legal - Privacy - Data Collection and Storage We noticed that your app requests the user's consent ...
- 牛客小白月赛96(待F)
比赛链接:牛客小白月赛96 赛时感受 赛时在前面卡的时间有点长,C题没开longlong wa了n发,D题没考虑负数又wa了n发,然后来写E的时候时间就不长了,匆忙写一次交一发. A 思路 当其中一个 ...
- [OC]一个括号新建一个类
[OC]一个括号新建一个类 特别说明 以下代码仅仅用于说明用途,命名也不是特别规范,小朋友不要模仿哦. 前言 在iOS开发中,我们会经常用到这么一段代码: UIView *myView = [UIVi ...
- mysql的varchar和oracle的varchar2比较
首先说结论: 1.mysql存储的是字符数(不分语言) 2.oracle存储的需要看定义,如果定义为varchar2(n),则默认是n个字节,如果是varchar2(n char)则是n个字节. 3. ...
- 实验13.Nat转发telnet实验
# 实验13.Nat转发telnet实验 本节用于测试NAT服务,用于将流量转发到内网的指定设备上. 实验组 配置路由器 由于之前配置过ospf,所以这次用直接指静态练手,首先确保全网畅通 R3 GW ...