为什么两个CUDA流中的操作不重叠?

时间:2019-01-15 14:47:21

标签: cuda nvprof cuda-streams nvvp

我的程序是一个管道,其中包含多个内核和memcpys。每个任务将通过相同的管道使用不同的输入数据。主机代码在处理任务时将首先选择一个Channel,一个便笺本存储器和CUDA对象的封装。在最后一个阶段之后,我将记录一个事件,然后将处理下一个任务。
主要的管道逻辑如下。 问题是,不同流中的操作没有重叠。我附上了处理10个任务的时间表。您可以看到流中没有任何操作重叠。对于每个内核,一个块中有256个线程,而网格中有5个块。 用于memcpy的所有缓冲区都是固定的,我确信我已经满足了requirements的要求,以实现重叠的内核执行和数据传输。有人可以帮我找出原因吗?谢谢。

环境信息
GPU:Tesla K40m(GK110)
最大翘曲度/ SM:64
最大线程块/ SM:16
最大线程数/ SM:2048
CUDA版本:8.0

    void execute_task_pipeline(int stage, MyTask *task, Channel *channel) {
    assert(channel->taken);
    assert(!task->finish());

    GPUParam *para = &channel->para;

    assert(para->col_num > 0);
    assert(para->row_num > 0);

    // copy vid_list to device
    CUDA_ASSERT( cudaMemcpyAsync(para->vid_list_d, task->vid_list.data(),
                sizeof(uint) * para->row_num, cudaMemcpyHostToDevice, channel->stream) );

    k_get_slot_id_list<<<WK_GET_BLOCKS(para->row_num),
        WK_CUDA_NUM_THREADS, 0, channel->stream>>>(
                vertices_d,
                para->vid_list_d,
                para->slot_id_list_d,
                config.num_buckets,
                para->row_num);

    k_get_edge_list<<<WK_GET_BLOCKS(para->row_num),
        WK_CUDA_NUM_THREADS, 0, channel->stream>>>(
                vertices_d,
                para->slot_id_list_d,
                para->edge_size_list_d,
                para->offset_list_d,
                para->row_num);

    k_calc_prefix_sum(para, channel->stream);

    k_update_result_table_k2u<<<WK_GET_BLOCKS(para->row_num),
        WK_CUDA_NUM_THREADS, 0, channel->stream>>>(
            edges_d,
            para->vid_list_d,
            para->updated_result_table_d,
            para->prefix_sum_list_d,
            para->offset_list_d,
            para->col_num,
            para->row_num);

    para->col_num += 1;
    // copy result back to host
    CUDA_ASSERT( cudaMemcpyAsync(&(channel->num_new_rows), para->prefix_sum_list_d + para->row_num - 1,
            sizeof(uint), cudaMemcpyDeviceToHost, channel->stream) );
    // copy result to host memory
    CUDA_ASSERT( cudaMemcpyAsync(channel->h_buf, para->updated_result_table_d,
                channel->num_new_rows * (para->col_num + 1), cudaMemcpyDeviceToHost, channel->stream) );

    // insert a finish event in the end of pipeline
    CUDA_ASSERT( cudaEventRecord(channel->fin_event, channel->stream) );
}

Timeline in visual profiler

1 个答案:

答案 0 :(得分:1)

您是否要重叠82微秒内的处理?

由于已经对应用程序进行了概要分析,因此线索可能位于两个内核执行之间的橙色大框内(在图像中看不到这样的地方)。

如果这是同步,请将其删除。

如果这是像cudaLaunch_KernelName这样的跟踪,请尝试使处理更大(更多数据或更多计算),因为向GPU发送指令所花的时间比执行它要花费的时间多,因此您无法进行并行计算进入这些不同的流。