减少CUDA并行化中的内存损失

时间:2013-08-30 02:17:29

标签: cuda

我有一个循环,我试图在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.不知道这意味着什么。

1 个答案:

答案 0 :(得分:1)

你还没有告诉我们关于calculate_with()的任何信息,所以不清楚其中任何一项是否可以并行化,但这肯定是值得研究的。

然而,一种方法是简单地将缓冲区大小限制为GPU内存可以处理的内容,然后根据缓冲区大小在循环中调用内核:

void __global__ loop1_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)*num_buffs*buf_size);
for (int j=0; j<(N/num_buffs; j++){
  loop_kernel<<<mesh,block>>>(buf_gpu);
  cudaMemcpy(host_data, buf_gpu, (sizeof(float)*num_buffs*buf_size), cudaMemcpyDeviceToHost);
  }
cudaFree(buf_gpu);
}

显然,cudaMemcpy行只需要是实际生成的需要从内核操作中保存的数据。