OpenCL和CUDA中的持久线程

时间:2013-02-11 21:18:39

标签: cuda opencl gpu gpgpu

我读过一些关于"持续线程"对于GPGPU,但我并不是真的理解它。任何人都可以给我一个例子,或者告诉我使用这种编程方式吗?

在阅读和谷歌搜索"持续线程"后,我一直记在脑海中:

  

Presistent Threads它不过是一个while循环,它可以保持线程运行并计算大量的工作。

这是对的吗?提前致谢

参考:http://www.idav.ucdavis.edu/publications/print_pub?pub_id=1089 http://developer.download.nvidia.com/GTC/PDF/GTC2012/PresentationPDF/S0157-GTC2012-Persistent-Threads-Computing.pdf

2 个答案:

答案 0 :(得分:8)

CUDA利用单指令多数据(SIMD)编程模型。计算线程以块的形式组织,并且线程块被分配给不同的流式多处理器(SM)。通过在32个线程的 warps 中排列线程来执行SM上线程块的执行:每个warp以锁定步骤操作并完全执行 对不同数据的相同指令。

通常,为了填充GPU,内核将启动更多可以实际托管在SM上的块。由于并非所有块都可以托管在SM上,因此工作调度程序在块完成计算时执行上下文切换。应该注意的是,调度器完全在硬件中管理块的切换,并且程序员无法影响如何在SM上调度块。这暴露了所有那些不完全适合SIMD编程模型并且存在工作不平衡的算法的限制。实际上,块A不会被同一SM上的另一个块B替换,直到块A的最后一个线程不会完成执行。

虽然CUDA不会将硬件调度程序暴露给程序员,但持久性线程样式依赖于工作队列来绕过硬件调度程序。当块完成时,它会检查队列是否有更多工作,并继续这样做,直到没有剩余工作,此时块退出。通过这种方式,内核的启动时块数与可用SM的数量一样多。

以下示例更好地说明了持久性线程技术,该示例取自演示文稿

“GPGPU” computing and the CUDA/OpenCL Programming Model

文章中提供了另一个更详细的例子

Understanding the efficiency of ray traversal on GPUs

// Persistent thread: Run until work is done, processing multiple work per thread
// rather than just one. Terminates when no more work is available

// count represents the number of data to be processed

__global__  void persistent(int* ahead, int* bhead, int count, float* a, float* b)
{
    int local_input_data_index, local_output_data_index;
while ((local_input_data_index = read_and_increment(ahead)) <   count)
{                                   
        load_locally(a[local_input_data_index]);

        do_work_with_locally_loaded_data();

        int out_index = read_and_increment(bhead);

        write_result(b[out_index]);
    }
}

// Launch exactly enough threads to fill up machine (to achieve sufficient parallelism 
// and latency hiding)
persistent<<numBlocks,blockSize>>(ahead_addr, bhead_addr, total_count, A, B);

答案 1 :(得分:3)

很容易理解。通常每个工作项处理少量工作。如果要保存保存工作组切换时间,可以让一个工作项使用循环处理大量工作。例如,你有一个图像,它是1920x1080,你有1920个工作项,每个工作项使用循环处理一列1080像素。