首页 文章

cuda使用循环缓冲区实现核外实现

提问于
浏览
0

我试图在GPU内存和CPU内存之间进行核心操作 . 例如,我有1GB的数据块,我需要按顺序处理1000个这样的块,每个块都由内核启动完成 . 假设必须逐个进行处理,因为第n个内核启动需要使用第(n-1)个内核产生的结果,该结果存储在第(n-1)个块中,除了第一次内核启动 . 所以我想在GPU上使用循环缓冲区来存储最近的5个块,并使用事件在数据流和任务流之间进行同步 . 数据流准备数据,任务流启动内核 . 代码如下所示 .

const int N_CBUF = 5, N_TASK = 1000;

// Each pointer points to a data block of 1GB
float* d_cir_buf[N_CBUF];
float* h_data_blocks[N_TASK];

// The data stream for transfering data from host to device.
// The task stream for launching kernels to process the data.
cudaStream_t s_data, s_task;

// The data events for the completion of each data transfer.
// The task events for the completion of each kernel execution.
cudaEvent_t e_data[N_TASK], e_task[N_TASK];

// ... code for creating the streams and events.

for (int i = 0; i < N_TASK; i++) {
  // Data transfer should not overwritten the data needed by the kernels.
  if (i >= N_CBUF) {
    cudaStreamWaitEvent(s_data, e_task[i-N_CBUF+1]);
  }
  cudaMemcpyAsync(d_cir_buf[i % N_CBUF], h_data_blocks[i], ..., cudaMemcpyHostToDevice, s_data);
  cudaEventRecord(e_data[i], s_data);

  cudaStreamWaitEvent(s_task, e_data[i]);

  // Pass the current and the last data block to the kernel.
  my_kernel<<<..., s_task>>>(d_cir_buf[i % N_CBUF], 
    i == 0 ? 0 : d_cir_buf[(i+N_CBUF-1)%N_CBUF]);
  cudaEventRecord(e_task[i], s_task);
}

我想知道这是否是一个有效的想法,还是有什么完全错的?此外,CUDA编程指南提到如果从两个不同的主机内存地址到同一设备地址有memcpy,那么就没有并发执行,这在我的情况下是否重要?特别是,如果 d_cir_buf 的内存被分配为一个整体大块然后分成5块,那么它会算作"the same memory address in device",导致并发失败吗?此外,在我的情况下,(n 5)_394070数据传输,但是,在给定所需的同步的情况下,将不会同时执行两个这样的传输 . 这样可以吗?

1 回答

  • 2

    我觉得你的问题最适合双缓冲:

    • 两个流

    • 在stream1中上传data1

    • 在stream1中的data1上运行内核

    • 在stream2中上传data2

    • 在stream2中的data2上运行内核

    ... 等等

    stream2中的内核可以与strezm 1中的数据传输重叠,反之亦然

相关问题