2

私はpycudaを学ぼうとしていますが、理解しようとしている質問がいくつかあります。私の主な質問は、pycuda と cuda ファイル内の関数の間で通信する方法だと思います。

したがって、C++ ファイル (cuda ファイル) があり、そこにいくつかの関数があり、そのうちの 1 つに pycuda を実装したい場合、たとえば、いくつかの配列を含み、計算を行う関数「compute」が必要だとしましょう。それら.私のアプローチは何ですか?

1) Python で配列を初期化し、メモリを GPU に割り当て、データを GPU に転送します。

2) pycuda から mod=SourceModule(""" global void ......""") を呼び出します。

今、私は尋ねたいです:私はこのモジュールをどのように処理しますか?私はそれにすべての「計算」機能を入れますか?なぜなら、「グローバル」でいくつかの計算を行うだけなら、pycudaとの間で通信する方法がわからないからですc++ 関数。結果を c++ ファイル (cuda ファイル) に戻す方法。

3) cuda では、スレッドの数を「blockDIm」として、ブロックの数を「gridDim」として持っています。 size(16,16) は 256 ブロックを意味しますか?

4) ベクトルを追加する 'cuda by an example book' の例を pycuda で実行しようとしました。コードは以下のとおりです。

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のようなものを見る必要があります。GPUとのインターフェイスにc++コード内でpycudaを使用するのではなく、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)はいblock(4,4,1)は16スレッドで、grid(16,16)は256ブロックです。

編集:

あなたのコメントのいくつかに答えるために:

はい、ブロック(4,1,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でのさまざまな作業をすべてつなぐ接着剤として機能するということです。これは、メモリの割り当てをコンパイルしたり、カーネルを実行したりするのに役立ちます...このように使用している限り、問題はありません。

于 2011-12-01T15:49:15.013 に答える