使用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 resres = 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函数。

其他调用方法

前面提到,我们也可以在C程序中直接调用这个CUDA函数。例如在上面我们编译好libhello.so的CUDA动态链接库之后,

#include <dlfcn.h>int main()
{void* handle = dlopen("./libhello.so", RTLD_LAZY);int (*helloFromGPU)();helloFromGPU = dlsym(handle, "main");helloFromGPU();dlclose(handle);return 1;
}

然后使用如下指令编译成一个可执行文件:

$ gcc -o hello_c hello_c.c -ldl

再执行这个可执行文件,可以得到跟Python程序类似的打印结果。

总结概要

从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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/776610.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WEEK5|WEB Unserialize Again

进入后是一个文件上传但是这里并没有漏洞点看cookie得到源码<?php highlight_file(__FILE__); error_reporting(0); class story{private $user=admin;public $pass;public $eating;public $God=false;public function __wakeup(){$this->user=human;if(1==1){die();}…

PixiJS源码分析系列:第四章 响应 Pointer 交互事件(上篇)

响应 Pointer 交互事件(上篇) 上一章我们分析了 sprite 在 canvasRenderer 上的渲染,那么接下来得看看交互上最重要的事件系统了最简单的 demo 还是用一个最简单的 demo 演示 example/sprite-pointerdown.html 为 sprite 添加一个 pointerdown 事件,即点击事件,移动设备上就…

最新SEO自动外链蜘蛛池工具促进百度快速收录使用方法介绍

此工具集成市面上所有自动外链网站的资源链接,经过合并、去重、筛选、验证 总结出最终的外链资源 ,软件实时更新本软件将您繁杂的外链推广转为自动化进行,并且加入站群的支持,您只需要将你的站群域名粘贴到软件里,点击开始按钮就可以了软件会自动轮刷您的每一个网站软件效…

Markdown入门指南

Markdown入门指南HelyaHsiung2021.9.27SRE IN UESTC1.The Title of Markdown (1) Denote title using = or - First title ===========Second title -----------(2) Denote title using # # First title ## Second title ### Third title #### Fourth title ##### Fifth titl…

BGP属性 ASPath

BGP属性 ASPath AS_PATH 属性 BGP路由的必遵属性; AS间防环属性; 用于BGP路由的路径选择,当经过多条路径到达莫网络的情况,会选择经过ASpath 较少的作为最优; 顺序的记录了某条BGP路由所经过的AS信息,每经过一个AS会在ASPath 属性的最左边…

功能强大的电路设计与仿真软件Multisim 14.3安装教程

一款功能强大的电路设计与仿真软件Multisim是一款强大的电子电路仿真软件,广泛应用于电子工程和教育领域。本教程全面细致地解析了原理图设计、电路仿真以及虚拟仪器测试等核心功能,通过友好易学的界面设计,为用户打造了一款高效便捷的电路设计和分析工具,助您轻松掌握电路…

图书《数据资产管理核心技术与应用》分享

《数据资产管理核心技术与应用》是由清华大学出版社出版的一本图书,该图书主要特点如下: 1、依托于大数据技术,独家加密数据血缘的底层技术实现 2、详解数据资产管理的知识体系和核心技术 3、应用元数据管理和数据建模技术,充分发挥出数据资产的更大潜力和价值。 4、全书从…

山东省威海市台依村,杨文召——老赖!!!

山东省威海市台依村,杨文召——老赖!!!认识下老赖的家人!!!

MQ高级

消息的可靠性:一个消息发送出去以后至少被消费一次 丢失场景:消息发送时候丢失,mq崩了消息丢失,消费者把消息搞丢了(交易服务) 解决方法针对以上三个场景和兜底方案 1、发送者可靠性 消息从生产者到消费者的每一步都可能导致消息丢失: - 发送消息时丢失: - 生产者发送…

VitePress安装总结

1、安装node.js 2、安装vscode,并在扩展中安装markdown插件 3、在vscode的终端中修改淘宝镜像源:1npm config set registry https://registry.npmmirror.com4、在终端中输入1npm add -D vitepress5、在D盘创建文件夹,右键用vscode打开,或在vscode中打开文件夹 6、在终端中执…

哪位大佬知道为啥最后计数是0吗? 实际是有数据的

大家好,我是Python进阶者。 一、前言 前几天在Python白银交流群【Jethro Shen】问了一个Python数据处理的问题,问题如下:哪位大佬知道为啥最后计数是0吗?实际是有数据的二、实现过程 这里【瑜亮老师】给了一个指导,如下所示:这不是发生错误了么?你设置的发生错误return …

JDK、JRE和JVM简述

JDK(Java Development Kit) JDK是Java开发环境的核心组件,包括:Java编译器、JRE(Java运行环境)JavaDoc文档生成器和其他一些工具。 JDK是Java程序员开发Java应用程序所必需的软件包。 JRE(Java Runtime Environment) 也称为Java运行环境,它是Java应用程序运行的基础。…