并行前缀和-最快的实现 我想用C++实现并行前缀和算法。我的程序应该采用输入数组x[1…N],并且应该在数组y[N]中显示输出。(注意,N的最大值为1000。)

并行前缀和-最快的实现 我想用C++实现并行前缀和算法。我的程序应该采用输入数组x[1…N],并且应该在数组y[N]中显示输出。(注意,N的最大值为1000。),c++,algorithm,C++,Algorithm,到目前为止,我查阅了许多研究论文,甚至维基百科上的算法。 但我的程序也应该显示输出、步骤以及每个步骤的操作/指令 我想要最快的实现,就像我想要最小化操作数量和步骤一样 例如: x = {1, 2, 3, 4, 5, 6, 7, 8 } - Input y = ( 1, 3, 6, 10, 15, 21, 28, 36) - Output 但是除了显示y数组作为输出外,我的程序还应该显示每个步骤的操作。我也引用了这个线程,但是可以从中得到很多帮助。下面的代码将完成这项工作 voi

到目前为止,我查阅了许多研究论文,甚至维基百科上的算法。 但我的程序也应该显示输出、步骤以及每个步骤的操作/指令

我想要最快的实现,就像我想要最小化操作数量和步骤一样

例如:

x = {1, 2, 3,  4,   5,   6,   7,  8 } - Input
y = ( 1, 3, 6, 10, 15, 21, 28, 36) - Output

但是除了显示y数组作为输出外,我的程序还应该显示每个步骤的操作。我也引用了这个线程,但是可以从中得到很多帮助。

下面的代码将完成这项工作

void prfxSum()
{
    int *x=0;
    int *y=0;
    int sum=0;
    int num=0;
    int i=0;

    cout << "Enter the no. of elements in input array : ";
    cin >> num;

    x = new int[num];
    y = new int[num];

    while(i < num)
    {
        cout << "Enter element " << i+1 << " : ";
        cin >> x[i++];
    }

    cout << "Output array :- " << endl;
    i = 0;
    while(i < num)
    {
        sum += x[i];
        y[i] = sum;
        cout << y[i++] << ", ";
    }

    delete [] x;
    delete [] y;
}

您可以通过从文件中输入1000个数组x[]元素来避免用户输入它。

这个问题的答案是:这里:。英伟达文章提供了使用CUDA GPU的最佳可能实现,卡内基梅隆大学PDF文件解释了算法。我还使用MPI实现了一个O(n/p)前缀和,您可以在这里找到:

这是通用算法的伪代码(与平台无关):

例3。高效工作和扫描算法的上扫(减少)阶段(Blelloch 1990之后)

例4。高效工作并行和扫描算法的下扫阶段(Blelloch 1990之后)


其中,x是输入数据,n是输入的大小,d是并行度(CPU数量)。这是一个共享内存计算模型,如果它使用分布式内存您需要向该代码中添加通信步骤,就像我在提供的Github示例中所做的那样。

我只实现了数组中所有元素的和(Blelloch的上扫减少部分),而不是使用Aparapi()实现的完整前缀和在java/opencl中。它在上可用,并且是为一般块大小(代码中称为localBatchSize)而不是2编写的。我发现块大小为8最适合我的GPU


虽然实现是有效的(求和计算是正确的),但它的性能比顺序求和差得多。在我的core-i7(8核)CPU上,8388608(8MB)数字的顺序求和大约需要12毫秒,在GPU上并行执行(NVidia Quadro K2000M,384核)大约需要100毫秒。我甚至优化到只传输计算后的最终和,而不是整个数组。如果不进行此优化,则需要20毫秒以上的时间。实现似乎是根据@marcel valdez orozco回答中描述的算法进行的。

您的具体问题是什么?看起来一个非常简单的算法就足够了。@Niklas B::实际上我希望我的程序应该使用最小步长和最小运算。比如,如果N是1000,我的程序应该使用小于20的步长和小于2100的运算。试着自己写一个!只需在循环中对数字求和。@Niklas B:他想要“并行”前缀求和算法。你在维基百科关于并行前缀求和的文章中实现了该算法吗?如果是这样的话,那么将其发布在这里或ideone上,我们将帮助您“显示输出、步骤以及每个步骤的操作/说明”部分。这是如何并行的?这完全是循序渐进的。我不知道OP为什么接受这个答案。回答很好,但是
x[k+2^d+1-1]
应该是
x[k+2^(d+1)-1]
在这里和你链接到的CUDA文章中(我相信他们给出的代码图——我相信下标符号错误地丢失了)。你是正确的。我检查了Blelloch的文章,似乎NVIDIA文章是不正确的。在上述算法的向下扫描阶段,假设n=10,对于d=2,k=8,索引k+2 ^ -1>n。k+2^(d+1)–1>n也是如此。这将导致应用程序核心转储。我们应该如何处理n不是2的幂的情况?你需要用0来填充它,所以它是2的幂。我有点难以理解所有k=0到n–1乘2^(d+1)并行做什么。我得到了所有k=0到n-1部分的
,但是
与2^(d+1)
有什么关系呢?我知道
d
来自outher循环,所以我当然可以计算
2^(d+1)
,但是我应该怎么做,或者
所用的
关键字是什么意思?如果你能澄清这一点,那就太好了。谢谢我还实现了其他算法,比较了开放CL和线程与直接顺序执行,我发现Intel core i7 CPU已经做了一些重大改进。您还需要查看编译选项,如果您想要真正的顺序执行,请从编译中删除所有优化,即使这样,也很难打败顺序和,CPU在计算和方面非常高效,我不知道在运行时到底做了哪些优化,使其如此快速。
Enter the no. of elements in input array : 8
Enter element 1 : 1
Enter element 2 : 2
Enter element 3 : 3
Enter element 4 : 4
Enter element 5 : 5
Enter element 6 : 6
Enter element 7 : 7
Enter element 8 : 8
Output array :- 
1, 3, 6, 10, 15, 21, 28, 36
 for d = 0 to log2(n) – 1 do 
      for all k = 0 to n – 1 by 2^(d+1) in parallel do 
           x[k +  2^(d+1) – 1] = x[k +  2^d  – 1] + x[k +  2^(d+1) – 1]
 x[n – 1] = 0
 for d = log2(n) – 1 down to 0 do 
       for all k = 0 to n – 1 by 2^(d+1) in parallel do 
            t = x[k +  2^d  – 1]
            x[k +  2^d  – 1] = x[k +  2^(d+1) – 1]
            x[k +  2^(d+1) – 1] = t +  x[k +  2^(d+1) – 1]