在 CUDA 中高效地解码 RLE

Decoding RLE in CUDA efficiently

我需要在 CUDA 中解码 RLE,并且我一直在尝试思考将 RLE 扩展到包含我的所有值的列表中的最有效方法。假设我的值为 2、3、4,我的 运行 为 3、3、1 我想将其扩展为 2、2、2、3、3、3、4。

起初我以为我可以使用 cudaMemset 但我现在很确定它会启动一个内核并且我有 CUDA Compute Capability 3.0 所以即使为每个值启动一个新内核可能效率不高/ 运行 对 我没有可用于执行此操作的动态并行性。

所以我想知道这个解决方案是否合理,然后再实施它,因为如果您不聪明的话,有很多事情最终无法在 CUDA 上正常运行。制作一个将调用 cudaMalloc 然后 cudaMemCpy 到目的地的内核是否合理?我可以很容易地计算出前缀总和,以了解将内存复制到哪里和从哪里复制,并至少使我所有的阅读合并。我担心的是多次调用 cudaMalloccudaMemCpy

另一个可能的选择是将这些值写入共享内存,然后将它们复制到全局内存。我想知道我的第一个解决方案是否应该有效且高效,或者我是否必须执行后者。

您不想考虑为每个 value/run 对执行单独的操作(例如 cudaMalloccudaMemset)。

在运行序列上计算前缀和后,前缀和中的最后一个值将是总分配大小。将其用于整个最终扩展序列的单个 cudaMalloc 操作。

一旦分配了必要的 space,并计算了前缀和,实际的扩展就非常简单了。

thrust can make this pretty easy if you want a fast prototype. There is an example code 给它。

@RobertCrovella 当然是正确的,但如果您有余地稍微调整压缩方案,您可以在效率方面走得更远。

抱歉 self-plugging,但您可能对 Run-Length 编码变体的 my own implementation 感兴趣,它添加了将输出位置锚定到输入中(例如。 "in which offset in which run do we have the 2048th element?");这允许将工作更公平地分配给线程块,并避免需要 full-blown 前缀总和。它仍然是 work-in-progress,所以我在撰写本文时在 336 GB/sec 内存带宽卡(Titan X)上只得到 ~34 GB/sec,但它非常有用。