2012-03-30 10 views
2

A [x] [y] = sum {z = 0からz = n}まで{B [x] [y] [z] + C [x]行列Aは次元[高さ] [幅]、行列BはCは次元[高さ] [幅] [n]を有する。サム3D行列の合計

index = 0; 
for (z = 0; z<n; ++z) 
    for(y = 0; y<width; ++y) 
     for(x = 0; x<height; ++x) { 
      matrix[index] = value; 
      index++; 
     } 

Q1:

値は、のようなもので、メモリにマッピングされ、このクーダカーネルは大丈夫でしょうか?

idx = blockIdx.x*blockDim.x + threadIdx.x; 
idy = blockIdx.y*blockDim.y + threadIdx.y; 

for(z=0; z<n; z++){ 
    A[idx*width+idy] += B[idx*width+idy+z*width*height] + C[idx*width+idy+z*width*height]; 
} 

Q2:これは計算を高速化しますか?

idx = blockIdx.x*blockDim.x + threadIdx.x; 
idy = blockIdx.y*blockDim.y + threadIdx.y; 
idz = blockIdx.z*blockDim.z + threadIdx.z; 

int stride_x = blockDim.x * gridDim.x; 
int stride_y = blockDim.y * gridDim.y; 
int stride_z = blockDim.z * gridDim.z; 

while (idx < height && idy < width && idz < n) { 
    atomicAdd(&(A[idx*width+idy]), B[idx*width+idy+idz*width*height] + C[idx*width+idy+idz*width*height]); 
    idx += stride_x; 
    idy += stride_y; 
    idz += stride_z; 
} 

答えて

1

Q1:非常に大きな行列を使用するときに問題がある可能性があります:あなたは答え

備考を知っている行列でそれをテストします。適切な増分でwhileループを使用します。 Example by Cudaはいつものように参考書です。

ネストループを実装する例は、For nested loops with CUDAです。そこにはwhileループが実装されています。

marina.kは競合状態です。それは、原子操作がコードを遅くする傾向があるので、アプローチ1を好むでしょう。

+0

最大次元数= 2(CC用<2)= 3(CCため> = 2)。だから私は問題はないと思う。私は大きな行列を持っていますが、問題は見えません。 – user1281071

+0

よかったです。私は自分の答えを更新しました。 – Azrael3000

+0

あなたは次のようにします: 'if(idx> = height || idy> = width || idz> = n)return;'? – user1281071

2

最初のカーネルは問題ありません。しかし、マトリックスBCへのアクセスを統合していません。

第2カーネル機能については、 1つのスレッドだけでなく、A[idx*width+idy]のアドレスに書き込むことができるデータ競合の原因があります。 AttomicAdd

一般的な質問: 私は実験がより良いことを示すと思います。それはあなたが持っている典型的なマトリックスサイズに依存します。 Fermi < 1024の最大スレッドブロックサイズと、行列のサイズが大きい場合は、多くのスレッドブロックが宝石であることに注意してください。通常は(スレッドブロックが多い)処理が遅くなります。 ArrayFire

+0

データレーシングで良い点、thx :) アトミック関数を追加すると、Q2のコードフォームはQ1のコードとまったく同じになりますか? 私の主な目標はスピードですので、私は最速の解決策を探しています。 – user1281071

+0

私は自分の答えを編集しました。 – geek

+0

"実験はそれがより良いことを示す"、それは原子の関数を使用する方が良いですか?またはそれを使用しない? – user1281071

2

実簡単:スレッドブロック= 3、スレッドブロックのグリッドの最大次元の

array A = randu(nx,ny,nz); 
array B = sum(A,2); // sum along 3rd dimension 
print(B);