pycuda,cuda - 一些问题和一个简单的代码,给我错误“标识符”N“未定义”

时间:2011-12-01 11:43:25

标签: cuda pycuda

我正在尝试学习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个线程??网格大小,大小(16,16)表示256个块?

4)我试图在pycuda做一个来自'cuda by a book 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“未定义”

谢谢!

1 个答案:

答案 0 :(得分:2)

我使用pycuda的方式以及我认为它的使用方式是作为python和cuda之间的桥接接口。它不是python-&gt; 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-&gt; python-&gt; c ++,我认为你不需要在中间使用python。

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

编辑:

回答你的一些评论:

是块(4,1,1)是一维的,块(4,4,1)是2D。

我修复了你的代码,你只需要将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的所有不同部分的粘合剂。它可以帮助你编译分配内存,运行你的内核等...只要你这样使用它就可以了。