CUDA で並列化しようとしているループがあります。次のようになります。
float *buf = new float[buf_size]; // buf_size <= 100
for (int j; j<N; j++){
caluculate_with(buf);
}
delete [] buf;
ループの性質は、各反復の開始時にバッファ配列の値が問題にならないことです。そのため、ループ自体はごく簡単に並列化できます。
しかし、CUDA では、カーネルへの非同期呼び出しのために、はるかに大きなバッファーが必要になりました。
void __global__ loop_kernel(float *buf_gpu) {
const int idx = index_gpu(blockIdx, blockDim, threadIdx);
float *buf = buf_gpu + (idx*buf_size);
caluculate_with(buf);
}
....
float * buf_gpu;
cudaMalloc(&buf_gpu,sizeof(float)*N*buf_size);
loop_kernel<<<mesh,block>>>(buf_gpu);
cudaFree(buf_gpu);
}
カーネルへの各呼び出しはバッファの独自のセグメントを取得するため、バッファ サイズはループ サイズ N に合わせてスケーリングされますが、これは明らかな問題です。(バッファ サイズ) の量のメモリを使用する代わりに、(バッファ サイズ * ループ サイズ) を割り当てる必要があります。私の GTX590 の GPU メモリ制限は、私が取り組んでいる問題の N の典型的な値に達しています)。
編集:私の他の試みについて詳しく説明します。buf_size はそれほど大きくないので、カーネルを次のように書き直してみました。
void __global__ loop_kernel() {
float *buf = new float[buf_size];
caluculate_with(buf);
delete [] buf;
}
...
assert(cudaSuccess == cudaDeviceSetLimit(cudaLimitMallocHeapSize,8*1024*1024));
loop_kernel<<<mesh,block>>>();
assert(cudaSuccess == cudaDeviceSynchronize());
cudaDeviceSynchronize() アサーションは戻りステータス 4 で失敗します。それが何を意味するのかわかりません。