3

古い GeForce 8800GT で CUDA のメモリを操作すると、常に奇妙な 0.04 ミリ秒のオーバーヘッドが発生します。デバイスの定数メモリに〜1〜2Kを転送し、そのデータを操作して、デバイスからfloat値を1つだけ取得する必要があります。

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 ミリ秒の時間が追加されます。この男の研究に対応しています:http://www.cs.virginia.edu/~mwb7w/cuda_support/memory_transfer_overhead.html

彼はまた、GPU への 1K ブロックの転送ごとにこれらの 0.01 ミリ秒を得ました。では、その 0.04 ミリ秒 (0.05 - 0.01) のオーバーヘッドはどこから来たのでしょうか? 何か案は?このコードを新しいカードで試す必要がありますか?

cudaDeviceSynchronize と CPU コードの後、私の GeForce は省電力モードか、このようなモードになるようです。

4

1 に答える 1

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メモリが多いため)、ループを使用します。しかし、それらを少なくしてください。

于 2012-10-30T13:37:56.797 に答える