【问题标题】:How to store bool result of a CUDA kernel function如何存储 CUDA 核函数的布尔结果
【发布时间】:2017-05-09 15:58:50
【问题描述】:

假设我们有 2^10 个 CUDA 核心和 2^20 个数据点。我想要一个可以处理这些点并为每个点提供真/假的内核。所以我将有 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 个线程使用一个字节,然后最后将结果从共享内存写入输出数组?

  • 我应该使用原子变量吗?

编写这样的内核和最符合逻辑的数据结构来保存结果的最佳方法是什么?使用更多内存并简单地对主内存进行更多写入而不是在写回结果内存区域之前尝试压缩结果会更好吗?

【问题讨论】:

  • 如果您对性能感兴趣,通常情况下(例如使用 Thrust),通过最大限度地减少到全局内存的数据流量,您可以最大限度地提高性能。如果您的其他数据用例在一个字节中的布尔结果与打包到一个字节中的布尔结果同样适用,那么这意味着全局流量的 8:1 减少可能是一个重要的性能因素。我认为在没有真正的测试用例的情况下,这样的性能问题真的很难判断。我不确定概括是否比自己测试和性能基准测试更好。

标签: c++ cuda predicate partition


【解决方案1】:

使用efficiently pack the results 固有的__ballot() warp-voting 时,速度和数据大小之间没有权衡。

假设您可以将 output 重新定义为 uint32_t 类型,并且您的块大小是 warp 大小 (32) 的倍数,您可以使用简单地存储打包输出

output[tidx / warpSize] = __ballot(f(input[tidx]));

请注意,这会使 warp 的所有线程尝试存储 __ballot() 的结果。经线只有一根线会成功,但由于它们的结果都是相同的,所以不管哪根线都会成功。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多