在我的旧geforce 8800GT上使用内存时,我总是有一个奇怪的0.04 ms开销。我需要将〜1-2K传输到不断记忆的设备,在其上使用该数据,并从设备中获得一个浮点值。
我使用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 ms)。奇怪的是,当我尝试做更多的内存工作(添加其他cudamemcpytosymbolasync和cudamemcpyasync调用)时,我会得到每个呼叫的额外时间。它与这个人的研究相对应:http://www.cs.virginia.edu/~mwb7w/cuda_support/memory_transfer_overhead.html
他还将1K块到GPU的1K块获得了0.01毫秒。那么,0.04 ms(0.05-0.01)的开销来自哪里?有任何想法吗?可能是我应该在较新的卡上尝试此代码?
在我看来,在cudadevicesynchronize和CPU代码之后,我的geforce进入了某种节能模式或类似的东西。
我建议您增加要实现的线程数
//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内存),请使用循环。但是,减少它们。