`forall` 表达式:并行计算还是串行计算?

`forall` expression: parallel or serial calculation?

我对forall语句的理解是它们是并行执行的,而for语句是串行执行的。实际上,以下代码似乎证实了这种预期(即,由于线程化,随机序列仅用于 forall):

for i in 1..5 do writeln( i * 10 );
10
20
30
40
50

forall i in 1..5 do writeln( i * 10 );
10
50
20
30
40

另一方面,如果我在右侧使用forall(或)作为表达式

var A = ( forall i in 1..5 do i * 10 );
var B = [ i in 1..5 ] i * 10;

var X = ( forall a in A do a );
var Y = [ a in A ] a;

var P = ( for i in 1..5 do i * 10 );  // for comparison

writeln( "A = ", A );
writeln( "B = ", B );
writeln( "X = ", X );
writeln( "Y = ", Y );
writeln( "P = ", P );

所有结果都变得相同(即从 10 到 50 排序):

A = 10 20 30 40 50
B = 10 20 30 40 50
X = 10 20 30 40 50
Y = 10 20 30 40 50
P = 10 20 30 40 50

这是否意味着赋值右侧的forall表达式总是串行执行?如果是这样,相应的 [...] 是否也等同于 for 表达式?

好问题。您是正确的,以这种方式使用 forall 表达式(显式或 []-"bracketed" )会产生确定性结果,但是 forall 表达式 仍然导致并行执行。

像你这样的表达式有效地导致了压缩迭代,它被定义为使得相应的迭代将匹配。例如,在 中,看似 "whole-array" 的操作如下:

var A, B, C: [1..10] real;
A = B + C;

等同于(提升)执行压缩 forall 循环:

var A, B, C: [1..10] real;
forall (a, b, c) in zip(A, B, C) do
  a = b + c;

这两个表达式:
(a) specify parallel execution,
(b) ensure ABC 数组的相应元素在循环体的每个实例中使用(否则语言将不会很有用)。

以你的一个例子为例,

...B = [ i in 1..5 ] i * 10...

相当于:

forall (b, v) in zip(B, [i in 1..5] i * 10) do
  b = v;

或:

forall (b, i) in zip(B, 1..5) do
  b = i * 10;

对于您提供的其他变体也是如此。

这是在 Chapel 中通过使用称为 领导者-跟随者迭代器 的概念来实现的。这些最初是在 PGAS 2011 上发表的一篇名为 User-Defined Parallel Zippered Iterators in Chapel whose slides are here. They are also described in a Chapel primer on parallel iterators.

的论文中描述的