Parallel processing 以下两个循环可以并行吗?

Parallel processing 以下两个循环可以并行吗?,parallel-processing,Parallel Processing,嗨,我想知道这两个循环是否可以并行化?似乎y(i+1)部分使之不可能。因为它取决于尚未生成的值。如果y是一个数组(它看起来像一个函数,但随后将分配给一个函数调用),那么y(i+1)部分已经存在,尽管并行化仍然存在问题。当然可以 您只需要以这样一种方式编写它,即每个并行任务不会“踩”任何其他任务的内存 在第二种情况下,这将是一个棘手的问题,但我确信,经过足够的思考,这是可能的。在第一种情况下,只有当您有一个辅助存储区域时,并行化才是可能的。为了获得最大的并行性,您需要一个完全独立的阵列: do i

嗨,我想知道这两个循环是否可以并行化?似乎
y(i+1)
部分使之不可能。因为它取决于尚未生成的值。

如果y是一个数组(它看起来像一个函数,但随后将分配给一个函数调用),那么y(i+1)部分已经存在,尽管并行化仍然存在问题。

当然可以

您只需要以这样一种方式编写它,即每个并行任务不会“踩”任何其他任务的内存


在第二种情况下,这将是一个棘手的问题,但我确信,经过足够的思考,这是可能的。

在第一种情况下,只有当您有一个辅助存储区域时,并行化才是可能的。为了获得最大的并行性,您需要一个完全独立的阵列:

do i=2, n-1
   y(i) = y(i+1)
end do

do i=2, n-1
   y(i) = y(i+1) - y(i-1)
end do
如果只想使用两个并行执行单元,则需要存储阵列的一个元素:

for all i in [2, n-2] in parallel do
   y'(i) = y(i+1)
end do
您需要这样做来避免上半场最后一个元素和下半场第一个元素的竞争条件。事实上,所需的额外存储量与并行化代码的因素之间存在直接关系

第二个循环不能并行化,因为必须计算y(i-1)才能计算y(i)。不可能。对于第一个循环来说,这不是问题,因为在循环开始之前,所有最终读取的值都保证具有正确的值。第二次就不是这样了


值得一提的是,这些循环可以组合在一起,只要它们是按顺序执行的。这比将第一个并行化而将第二个单独处理要快。

在这两种情况下,您都有所谓的“循环携带依赖项”

y(i)的计算取决于y(i+/-1),因为在并行循环中,您无法保证执行i的顺序y(i+1)可能在计算y(i)之前已更新为其新值。更糟糕的是,y(i+1)可能正在一个线程上更新,而另一个线程试图读取可能已损坏的值(因为其数据仅在更新过程的一半。在这两种情况下,您都会得到错误的答案)

这里最好的解决方案是拥有一个只读和可写的数组

do i=2, n-1    
    y(i) = y(i+1) - y(i-1) 
end do

现在您的问题消失了,因为并行循环没有更新数组y。如果您的语言支持指针,您可以通过维护指向新/旧数组的指针并简单地交换指针来轻松地交换新/旧数组。唯一的额外开销是您需要保留一个额外的数据副本作为循环引用的只读副本to.

不是任何特定的语言,只是一般情况。如果你需要知道它是OpenMP,那么在OpenMP的情况下,我只会指定循环应该并行化。你的意思是我需要修改循环的内部结构吗?对不起,我不熟悉OpenMP。我所有的线程工作都是用libdispatch完成的。也许你会更清晰的例子,如果你真的展示了你要做的事情,而不是一个做作的例子。@AbhiBeckert你如何并行化第二个循环?在计算a(i)之前,你需要知道a(i-1)的最终计算值@Patrick87在我的脑海中,也许一个选项是让一个任务获取i+1,而第二个任务获取i-1,第三个线程进行实际计算,第四个线程写出结果。这是4个并行任务。在这种情况下,我不确定它是否会带来任何性能改进。显然,您需要一些代码来确保(i-1)直到另一个线程应用了新的值才被提取。对于第二个循环…可以只使用原始数组(oy)中的值来重述右侧以计算新数组(ny)。计算oy(3)-oy(1),然后可以计算新的ny(2)。计算oy(4)-oy(3)+oy(1),然后可以计算新的ny(3)。然后计算oy(5)-oy(4)加上我们计算得到的第一个值ny(4),oy(6)-oy(5)加上我们计算得到ny(5)的第二个值,依此类推。
do i=2, n-1    
    y(i) = y(i+1) - y(i-1) 
end do
do i=2, n-1    
    yNew(i) = yOld(i+1) - yOld(i-1) 
end do
swap(yOld, yNew)