`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
表达式 仍然导致并行执行。
像你这样的表达式有效地导致了压缩迭代,它被定义为使得相应的迭代将匹配。例如,在 chapel 中,看似 "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 A
、B
和 C
数组的相应元素在循环体的每个实例中使用(否则语言将不会很有用)。
以你的一个例子为例,
...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.
的论文中描述的
我对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
表达式 仍然导致并行执行。
像你这样的表达式有效地导致了压缩迭代,它被定义为使得相应的迭代将匹配。例如,在 chapel 中,看似 "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 A
、B
和 C
数组的相应元素在循环体的每个实例中使用(否则语言将不会很有用)。
以你的一个例子为例,
...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.
的论文中描述的