C配列に含まれる3の数を数えて出力する小さなプログラムをCUDAで作成しました。
#include <stdio.h>
#include <assert.h>
#include <cuda.h>
#include <cstdlib>
__global__ void incrementArrayOnDevice(int *a, int N, int *count)
{
int id = blockIdx.x * blockDim.x + threadIdx.x;
//__shared__ int s_a[512]; // one for each thread
//s_a[threadIdx.x] = a[id];
if( id < N )
{
//if( s_a[threadIdx.x] == 3 )
if( a[id] == 3 )
{
atomicAdd(count, 1);
}
}
}
int main(void)
{
int *a_h; // host memory
int *a_d; // device memory
int N = 16777216;
// allocate array on host
a_h = (int*)malloc(sizeof(int) * N);
for(int i = 0; i < N; ++i)
a_h[i] = (i % 3 == 0 ? 3 : 1);
// allocate arrays on device
cudaMalloc(&a_d, sizeof(int) * N);
// copy data from host to device
cudaMemcpy(a_d, a_h, sizeof(int) * N, cudaMemcpyHostToDevice);
// do calculation on device
int blockSize = 512;
int nBlocks = N / blockSize + (N % blockSize == 0 ? 0 : 1);
printf("number of blocks: %d\n", nBlocks);
int count;
int *devCount;
cudaMalloc(&devCount, sizeof(int));
cudaMemset(devCount, 0, sizeof(int));
incrementArrayOnDevice<<<nBlocks, blockSize>>> (a_d, N, devCount);
// retrieve result from device
cudaMemcpy(&count, devCount, sizeof(int), cudaMemcpyDeviceToHost);
printf("%d\n", count);
free(a_h);
cudaFree(a_d);
cudaFree(devCount);
}
私が得る結果は次のとおりです。
4 つのスレッドを使用して CPU で実行すると、次のようになります。 real 0m0.101s user 0m0.100s sys 0m0.024s
GPU は古いものであることに注意してください。ルート アクセス権がないため正確なモデルはわかりませんが、実行する OpenGL のバージョンは MESA ドライバーを使用する 1.2 です。
私は何か間違ったことをしていますか?より速く実行するにはどうすればよいですか?
注: ブロックごとにバケットを使用してみました (そのため、atomicAdd() はそれぞれのブロックで削減されます) が、まったく同じパフォーマンスが得られます。また、このブロックに割り当てられている 512 の整数をメモリの共有ブロックにコピーしようとしましたが (コメントで確認できます)、時間は再び同じです。