CUDA基于元素总和将数组划分为块的算法

时间:2014-06-12 14:53:27

标签: cuda

问题是:我有一个包含随机数的数组。我应该将它们分成块,这样在每个块中,所有元素的总和不大于给定的N.我以为我可以简单地用扫描解决这个问题,但是有一个令人讨厌的错误,我不知道如何有效解决

例如,我尝试如下:N=8,数组为:

{2, 3, 1, 4, 4, 1, 6}

执行包容性总和扫描:

{2, 5, 6, 10, 14, 15, 21}

然后按N=8进行简单的整数除法,得到以下分区:

{0, 0, 0, 1, 1, 1, 2}

然后我意识到存在一个错误,即第二个块中所有元素的总和是4+4+1=9而不是8,因为通过使用整数除法,我假设所有元素的总和在第一个街区必须是8.

正确的分区应该是:

{0, 0, 0, 1, 1, 2, 2}

我试图遍历列表并重新划分边界点,但我的并行实现比串行实现慢。你碰巧知道这个问题的有效并行算法吗?

1 个答案:

答案 0 :(得分:1)

不是从扫描开始,而是从并行计算每个节点n(i)开始,后续节点n(j)的索引是什么,它结束了从n(i)开始并且总和小于或者的子序列等于8.(步骤1)

这是一个由并行的每个线程操作的相当短的循环,它将为您提供一系列索引。

{2,3,1,4,4,1,6}

{2,3,3,4,5,6,6}(步骤1结束)

然后并行遍历从节点0开始的链表;考虑在步骤1中为0计算的索引之后的节点的后继0;基本上这是解决方案中的箱的起始点的链接列表。

[在log(n)步骤中并行计算并且n log(n)工作矩阵,其在位置(i,k)为节点i提供距节点i 2 ^ k跳的节点。

{0,1,2,3,4,5,6}

3,4,4,5,6, - , -

5,6,6, - , - , - , -

- , - , - , - , - , - , -

从节点0开始并行地计算每个节点的位置,并连续唤醒更多节点以用于log(n)整个并行步骤。

0, - , - , - 1, - 2, -

分散并获取起点列表](步骤2)

{0,3,5}

现在与此序列并行分散一个0和1的新序列,如下所示;从0开始(步骤3)

{0,0,0,1,0,1,0}

最后应用包容性扫描以获得结果。 (第4步)

在你的例子中:

{2,3,1,4,4,1,6}

{2,3,3,4,5,6,6}(步骤1)

{0,3,5}(第2步)

{0,0,0,1,0,1,0}(步骤3)

{0,0,0,1,1,2,2}(步骤4)

如果原始序列中没有0,则initail循环具有常量步和线性工作,因此您需要支付列表遍历,即log(n)步和扫描。如果你在原始序列中有零,但数字是随机选择的自然数,那么在受影响的SM上有很多长零序列创建坏的最坏情况的概率仍然相当低。只要自然数(随机选择)随机选择,大于8的常数就不会有太大差别;在实践中,出于类似的推理,也不应该成为输入的一部分。

如果您涉及负数,那么这个解决方案不可行,但可能是朝着改进的通用解决方案迈出的一步。

我可以看到有一个更简单的解决方案的空间,我已经把一些已知的构建块放在一起。据我所知,解决方案仍然是正确和切实可行的,使用已知的模式,我们至少知道有一个。