我想设计一个具有线程块的CUDA内核,warp读取它们自己的1-D数组。假设一个带有两个warp的线程块需要两个数组{1,2,3,4}和{2,4,6,8}。然后每个warp将通过读取自己的数组来执行一些计算。计算基于每个数组元素完成。这意味着线程块将具有阵列中元素2和4的冗余计算。 这是我的问题:如何避免这种冗余计算?
准确地说,一旦元素已被其他warp触摸,我想让warp跳过元素的计算,否则计算会正常进行,因为任何warp之前都没有触及过该元素。
可以考虑在专用于线程块的共享存储器上使用散列表。但是我担心每当数组的warp访问元素时哈希表访问导致性能下降。
有任何想法或意见吗?
答案 0 :(得分:1)
在多核协处理器上的并行计算中,希望对一组独立的数据执行算术运算,即消除对线程/ warp提供的向量集的任何依赖性。通过这种方式,计算可以并行运行。如果要跟踪先前计算过的元素(在这种情况下,两个输入数组中常见的2和4),则必须序列化并创建分支,这反过来会降低计算性能。
总之,您需要通过将输入向量减少到具有不同组件的向量来检查是否可以消除输入级别的冗余。如果不是,跳过重复组件的冗余计算可能不一定会提高性能,因为计算是批量执行的。
答案 1 :(得分:0)
让我们试着了解硬件级别会发生什么。
首先,CUDA中的计算是通过warp进行的。 warp是一组32个线程,它们彼此同步。在同一时刻对相应warp的所有线程执行指令。从技术上讲,它不是线程,而是最终在硬件上执行的warp。
现在,让我们假设您能够以某种方式跟踪哪些元素不需要计算,因此您可以在内核中添加条件,如
...
if(computationNeeded){
compute();
}
else{
...
}
...
现在让我们假设特定warp中有5个线程,其中"计算需要"是假的,不需要计算。但根据我们的定义,所有线程都执行相同的指令。因此,即使你设置了这些条件,所有线程都必须执行if和else块。
例外: 如果特定块的所有线程执行if或else条件,则会更快。但它几乎适用于所有现实世界的算法。
建议 在CPU或GPU上进行预处理步骤,从而消除输入数据中的冗余元素。另外,请检查此步骤是否值得。
准确地说,一旦元素已被其他warp触摸,我想让warp跳过元素的计算,否则计算会正常进行,因为任何warp之前都没有触及过该元素。
在专用于线程块的共享内存上使用哈希表 可以考虑
如果你想在网格的所有经线之间进行交互间通信,那么只能通过全局存储器而不是共享存储器。