PyCUDA GPUArray 基于切片的操作

2 投票
2 回答
2392 浏览
提问于 2025-04-16 15:59

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)和内存交易的比率。

如果你在写内核时需要帮助,可以留言,我可以把答案扩展一下,给你一个大致的原型。

撰写回答