当存在无限CPU时比较两个数组的最佳方法是什么?

时间:2015-10-04 09:10:38

标签: arrays algorithm parallel-processing

这是我在面试时遇到的问题。有两个排序的数组A和B.检查数组A中的每个元素是否出现在数组B中。假设有无限的CPU核心。采访者建议算法应该在O(1)中运行。我只想出了一个O(log(n))解决方案。有什么想法吗?

P.S。我的O(log(n))解决方案是将A中的一个元素分配给一个CPU核心,每个CPU使用二进制搜索来检查该元素是否存在于数组B中。我记得访谈者可能已经建议二进制搜索可以是给定无限CPU优化到O(1)。但我不确定。以防万一。

4 个答案:

答案 0 :(得分:2)

以下是公共CRCW模型中的O(1)PRAM algorithm,即只有在写入相同值时才能进行并发写入。假设原始数组A有n个元素,B的大小为m。

found = new bool[n]
parallel for i in 0..n-1:
  found[i] = false
  parallel for j in 0..m-1: 
    if A[i] == B[j]:
      found[i] = true

result = true
parallel for i in 0..n-1:
  if !found[i]:
    result = false

print result ? "Yes": "No"

当然,我并不完全确定这是一个多么实用的模型。实际上,您可能没有并发写入。在具有独占写入的CREW模型中,您可以在O(log log n)时间内计算AND和OR聚合,并且我认为也存在相应的下限。

向面试官询问他感兴趣的并行模型的具体情况可能是个好主意。

答案 1 :(得分:2)

让每个核心从A中获取一个元素,从B中获取一对相邻元素。为每个可能的组合使用不同的核心。核心将各自比较他们的三个元素。如果A中的元素介于两者之间(并且不等于任何一个),则A中的元素不会出现在B中。

这缺少一些明显的优化。例如,a1000不需要与b1& b2,但有无限的机器,谁在乎。

答案 2 :(得分:1)

设A总计 a 元素,B总计 b 元素(我假设元素可能重复)。

我们需要((a * b)+ 1)核心:我们想检查B中A的每个元素。所以我们需要总 b 处理A的每个元素,因此 a * b 。最后 +1 用于运行主程序的主处理器。

每个处理器将简单地比较两个元素是否相等。如果是,则会返回true,否则为false。以A [0]为例。我们只是比较B的任何元素是否等于A [0]。因此我们将A [0]和B [0]传递给第一个处理器,A [0]和B [1]传递给第二个处理器,依此类推,并对结果进行OR运算。相应地,将在每个核心上运行的test()方法的代码为:

public static bool test (int aElement, int bElement)
{
    return aElement == bElement;
}

接下来我们对A [1]进行相同的处理,然后A [2]直到A [a-1]并行。

我们对此结果进行AND,例如:

(test(A[0], B[0]) || test(A[0], B[1])...) && (test(A[1], B[0]) || test(A[1], B[1])... )

因此,Main()将如下所示:

public void Main (string[] args)
{
    //Read A and B arrays and create the next line dynamically
    var allPresent = (test(A[0], B[0]) || test(A[0], B[1]) ||... test(A[0], B[b-1]))
                  && (test(A[1], B[0]) || test(A[1], B[1]) ||... test(A[1], B[b-1]))
                  .
                  .
                  .
                  && (test(A[a-1], B[0]) || test(A[a-1], B[1]) ||... test(A[a-1], B[b-1]))
    Console.WriteLine("All Elements {0}", (allPresent ? "Found" : "Not Found"));
}

我们并行生成所有test(A[k], B[l]),结果为O(1)时间。

答案 3 :(得分:0)

为了补充Niklas B.的非常好的答案,我补充说,对于O(1)解决方案,我怀疑在最坏的情况下,即使使用有序数组,也可以使用低于Ω(MN)的内核。< / p>

如果所有元素在两个数组中都出现一次(并且隐式地M = N),则可以在“面对”元素之间并行执行N次比较,即使用Θ(N)核。

但是当允许重复时,相等的元素可以出现移位,移位可以增大到Ω(M + N)并且事先不知道。要尝试所有元素的所有可能移位,请执行Ω(MN)比较。