2

我正在尝试学习 pycuda,并且我有一些我想了解的问题。我认为我的主要问题是如何在 pycuda 和 cuda 文件中的函数之间进行通信。

所以,如果我有一个 C++ 文件(cuda 文件)并且在其中我有一些函数,我想在其中一个中实现 pycuda。例如,假设我想要包含一些数组的函数“compute”并进行计算他们。我的方法是什么?

1)在python中初始化数组,为GPU分配内存并将数据传输到GPU。

2)从pycuda调用mod=SourceModule(""" global void ......""")。

现在,我想问:我将如何处理这个模块?我会把所有的“计算”功能放在里面?因为,如果只是在“全局”中进行一些计算,我不知道如何在 pycuda 和c++ 函数。我如何将结果传递回 c++ 文件(cuda 文件)。

3)在cuda中,我们有线程数为'blockDIm'和块数为'gridDim'。在pycuda中?我们有块大小,块(4,4,1),这意味着16个线程??网格大小, size(16,16) 表示 256 个块?

4)我试图在pycuda中做一个来自'cuda by an example book'的例子,它添加了向量。代码如下:

import pycuda.driver as cuda
import pycuda.autoinit
from pycuda.compiler import SourceModule
import scipy as sc



N=50*1024

a=sc.arange(0,N).astype(sc.float32)
a_gpu = cuda.mem_alloc(a.nbytes) #allocate memory on GPU
cuda.memcpy_htod(a_gpu, a) #transfer data to the GPU

b=sc.array([i**2 for i in range(0,N)]).astype(sc.float32)
b_gpu = cuda.mem_alloc(b.nbytes)#allocate memory on GPU
cuda.memcpy_htod(b_gpu, b) #transfer data to the GPU

c=sc.zeros(N).astype(sc.float32)
c_gpu = cuda.mem_alloc(c.nbytes)#allocate memory on GPU


mod =SourceModule("""
   __global__ void add(int*a,int *b,int *c){
      int tid=threadIdx.x + blockIdx.x*gridDim.x;
        while (tid<N){
    c[tid]=a[tid]+b[tid];
    tid+=blockDim.x*gridDim.x;
         }
           }
            """)

#call the function(kernel)
func = mod.get_function("add")
func(a_gpu,b_gpu,c_gpu, block=(16,16,1),grid=(16,16))

#transfer data back to CPU
cuda.memcpy_dtoh(c, c_gpu)

但它给了我一个错误:“标识符“N”未定义“

谢谢!

4

1 回答 1

2

我使用 pycuda 的方式以及我认为它打算使用的方式是作为 python 和 cuda 之间的桥梁接口。它不是 python->c++ 接口工具。为此,您将不得不查看类似SWIG的内容。我不会在 c++ 代码中使用 pycuda 与 GPU 交互,而是使用 pycuda 对我的应用程序进行原型设计或设计,然后将其转移到仅使用 c++。

考虑到这一点,我将尝试解决您的问题

1)使用 Pycuda,您还可以使用 gpuarray 模块,该模块将为您分配和传输步骤,因此您可以实例化它们并在 GPU 中使用它们:

import pycuda.gpuarray as gpuarray
a = gpuarray.arange(400, dtype=numpy.float32)
b = gpuarray.arange(400, dtype=numpy.float32)
#call Cuda function pass 'a' and 'b' 
resulta = a.get()
resultb = b.get()

2)再次强调,pycuda 不是 c++ 接口。如果你需要从 cuda->python->c++ 得到结果,我认为你不需要中间的 python。

3)是块(4,4,1)是16个线程,网格(16,16)是256个块。

编辑:

回答您的一些评论:

是的,块(4,1,1)是一维的,块(4,4,1)是二维的。

我修复了你的代码,你只需要将 N 传递给 CUDA 内核。

import pycuda.driver as cuda
import pycuda.autoinit
from pycuda.compiler import SourceModule
import scipy as sc



N=50*1024

a=sc.arange(0,N).astype(sc.float32)
a_gpu = cuda.mem_alloc(a.nbytes) #allocate memory on GPU
cuda.memcpy_htod(a_gpu, a) #transfer data to the GPU

b=sc.array([i**2 for i in range(0,N)]).astype(sc.float32)
b_gpu = cuda.mem_alloc(b.nbytes)#allocate memory on GPU
cuda.memcpy_htod(b_gpu, b) #transfer data to the GPU

c=sc.zeros(N).astype(sc.float32)
c_gpu = cuda.mem_alloc(c.nbytes)#allocate memory on GPU


mod = SourceModule("""
   __global__ void add(int*a,int *b,int *c, int N){
      int tid=threadIdx.x + blockIdx.x*gridDim.x;
        while (tid<N){
    c[tid]=a[tid]+b[tid];
    tid+=blockDim.x*gridDim.x;
         }
           }
            """)

#call the function(kernel)
func = mod.get_function("add")
func(a_gpu,b_gpu,c_gpu, sc.int32(N), block=(16,16,1),grid=(16,16))

#transfer data back to CPU
cuda.memcpy_dtoh(c, c_gpu)
print c

另一种方法是在 SourceModule 上使用字符串替换:

mod = SourceModule("""
   __global__ void add(int*a,int *b,int *c){
      const int N = %d;
      int tid=threadIdx.x + blockIdx.x*gridDim.x;
        while (tid<N){
    c[tid]=a[tid]+b[tid];
    tid+=blockDim.x*gridDim.x;
         }
           }
            """ % (N))

最后一点是,当您使用 Pycuda 时,它通常用作将 CUDA 的所有不同部分连接在一起的粘合剂。它可以帮助您编译分配内存、运行内核等...只要您像这样使用它就可以了。

于 2011-12-01T15:49:15.013 回答