我正在尝试在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块,那么它会被计为“设备中的相同内存地址”,导致并发失败吗?此外,在我的情况下,第(n + 5)次数据传输将转到与第n次数据传输相同的地址,但是,如果需要同步,则不会有两个这样的传输同时执行。这样可以吗?
答案 0 :(得分:2)
我觉得你的问题最适合双重缓冲:
......等等
stream2中的内核可以与strezm 1中的数据传输重叠,反之亦然