【发布时间】:2015-01-18 07:07:33
【问题描述】:
在 CUDA 内核中,我需要找到一个映射到 threadIdx 的键。
映射可能如下所示:
key -> threadIdx
0 -> {0,1,2,3,4}
1 -> {5,6,7}
2 -> {8,9,10}
...
每个键 k_i 都映射到 n_i(可变的、任意的 n_i 和 n_i>0)线程。
该键将用于检索全局数组中的相应值。然后在这个内核的后续计算中使用这个值。
映射可以绘制为分段常数函数:
键的数量不限于 3 个(这只是一个示例!)并且仅在运行时知道,以及每个键的各自“宽度”。
如何有效地在CUDA内核中找出对应的key? 我想到了以下两种选择:
在内核中使用二分查找(内存高效)
-
预先计算每个 threadIDx 的映射,然后启动内核(运行时高效)
0 0 0 0 0 1 1 1 2 2 2 ...
有没有更好的方法来实现这一点?
【问题讨论】:
-
将每个元素读取一次(到共享内存中)可能更有效。虽然缓存会在重复访问相同地址时为您提供帮助,但共享内存对于大量读取可能会更好。如果每个键的值大致为偶数,那么最好让每个线程处理其键的所有值。
-
您的映射似乎只是
int key = ((int)threadIdx.x-2) / 3;,每个线程都可以轻松有效地计算它。如果除数是运行时变量而不是模板参数,这将需要一个完整的 32 位整数除法,但它仍然应该非常有效。你试过并计时了吗? -
@njuffa 正如我上面指出的:每个“宽度”都可以不同!
-
@m.s.我不清楚这到底是什么意思。我认为“宽度”是不同的,而是键数的线性函数,正如您的示例所建议的那样[具有恒定“斜率”的阶跃函数]。在这种情况下,应该使用基于整数除法的公式。您是说“宽度”是完全任意的,即它不能由每个线程可以在运行时评估的封闭式表达式来描述?
-
@njuffa 是的,“宽度”是任意的。