问题描述
这是我目前拥有的算法,它在 O(1) 时间内运行,但使用了 n^2 个内核:
for i = 0 to n-1 do in parallel
for j = 0 to n-1 do in parallel
if (A[i]>A[j]) or (A[i]=A[j] and i>j) then
wins[i] = 1;
else
wins[i] = 0;
for i = 0 to n-1 do in parallel
A[wins[i]] = A[i];
for i = 0 to n-1 do in parallel
if win[i] == win[i - 1] or win[i] == win[i + 1]
return true
return false
解决方法
在 CRCW 机器上,您可以很好地执行所有比较并写出是否为真。
result= false;
for i = 0 to n-1 do in parallel
for j = 0 to n-1 do in parallel
if A[i] == A[j] then
result= true;
使用较少的处理器似乎很困难,因为除非您使用传递性来推断新的关系,否则特定比较的结果几乎不会为您提供其他比较的信息。可以通过形成两倍大小的“链”来利用传递性,但我不知道如何在恒定时间内完成。
如果存储的值是限制在 [1,n]
范围内的整数,您可以使用直方图:
result= false;
for i = 0 to n-1 do in parallel
H[i]= 0;
for i = 0 to n-1 do in parallel
H[A[i]]++;
for i = 0 to n-1 do in parallel
if H[i] > 1
result= true;
这假设并发 ++ 可用。如果没有,您可以改用辅助数组,将 i
存储在 A[i]
的位置,假设并发写入导致写入其中一个值。然后在第二遍中,您检查是否还有另一个 A[i]
。
result= false;
for i = 0 to n-1 do in parallel
B[i]= 0;
for i = 0 to n-1 do in parallel
B[A[i]]= i;
for i = 0 to n-1 do in parallel
if B[A[i]] > 0 and B[A[i]] != i
result= true;
,
这个想法是利用所有值都在 1
和 n
之间的事实。
假设一个 PRAM 以及并发写入和并发读取。
dup = false
for i = 1 to n do in parallel
if (A[abs(A[i])]) < 0 : dup = true; stop;
A[abs(A[i])] = - A[abs(A[i])]
return dup
这种虚构的内存处理并发写入的方式尚不清楚。
我假设内存会通过序列化写入来处理它。
这是一个新的解决方案,更准确地考虑了它。
dup = false
for i = 1 to n do in parallel
k = A[i]
A[k] = - A[k]
If (A[k]) > 0 : dup = true; stop;
return dup
这是另一个版本,以防内存工作方式仍然不确定:
for i = 1 to n do in parallel
k = A[i]
A[k] = 0
dup = false
for i = 1 to n do in parallel
If (A[k]) != 0 : dup = true;
return dup
注意:在所有提案中,我假设所有读取 k = A[i]
在所有写入之前执行。