OpenCL和CUDA中的持久线程

OpenCL和CUDA中的持久线程,cuda,opencl,gpu,gpgpu,Cuda,Opencl,Gpu,Gpgpu,我读过一些关于GPGPU的“持久线程”的文章,但我并不真正理解它。有谁能给我举个例子或者告诉我如何使用这种编程方式吗 在阅读和谷歌搜索“持续线程”后,我在脑海中想的是: 存在的线程只不过是一个while循环,它保持线程运行并计算大量的工作 这是正确的吗?提前谢谢 参考: 很容易理解。通常每个工作项处理少量的工作。如果要节省工作组切换时间,可以使用循环让一个工作项处理大量工作。例如,您有一个图像,它是1920x1080,您有1920个工作项,每个工作项使用循环处理一列1080像素 CUDA利用单指

我读过一些关于GPGPU的“持久线程”的文章,但我并不真正理解它。有谁能给我举个例子或者告诉我如何使用这种编程方式吗

在阅读和谷歌搜索“持续线程”后,我在脑海中想的是:

存在的线程只不过是一个while循环,它保持线程运行并计算大量的工作

这是正确的吗?提前谢谢

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

CUDA利用单指令多数据(SIMD)编程模型。计算线程按块组织,线程块分配给不同的流式多处理器(SM)。SM上的线程块的执行是通过将线程排列成
32
线程的扭曲来执行的:每个扭曲在锁定步骤中操作,并精确执行 不同数据上的相同指令

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

尽管CUDA不向程序员公开硬件调度器,但持久线程样式通过依赖工作队列绕过硬件调度器。当一个块完成时,它会检查队列中是否有更多的工作,并继续这样做,直到没有剩余工作为止,此时块将退出。通过这种方式,内核启动时的块数与可用SMs的数量相同

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

本文还提供了另一个更详细的例子

//持久线程:运行直到工作完成,每个线程处理多个工作
//而不仅仅是一个。当没有更多工作可用时终止
//count表示要处理的数据数
__全局无效持久(整数*前移,整数*前移,整数计数,浮点*a,浮点*b)
{
int本地输入数据索引,本地输出数据索引;
而((本地输入数据索引=读取和增量(前进))
也许你应该包括一些关于“持久线程”的论文的具体参考资料。完成:针对GPGPU工作负载的持久线程风格GPU编程的研究如果你愿意,你可能会得到一些其他有用的见解。我对它的理解是,它或多或少和你描述的一样,意味着一个内核不会退出,并且不断地从全局内存中的队列轮询工作。投票赞成强调一点,即启动足够多的线程以使硬件饱和
// 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);