pycuda核函数编写

105 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情

首先,虽然python有pycuda可以使用来进行GPU的加速,但是内核函数是C写的,哈哈,是不是很惊喜。之前说过了pycuda跟numpy差不多,对于矩阵运算那是手到擒来,但是想一下,如果。。。使用C写核函数??那岂不是很复杂!!不然就别加速了吧!!我开始也是这么想的。然后我拿了一个例子了解一下,没有想象的那么难,本博客从简单到复杂,慢慢的说一下核函数,以及如何编写核函数。

在python中,有两个函数可以用于函数式的编写,一个是map,另一个就是reduce了,他们可以根据所提供的函数来完成相应的操作。上来肯定不能直接拿reduce和map说,就先用最简单的lambda表达式吧。

import numpy as np

add_pow = lambda x: x ** 2 + x

print(add_pow(1))
print(add_pow(2))
print(add_pow(3))

代码的结果如下:

image.png

下面,开始拿map说事,map函数有两个输入,第一个是一个函数,第二个是一个给定的函数可以处理的对象列表,只是说很难理解,直接上一串代码进行理解。

import numpy as np

add_pow = lambda x: x ** 2 + x
res = map(add_pow, [1, 2, 4, 6])
print(list(res))

image.png

map是这个样子,reduce也是类似的操作,但是是有不同的,reduce接收列表之后会执行递归式的二元运算,然后输出一个单例。

下面开始写简单的核函数了

import numpy as np
import pycuda.autoinit
from pycuda import gpuarray
from pycuda.scan import InclusiveScanKernel

res2 = np.array(np.random.randint(1, 5, 4), dtype=np.int32)
gpu_res2 = gpuarray.to_gpu(res2)
mult = InclusiveScanKernel(np.int32, "a*b")
print(mult(gpu_res2).get())
print(np.cumprod(res2))

image.png

是不是足够简单,一个字符串就解决了!

然后,再逐渐扩展一点!既然是C语言,那么C语言中常用的比较大小的式子,放在这里能不能行呢?可以尝试一下,如果不行大不了报个错呗。

import numpy as np
import pycuda.autoinit
from pycuda import gpuarray
from pycuda.scan import InclusiveScanKernel

res2 = np.array(np.random.randint(1, 5, 4), dtype=np.int32)
gpu_res2 = gpuarray.to_gpu(res2)
mult = InclusiveScanKernel(np.int32, "a>b? a:b")
print("source:", res2)
print(mult(gpu_res2).get())

image.png

居然还真的可以,感觉像是打开了新世界的大门呐,哥们!都是科技与狠活呐!说难吗?也不难,说简单?!肯定不可能那么简单的,这个就是对核函数进行入门,更复杂的操作可以自己进行探索。