从正在运行的CUDA模拟中获取值的最佳方法是什么?

时间:2013-06-06 15:31:25

标签: cuda

我正在运行一个大型数值模拟,我设计使用CUDA在GPU设备上运行。我不想在每个时间步将整个数据传输到CPU,我只是希望它在前一个步骤完成后立即计算每个新的时间步长。此外,有两种更新方法需要串联实现,我发现最好以异步方式实现。

示意图,它看起来像这样:

#define NSTREAMS 7
#define ITEMS 1000000     // ITEMS is of the order 10^5 -- 10^7

__global__ void updateDomain1(float* domain, float* start, unsigned int nItems);
__global__ void updateDomain2(float* domain, float* start, unsigned int nItems);

main(int argc, char* argv []) 
{
    cudaStream_t streams [NSTREAMS];
    float* domain_cpu  = new float [ITEMS];              
    float* domain_gpu;

     /* ... Set up everything here... */

    // Run the whole simulation:
    while (continueRunning) 
    {    
         for(int ii = 0; ii < NSTREAMS; ++ii)
         {
             updateDomain1<<<threads, blocks, 0, streams[ii]>>>(domain_gpu, domain_gpu + ITEMS / NSTREAMS * ii, ITEMS / NSTREAMS);
             updateDomain2<<<threads, blocks, 0, streams[ii]>>>(domain_gpu, domain_gpu + ITEMS / NSTREAMS * ii, ITEMS / NSTREAMS);
         }
    }

    // In the end, transfer everything back to the CPU
    cudaMemcpy(domain_cpu, domain_gpu, sizeof(float) * ITEMS, cudaMemcpyDeviceToHost)
}

这很有效。但是,现在我想在每个时间步记录域中一个点的单个值。我真的只对一个值感兴趣,所以我写了以下内容并在for - 循环后插入:

float getValueAtIndex(const float* const domain_gpu, const unsigned int index)  {
    float temp;
    cudaMemcpy(&temp, domain_gpu + index, sizeof(float), cudaMemcpyDeviceToHost) );
    return temp;
}

并将每个值存储在一个数组中。但是,这会使模拟速度变慢。特别是对于相对较小的ITEMS值,它可以减慢2倍。原因似乎是所有异步更新方法需要在内存传输发生之前完成,然后必须等待这也完成了。但是,我不能将内存传输放在异步内存传输中,因为它可能会记录一个尚未更新的值。

有没有更好的方法来记录这个值而不会减慢整个过程?

0 个答案:

没有答案