それが可能かどうか疑問に思っていました.CUDAのスレッドを使用して配列からセルを読み取る最良の方法は何ですか. 私が意味することを簡単にするために、これは例です:
{1,2,3,4,5,6,...} という配列があり、主にそのサイズに応じて、各スレッドが配列の n 個のセルを読み取るようにしたいと考えています。
私はいくつかのことを試してきましたが、うまくいかないようですので、誰かがそれを行う(正しい)方法を指摘できれば、それは素晴らしいことです.
ありがとうございました。
一般に、連続するスレッドが連続する配列インデックスを読み取れるようにする必要があります。これを行うと、「結合された」メモリ トランザクションが発生します。簡単に考えると、32 個のスレッドが物理的に並列に実行されていて、それらすべてが 1 つのロードを実行し、32 個のロードすべてが同じキャッシュ ラインに分類される場合、単一のメモリ アクセスを実行してキャッシュ ラインを埋めることができます。 、32個の個別のものではなく。
したがって、次のように、各スレッドn
がスレッドの数だけストライドされたセルにアクセスするようにする必要があります (入力データがfloat
arrayにあると仮定しますdata
)。
int idx = blockDim.x * blockIdx.x + threadIdx.x;
int stride = blockDim.x * gridDim.x;
for (int i = idx; i < numElements; i += stride) {
float element = data[i];
process(element);
}
アルゴリズムで各スレッドがn
連続したデータ要素を読み取る必要がある場合は、結合されていないロードが発生し、コストが大幅に高くなります。この場合、このタイプのアクセスが不要になるように、アルゴリズムを再設計することを検討します。
必要がある:
スレッドは n 個の次の数字を見る必要があります
したがって、次を使用できます。
#define N 2
#define NTHREAD 1024
#define ARRAYSIZE N*NTHREAD
// develop the kernel as:
__global__ void accessArray(int *array){
int tid = blockDim.x * blockIdx.x + threadIdx.x;
int startId = tid*N;
// access thread's stride
for(int i=0; i<N; i++){
array[startId+i]=tid;
}
}
// call the kernel by:
accessArray<<<NTHREAD/256, 256>>>(d_array);
をダンプして、array
それがスレッドの動作方法であるかどうかを確認してください。
完全なコード:
#include <cuda.h>
#include <stdio.h>
#define N 2
#define NTHREAD 1024
#define ARRAYSIZE N*NTHREAD
// develop the kernel as:
__global__ void accessArray(int *array){
int tid = blockDim.x * blockIdx.x + threadIdx.x;
int startId = tid*N;
// access thread's stride
for(int i=0; i<N; i++){
array[startId+i]=tid;
}
}
int main()
{
int h_array[ARRAYSIZE];
int *d_array;
size_t memsize= ARRAYSIZE * sizeof(float);
for (int i=0; i< ARRAYSIZE; i++) {
h_array[i] = 0;
}
cudaMalloc(&d_array, memsize);
cudaMemcpy(d_array, h_array, memsize, cudaMemcpyHostToDevice);
accessArray<<<NTHREAD/256, 256>>>(d_array);
cudaMemcpy(h_array, d_array, memsize, cudaMemcpyDeviceToHost);
for (int i=0; i<ARRAYSIZE; i++)
printf("A[%d] => %d\n",i,h_array[i]);
cudaFree(d_array);
}