我有一个长度为N的整数数组,包含值0、1、2、... (N-1),表示整数索引的排列。
如果给定了O(N)的并行计算,确定排列的奇偶性,最有效的方法是什么?
例如,您可以使用并行计算在log(N)时间内对N个数字进行求和。我期望以log(N)的时间找到排列的奇偶性,但似乎找不到一种算法。我也不知道如何称呼这种"具有并行计算复杂度顺序"的方法。
我有一个长度为N的整数数组,包含值0、1、2、... (N-1),表示整数索引的排列。
如果给定了O(N)的并行计算,确定排列的奇偶性,最有效的方法是什么?
例如,您可以使用并行计算在log(N)时间内对N个数字进行求和。我期望以log(N)的时间找到排列的奇偶性,但似乎找不到一种算法。我也不知道如何称呼这种"具有并行计算复杂度顺序"的方法。
Repeat ceil(log_2(N)) times:
foreach i in [0,N), in parallel:
if S[i] < S[A[i]] then:
S[A[i]] = S[i]
A[i] = A[A[i]]
S[i]
将包含包含i的循环中最小的索引。内层循环的第一次通过通过跟随A[i]
中的链接将最小的S[i]
传播到循环中的下一个槽位。然后将每个链接扩展两倍长,因此下一次传播它会传播到2个新的槽位,以此类推。最多需要ceil(log_2(N))
次传播来在整个循环中传播最小的S[i]
。foreach i in [0,N), in parallel:
if (S[i] == i) then:
S[i] = 1 //leader
else
S[i] = 0 //not leader
S
的元素相加,就可以得到排列中循环的数量,从而轻松计算其奇偶性。Coin[i] ← true with probability 1/2, false with probability 1/2
(barrier synchronization required in asynchronous models)
if Coin[i]
j ← Perm[i]
if not Coin[j]
Perm[i] ← Perm[j]
Perm[j] ← j
swaps ← swaps + 1
end if
end if
(barrier synchronization required in asynchronous models)
接下来,我们将交换的本地值相加并对2取模。
每次传递期望减少i数量,使得Perm[i] ≠ i,当前总数的1/4。由于期望的线性性,预期总数最多为n(3/4)r,因此经过r = 2log4/3n = O(log n)次传递后,预期总数最多为1/n,这反过来又限制了算法未收敛到标识排列所需的概率。失败时,我们可以切换到O(n)-span串行算法,而不会使期望跨度增加,或者重试。