我正在研究作为图像立方体的大数据集(450x450x1500)。我有一个适用于单个数据元素的内核。每个数据元素产生6个中间结果(浮点数)。我的块由1024个线程组成。每个线程(6个浮点数组)将6个中间结果存储在共享存储器中。但是,现在我需要添加每个中间结果以产生一个总和(6个和值)。我没有足够的全局内存来保存这6个浮点数组到全局内存,然后从主机代码中的推力或任何其他库中减少。
是否有可以从共享内存中的数组内核函数内部调用的减少例程?
解决此问题的最佳方法是什么?我是CUDA编程的新手,欢迎任何建议。
答案 0 :(得分:2)
这似乎不太可能:
我没有足够的全局内存来将这6个浮点数组保存到全局内存中,然后从主机代码中的推力或任何其他库中减少。
我无法想象你有足够的空间将数据存储在共享内存中,但不能存储在全局内存中。
无论如何,CUB提供了可以在线程块内调用的减少例程,它可以对存储在共享内存中的数据进行操作。
或者您可以编写自己的减少代码。这并不是非常难以做到,关于它的问题有很多问题,例如this one。
或者您可以调整cuda sample code。
答案 1 :(得分:1)
在看到所有评论之后,我了解到,除了进行1次或几次缩减之外,您需要进行450x450x6次的缩减。
在这种情况下,有更简单的解决方案。
您不需要为每个1500-D向量实现相对复杂的并行缩减。由于您已经有450x450x6向量减少,您可以使用传统的串行缩减方法并行减少所有这些向量。
您可以使用具有16x16线程的块来处理图像的特定区域,使用具有29x29块的网格来覆盖整个450x450图像。
在每个线程中,您可以迭代1500帧。在每次尝试中,您首先计算6个中间结果,然后将它们添加到总和中。当你完成所有迭代时,你可以将6个和写入全局内存。
完成内核设计。并且不需要共享内存。
你会发现表现非常好。由于它是一个内存绑定操作,因此它不会比简单地访问所有图像立方体数据一次长。
如果整个多维数据集没有足够的全局内存,可以将其拆分为[1500] [225] [225]的4个子多维数据集,并在每个子多维数据集上调用内核例程。您需要更改的唯一内容是网格大小。
答案 2 :(得分:0)
查看this,彻底解释CUDA中的并行减少。
答案 3 :(得分:0)
如果我理解正确,每个线程应该总结“仅”6
浮点数。
我不确定通过平行减少是否值得这样做,因为你将体验到性能提升。
如果您的目标是Kepler,则可以尝试使用 shuffle 操作,如果您正确设置了块大小,以便中间结果以某种方式适合Streaming Multiprocessor的寄存器。
正如Robert Crovella所指出的那样,关于存储中间结果的可能性的陈述似乎很奇怪,因为全局内存的数量肯定大于共享内存的数量。