嵌套缩减 - 在Chapel中最常用的写法是什么?

Nik*_*han 5 chapel

教堂减少目前忽略变量的初始值.这意味着这段代码

var x: int;
for i in 1..3 {
  forall j in 1..10 with (+ reduce x) {
    x += 1;
  }
}

writeln(x);
Run Code Online (Sandbox Code Playgroud)

返回10而不是30,正如这位用户天真地想到的那样.虽然这种行为很好(并且它在减少条款的注释中有记载 - 我只是没有想到它),但事实证明,如果我想得到30(通过在两个循环中累积),我需要实际上是手工完成.我认为它会非常优雅和对称的for循环也reduce有意图....即我想写

var x: int;
for i in 1..3 with (+ reduce x) {
  forall j in 1..10 with (+ reduce x) {
    x += 1;
  }
}

writeln(x);
Run Code Online (Sandbox Code Playgroud)

请注意,即使在求和数字的情况下,我也需要引入一个临时变量.对于最大/最小的操作,需要更加小心.

是否有理由不支持reducefor循环中的意图?或者,有没有更惯用(Chapel-rrific)的方式来做到这一点?

更新:我越是想到这一点,我提出的代码在外部for被a替换的情况下不起作用并不明显forall.我认为问题在于变量是任务本地的而不是迭代本地的,因此减少只会发生在任务上.因此,仍然需要一个单独的内部缩减步骤.这将删除的是需要一个临时变量.

我认为更为重要的问题是,进行这些嵌套缩减的正确方法是......

Bra*_*rad 5

在我看来,这是对Chapel减少意图设计的疏忽.具体来说,虽然我认为每个任务在将其缩减变量的个人副本初始化为身份时忽略原始变量的值是合适的(正如您当前所说),我相信任务的贡献应该合并回原来的并行循环结束时的变量值,而不是简单地覆盖原始值,因为它们相互组合.这将使您的原始尝试按预期工作,并且也将遵循OpenMP所做的操作,如下面的C示例所示,其结果为35:

#include <stdio.h>
#include <omp.h>

int main(int argc, char* argv[]) {
  int tot = 5;
  for (int i=0; i<3; i++) {
  #pragma omp parallel for reduction(+:tot)
    for (int j=0; j<10; j++) {
      tot += 1;
    }
  }
  printf("tot is: %d\n", tot);
}
Run Code Online (Sandbox Code Playgroud)

我建议在Chapel GitHub问题页面上提交一个提倡此行为的错误/功能请求.

从Chapel 1.15.0开始,解决此问题的一种方法是在串行循环中手动进行减少,如下所示:

config var tot: int = 5;

for i in 1..3 {
  var subtot: int;
  forall j in 1..10 with (+ reduce subtot) do
    subtot += 1;
  tot += subtot;
}

writeln("tot is: ", tot);
Run Code Online (Sandbox Code Playgroud)