PyCUDA GPUArray 基于切片的操作
PyCUDA的文档对于我们这些“非高手”来说,示例有点少。我在想,关于gpuarrays的数组操作有哪些可用的功能,也就是说,如果我想把这个循环用gpuarray来实现;
m=np.random.random((K,N,N))
a=np.zeros_like(m)
b=np.random.random(N) #example
for k in range(K):
for x in range(N):
for y in range(N):
a[k,x,y]=m[k,x,y]*b[y]
在普通的Python中,处理这个问题的常见方法大概是这样的
for k in range(K):
for x in range(N):
a[k,x,:]=m[k,x,:]*b
但是我找不到简单的方法来用GPUArray实现这一点,除了自己写一个自定义的逐元素内核。即使这样,对于这个问题,内核中也必须有循环结构,而一旦复杂到这个程度,我可能还不如直接写一个完整的SourceModule内核。
有没有人能给我点提示?
2 个回答
2
你还可以使用 memcpy_dtod()
方法和 gpuarrays 的切片功能。奇怪的是,普通的赋值方式不管用。set()
也不行,因为它是把数据从主机传输到设备(使用 memcpy_htod()
)。
for k in range(K):
for x in range(N):
pycuda.driver.memcpy_dtod(a[k,x,:].gpudata, (m[k,x,:]*b).gpudata, a[k,x,:].nbytes)
2
这可能最好是用你自己的内核来完成。虽然PyCUDA的gpuarray类把GPU内存变得很方便,可以和numpy数组互换使用,但如果你想做一些除了现成的线性代数和并行归约操作以外的事情,就必须自己为GPU编写代码。
不过,写这样一个小内核其实很简单。简单到它可能会受到内存带宽的限制——你可能想试着把几个相似的操作“融合”在一起,这样可以稍微提高每秒浮点运算(FLOPS)和内存交易的比率。
如果你在写内核时需要帮助,可以留言,我可以把答案扩展一下,给你一个大致的原型。