假设我们有:
执行这些添加的哪种访问模式会更快:
所有线程将 val t,1 添加到 dest 1 。
所有线程原子地将 val t,2 添加到 dest 2 。
等
每个具有索引t的线程将 val t,t 写入 dest t < / p>
每个具有索引t的线程将 val t,(t + 1)mod 32 写入 dest (t + 1)mod 32 子> 的
等
换句话说,当warp的所有线程在同一个循环中进行原子写入时,它会更快,还是没有原子写入重合的更好?我可以想到硬件可以更快地执行任一选项,我想知道实际实现了什么。
思想:
备注:
答案 0 :(得分:1)
这就是我理解你的问题的方法:
你有一个32x32的int矩阵:
Val0'0,Val1'0,...... Val31'0
Val1'0,Val1'1,...... Val31'1
。
。
Val31'0,Val31'1,...,Val31'31
你需要对每一行求和:
Val0'0 + Val1'0 + ... Val31'0 = dest0
Val0'1 + Val1'1 + ... Val31'1 = dest1等
问题是您的行值分布在不同的线程之间。 对于单个warp,最简单的方法是使用共享内存(在32x32共享内存数组中)为每个线程共享它的值。在线程同步之后,线程i对第i行求和,并将结果写入dest(i),它可以驻留在全局或共享内存中(取决于您的应用程序)。 这样,计算工作(31x31)的添加在warp中的线程之间平均分配,并且根本不需要原子操作(性能杀手)。 根据我的经验,原子操作通常可以而且应该通过线程之间不同的工作分配来避免。