假设我们有2 ^ 10个CUDA核心和2 ^ 20个数据点。我想要一个处理这些点的内核,并为每个点提供true / false。所以我将有2 ^ 20位。例如:
bool f(x) { return x % 2? true : false; }
void kernel(int* input, byte* output)
{
tidx = thread.x ...
output[tidx] = f(input[tidx]);
...or...
sharedarr[tidx] = f(input[tidx]);
sync()
output[blockidx] = reduce(sharedarr);
...or...
atomic_result |= f(input[tidx]) << tidx;
sync(..)
output[blckidx] = atomic_result;
}
Thrust / CUDA有一些算法称为“分区”,“转换”,提供类似的替代方案。
我的问题是,当我使用提供相应bool结果的谓词编写相关的CUDA内核时,
我应该为每个结果使用一个字节并直接将结果存储在输出数组中吗?执行一步计算并稍后执行另一步减少/分区。
我应该压缩共享内存中的输出,使用8个线程的一个字节,然后将共享内存的结果写入输出数组?
我应该使用原子变量吗?
编写这样的内核和最合理的数据结构以保持结果的最佳方法是什么?是否更好地使用更多内存并简单地对主内存执行更多写操作,而不是在写回结果内存区之前尝试压缩结果?
答案 0 :(得分:4)
使用efficiently pack the results内在的__ballot()
扭曲投票时,速度和数据大小之间没有权衡。
假设您可以将output
重新定义为uint32_t类型,并且您的块大小是warp大小的倍数(32),您可以使用
output[tidx / warpSize] = __ballot(f(input[tidx]));
注意这会使warp的所有线程都尝试存储__ballot()
的结果。只有一个经线的线程会成功,但由于它们的结果都是相同的,所以哪一个都没关系。