与 CUDA 中的线程和块并行化

Posted

技术标签:

【中文标题】与 CUDA 中的线程和块并行化【英文标题】:Parallelizing with threads and blocks in CUDA 【发布时间】:2019-05-13 02:54:15 【问题描述】:

我有以下简单的嵌套 for 循环

float a[1024][1024], b[1024]

for(i=1; i < 1024; i++)
    for(j = 1; j < 1024 - i; j++)
        b[i + j] += a[i][j];    
    

我正在尝试了解如何使用 CUDA 线程和线程块来分区此问题以与 GPU 并行化。到目前为止,我相信我总共进行了 N = 522753 次计算。我不完全确定如何从这里开始:我知道每个块中的线程数应该是 32 的倍数。例如,如果每个块的线程数是 1024,那么我至少需要 511 个块,每个线程从 1 -> N 进行计算。有人可以解释如何选择每个块的最佳线程数,以及如何实际并行实现。

【问题讨论】:

@talonmies 它来自提供给我的一个示例 - 并不意味着实际执行。比任何东西都多的伪代码,但我仍然不明白如何将每个块划分为块和线程以并行化概念 这种情况下的问题是不同的 (i,j)-pairs 想要写入同一个位置。说(3,0)和(0,3)。您可以使用 atomic_add,但最好以某种方式进行分区,即使用更少的 atomic_add 并且每个线程有更多的工作。 【参考方案1】:

长评论:

编辑:c 矩阵应该是列主而不是行主,并且排序应该在列而不是行上,但为了便于阅读,我将其保留为行主。

您可以(一次)为每个工作项准备一个计数和引用矩阵,以便第一列是计数,其余是引用,最后一列是写入地址

c[0] = 1, &a[1][1],                   &b[2]; // b[2]
c[1] = 2, &a[1][2],&a[2][1],          &b[3]; // b[3]
c[2] = 3, &a[1][3],&a[2][2],&a[3][1], &b[4]; // b[4]
..

然后根据它们的索引数量/子数组大小对它们进行排序(一次),使它们成为

   c[0]    = 1, &a[1][1],         &b[2]    //  b[2]
   c[1]    = 1, &a[1022][1],      &b[1023] // b[1023]
   ..
   c[k]    = 5, x1,y1,z1,t1,w1,   &b[m] // b[m]
   c[k+1]  = 5, x2,y2,z2,t2,w2,   &b[n] // b[n]

在 warp/block 的 cuda 线程之间平衡工作量。

然后访问 c 矩阵(每行 1 个 cuda 线程)以了解在每个工作项的普通 for 循环中添加哪些元素。

   const int length = (int)c[workitemId][0];
   for(int i=1;i<length+1;i++)
      resultOfWorkitem += *(c[workitemId][i]);
   *(c[workitemId][length+1])=resultOfWorkitem;

由于所有排序的列表只会排序一次,如果您要经常进行计算部分,那么这个额外的引用部分可能比使用原子更快,并且可能会为 c 和数组的只读访问而缓存。

如果随机写入地址成为性能问题,您可以根据最后一项的地址(连续的 b 索引)对 c 数组进行排序,但这会降低相邻 cuda 线程之间的工作平衡。也许这更快,没有测试。也许对 c 的第二个索引值进行排序可以通过减少读取次数来加快速度,尤其是当您对它们之间的每一行元素进行排序时,它们会与相邻线程的读取连续,类似于第一部分

 c[0] = 1, &a[1][1] // address x    \
 c[1] = 2, &a[1][2] // address x+1   > less than L1 cache line size 128byte?
 c[2] = 3, &a[1][3] // address x+2  /

保持每个工作项的连续地址访问和平衡工作是不可能的。

【讨论】:

以上是关于与 CUDA 中的线程和块并行化的主要内容,如果未能解决你的问题,请参考以下文章

CUDA并行编程思维过程

CUDA_one

使用 CUDA 在 C 中并行化基数排序的问题

Python CUDA 并行化多个小矩阵的 SVD

CUDA中的线程和块结构以及如何分配具有不同结构的线程(c ++)

使用 CUDA 在 python 中展开一个可并行化的 for 循环