在我的旧GeForce 8800GT上使用CUDA中的内存时,总是有0.04毫秒的奇怪开销。我需要将~1KK传输到我的设备的恒定内存,在其上处理该数据并从设备获得一个浮点值。
我有一个使用GPU计算的典型代码:
//allocate all the needed memory: pinned, device global
for(int i = 0; i < 1000; i++)
{
//Do some heavy cpu logic (~0.005 ms long)
cudaMemcpyToSymbolAsync(const_dev_mem, pinned_host_mem, mem_size, 0, cudaMemcpyHostToDevice);
my_kernel<<<128, 128>>>(output);
//several other calls of different kernels
cudaMemcpy((void*)&host_output, output, sizeof(FLOAT_T), cudaMemcpyDeviceToHost);
// Do some logic with returned value
}
我决定使用此代码测量GPU内存的工作速度(评论所有内核调用,添加了cudaDeviceSynchronize
调用):
//allocate all the needed memory: pinned, device global
for(int i = 0; i < 1000; i++)
{
//Do some heavy cpu logic (~0.001 ms long)
cudaMemcpyToSymbolAsync(const_dev_mem, pinned_host_mem, mem_size, 0, cudaMemcpyHostToDevice);
cudaMemcpyAsync((void*)&host_output, output, sizeof(FLOAT_T), cudaMemcpyDeviceToHost);
cudaDeviceSynchronize();
// Do some logic with returned value
}
我测量了周期的执行时间并且得到~0.05秒(因此,每次迭代0.05毫秒)。奇怪的是,当我尝试做更多的内存工作(添加额外的cudaMemcpyToSymbolAsync和cudaMemcpyAsync调用)时,每次调用我得到额外的<0.01 ms时间。它与这个家伙的研究相对应:http://www.cs.virginia.edu/~mwb7w/cuda_support/memory_transfer_overhead.html
每次传输1K块到GPU时,他也获得了0.01 ms。 那么0.04毫秒(0.05 - 0.01)的开销是从哪里来的?有任何想法吗?可能是我应该在新卡上试用这段代码?
在我看来,在cudaDeviceSynchronize和CPU代码之后,我的GeForce进入了一些省电模式或类似的东西。
答案 0 :(得分:1)
我建议你增加你正在实现的线程数
//Use malloc() to allocate memory on CPU.
//Change mem_size to the total memory to be tranferred to GPU.
cudaMemcpyToSymbolAsync(const_dev_mem, pinned_host_mem, mem_size, 0, cudaMemcpyHostToDevice);
dim3 dimBlock(128,2);
dim3 dimGrid(64000,1);
my_kernel<<<dimGrid, dimBlock>>>(output);
//several other calls of different kernels
//change size field to 1000*sizeof(FLOAT_T)
cudaMemcpy((void*)&host_output, output, sizeof(FLOAT_T), cudaMemcpyDeviceToHost);
// Do some logic with returned value
如果代码崩溃(因为更多线程或更多GPU内存),请使用循环。但是,减少它们。