你能在 O(n/p) 时间内进行并行计数排序吗?

Can you do a parallel counting sort in O(n/p) time?

是否可以并行进行计数排序并实现 O(n/p) 运行时间?

举个例子,我们有一个数组,其中包含数百万个元素,范围从 1 到 10。合并排序将 运行 在不超过 O(nlogn) 的时间内完成。应用于此问题的计数排序将在 O(n) 时间内 运行。并行化计数排序可能很有趣。如果我们为每个处理器分配一个包含 n/p 个元素的子数组,并且每个处理器都有自己的大小为 9 的计数数组,则累积元素计数的初始步骤应该花费 O(n/p) 时间。将所有计数数组合并为一个数组应该花费 O(p) 时间,因为您只迭代 p 个计数数组,每个数组的大小都是恒定的。

我还没有完全想清楚计数排序中元素按顺序放置的最后一步。如果计数数组的元素是原子的,您可以将原始数组的 n/p 部分分配给各个处理器并实现一些并行化,但是计数数组的各个元素会发生争用,可能会大大减少并行化。如果输入数组全为 10,则所有处理器都会在计数数组的第 9 个元素上进行序列化,从而将算法效率降低到 O(n)。

您可以将计数数组的子数组分配给 p 个处理器中的每一个,并且您回到了 O(n/p) 运行时间,但前提是元素分布相当均匀。而且,在我们的示例中,您将被限制为 10 个处理器。如果元素分布不均匀,则一个或多个处理器可能会执行更大比例的工作。例如,如果输入数组中一半的元素是 10,则一个处理器将不得不遍历一半的数组。最坏的情况是,数组全是 10,单个处理器将不得不遍历整个数组,将 运行 时间减少到 O(n)。

也许您可以在多个处理器之间划分计数数组的各个元素。例如,如果输入数组中有 50 个 10,则计数数组的元素 9 将反映这一点。您可以让 5 个处理器分别将 10 个 10 写入输出数组中的适当位置。如果count数组的每个索引位置的元素少于p个,这又是O(n)运行时间,但它避免了元素值分布不均匀的问题。

是否可以在O(n/p)时间内进行计数排序?

是的,这是可能的。将数组分成 p 个等长的部分。然后为每个进程创建一个计数数组'c'。让每个进程统计元素个数,存入c中。这将需要 O(n/p)。现在将所有计数数组 c 加在一起,并使数组共享给所有进程。这将采用 O(p*b),其中 b 是可能值的数量。到目前为止,这正是您的方法。现在您可以在 p 个进程中重新创建数组,因为您可以从 c 计算值的第一个和最后一个索引。对于每个值 i,其第一个索引是 c 中所有先前值的总和。它的最后一个索引是它的第一个索引加上 c[i]。此计算可以在 O(i) 中完成,其中 i 小于 b,因此小于 O(b)。每个进程现在都可以重新填充自己的部分。这又需要 O(n/p)。总而言之,您有 n/p + p*b + b + n/p。如果 p*b << n 它将导致 O(2*n/p)。 (因为 2/p 是一个常数因子,你仍然有 class O(n)。但是并行化会显着加快你的算法。)