使用Python写CUDA程序的方法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
使⽤Python写CUDA程序的⽅法
使⽤Python写CUDA程序有两种⽅式:
* Numba
* PyCUDA
numbapro现在已经不推荐使⽤了,功能被拆分并分别被集成到accelerate和Numba了。
例⼦
numba
Numba通过及时编译机制(JIT)优化Python代码,Numba可以针对本机的硬件环境进⾏优化,同时⽀持CPU和GPU的优化,并且可以和Numpy集成,使Python代码可以在GPU上运⾏,只需在函数上⽅加上相关的指令标记,
如下所⽰:
import numpy as np
from timeit import default_timer as timer
from numba import vectorize
@vectorize(["float32(float32, float32)"], target='cuda')
def vectorAdd(a, b):
return a + b
def main():
N = 320000000
A = np.ones(N, dtype=np.float32 )
B = np.ones(N, dtype=np.float32 )
C = np.zeros(N, dtype=np.float32 )
start = timer()
C = vectorAdd(A, B)
vectorAdd_time = timer() - start
print("c[:5] = " + str(C[:5]))
print("c[-5:] = " + str(C[-5:]))
print("vectorAdd took %f seconds " % vectorAdd_time)
if __name__ == '__main__':
main()
PyCUDA
PyCUDA的内核函数(kernel)其实就是使⽤C/C++编写的,通过动态编译为GPU微码,Python代码与GPU代码进⾏交互,如下所⽰:
import pycuda.autoinit
import pycuda.driver as drv
import numpy as np
from timeit import default_timer as timer
from piler import SourceModule
mod = SourceModule("""
__global__ void func(float *a, float *b, size_t N)
{
const int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i >= N)
{
return;
}
float temp_a = a[i];
float temp_b = b[i];
a[i] = (temp_a * 10 + 2 ) * ((temp_b + 2) * 10 - 5 ) * 5;
// a[i] = a[i] + b[i];
}
""")
func = mod.get_function("func")
def test(N):
# N = 1024 * 1024 * 90 # float: 4M = 1024 * 1024
print("N = %d" % N)
N = np.int32(N)
a = np.random.randn(N).astype(np.float32)
b = np.random.randn(N).astype(np.float32)
# copy a to aa
aa = np.empty_like(a)
aa[:] = a
# GPU run
nTheads = 256
nBlocks = int( ( N + nTheads - 1 ) / nTheads )
start = timer()
func(
drv.InOut(a), drv.In(b), N,
block=( nTheads, 1, 1 ), grid=( nBlocks, 1 ) )
run_time = timer() - start
print("gpu run time %f seconds " % run_time)
# cpu run
start = timer()
aa = (aa * 10 + 2 ) * ((b + 2) * 10 - 5 ) * 5
run_time = timer() - start
print("cpu run time %f seconds " % run_time)
# check result
r = a - aa
print( min(r), max(r) )
def main():
for n in range(1, 10):
N = 1024 * 1024 * (n * 10)
print("------------%d---------------" % n)
test(N)
if __name__ == '__main__':
main()
对⽐
numba使⽤⼀些指令标记某些函数进⾏加速(也可以使⽤Python编写内核函数),这⼀点类似于OpenACC,⽽PyCUDA需要⾃⼰写kernel,在运⾏时进⾏编译,底层是基于C/C++实现的。
通过测试,这两种⽅式的加速⽐基本差不多。
但是,numba更像是⼀个⿊盒,不知道内部到底做了什么,⽽PyCUDA就显得很直观。
因此,这两种⽅式具有不同的应⽤:
* 如果只是为了加速⾃⼰的算法⽽不关⼼CUDA编程,那么直接使⽤numba会更好。
* 如果为了学习、研究CUDA编程或者实验某⼀个算法在CUDA下的可⾏性,那么使⽤PyCUDA。
* 如果写的程序将来要移植到C/C++,那么就⼀定要使⽤PyCUDA了,因为使⽤PyCUDA写的kernel本⾝就是⽤CUDA
C/C++写的。
以上这篇使⽤Python写CUDA程序的⽅法就是⼩编分享给⼤家的全部内容了,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。