1

我想在 c# 中编写一个并行前缀总和。我使用了这个算法:

initial condition: list of n >= 1 elements stored in A[0...(n-1)]
final condition: each element A[i] contains A[0]+A[1]+...+A[i]
begin
  spawn (p1,p2,...,p(n-1))
  foe all pi where 1 <= i <= n-1 do
    for j←0 to ⌈logn⌉-1 do
      if i - 2^j >= 0 then
        A[i] ← A[i] + A[i - 2^j]
      end if
    end for
  end for
end

我在 c# 中的最终代码是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MPI;

namespace prefixsum3
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] A = new int[] { 4, 3, 8, 2, 9, 1, 3, 5, 6, 3 };
            using (new MPI.Environment(ref args))
            {
                Intracommunicator comm = Communicator.world;
                int size, rank, n, i;
                size = comm.Size;
                i = comm.Rank + 1;
                n = A.Length;
                int[] B = new int[10];
                for (int j = 0; j <= (Math.Ceiling(Math.Log(n))) - 1; j++)
                {
                    int t = Convert.ToInt32(Math.Pow(2, j));
                    if ( i - t >= 0)
                    {
                        B[i] = A[i] + A[i - t];
                    }
                    comm.Barrier();
                    A[i] = B[i];
                    comm.Barrier();
                }
                if (comm.Rank == 0)
                {
                    for (int z = 0; z < n; z++)
                    {
                        Console.Write(A[z].ToString() + ",");
                    }
                }
            }
        }
    }
}

赖特输出应该是:[4,7,15,17,26,27,30,35,41,44]
但我的输出代码是:[4,7,8,2,9,1,3,5, 6,3]
有人知道我的代码有什么问题吗?
编辑:
我发现每个处理器都在本地看到数组 A。现在的问题是如何在全局范围内定义数组 A 以使所有处理器都看到一个数组?

4

1 回答 1

0

至于正确性,原始算法中的对数以 2 为底,这是您的错误(或其中之一)。

关于效率,您没有正确理解双缓冲区算法:您应该在 B[i] 中写入,同步,然后在下一次迭代之前交换 A 和 B 数组。您不需要两个障碍或 A[i] = B[i]。但是,当 t 大于或等于 i 时,您必须执行 B[i] = A[i]。

最后 Math.Pow 效率低下,最好从 t = 1 开始,然后在每次迭代时将其乘以 2(t <<= 1)。无论如何,您应该简单地使用以下更快的循环并修复前面提到的错误(您不再需要日志):

for (int t = 1; t < n; t <<= 1)
于 2014-09-29T07:39:56.917 回答