使用块分发遇到未解决的访问错误

Bof*_*ofo 4 chapel

我在尝试使用 Block 分发版进行编译时遇到了错误。这是错误:

error: unresolved access of '[BlockDom(3,int(64),false,unmanaged DefaultDist)] real(64)' by '[int(64), int(64)]'
Run Code Online (Sandbox Code Playgroud)
use Random, BlockDist;

config const size = 10;
const Space = {1..size, 1..size};

const gridSpace: domain(2) dmapped Block(boundingBox=Space);
var grid: [gridSpace] real;
var grid2: [gridSpace] real;
var grid3: [gridSpace] real;

fillRandom(grid);
fillRandom(grid2);

forall i in gridSpace do {
    forall j in gridSpace do {
        forall k in gridSpace do {
            grid3[i,j] += grid[i,k] * grid2[k,j]; //error here
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ben*_*cht 5

当使用单个索引迭代 Chapel 中的多维域时,索引将具有域的索引类型。在上面的示例中,分布式域gridSpace是一个二维域,因此使用单个索引对其进行迭代将产生 2 个整数的元组。

例如,

var dom = {1..2, 1..2};
for idx in dom {
  writeln(idx); // index type is (int, int)
}
Run Code Online (Sandbox Code Playgroud)

将打印:

(1, 1)
(1, 2)
(2, 1)
(2, 2)
Run Code Online (Sandbox Code Playgroud)

使用 Chapel 1.19.0 编译您的示例时遇到的错误是:

error: unresolved access of '[BlockDom(2,int(64),false,unmanaged DefaultDist)] real(64)' by '[2*int(64), 2*int(64)]'
Run Code Online (Sandbox Code Playgroud)

这告诉我们,我们正试图用 2 个整数 ( ) 的2 个元组索引[BlockDom(2,int(64),false,unmanaged DefaultDist)]实数 ( real(64))的块分布二维数组( [2*int(64), 2*int(64)])。

您可以更正上述示例的一种方法是显式迭代每个维度:

forall i in gridSpace.dim(1) {
    forall j in gridSpace.dim(2) {
        forall k in gridSpace.dim(1) {
            grid3[i,j] += grid[i,k] * grid2[k,j];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,请注意,最内层循环将进行多次迭代,尝试grid3并行添加到相同的索引,从而造成数据竞争。

您可以通过使内循环串行来消除此数据竞争:

forall (i,j) in gridSpace {
  for k in gridSpace.dim(2) {
    grid3[i,j] += grid[i,k] * grid2[k,j];
  }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用+ 归约来处理内循环求和:

forall (i,j) in gridSpace {
  grid3[i,j] = + reduce (grid[i,..]*grid2[..,j]);
}
Run Code Online (Sandbox Code Playgroud)

我注意到上面的代码还有另外两个问题:

  1. gridSpace只与一个类型和没有价值定义的,所以它实际上是一个空的分布域。您可以通过使用以下值对其进行初始化来解决此问题Space
const gridSpace: domain(2) dmapped Block(boundingBox=Space) = Space;
Run Code Online (Sandbox Code Playgroud)

有关更多示例,请参阅发行版入门

  1. do不需要在forall上述循环。do仅在为循环体的单表达式省略花括号时才需要,例如
for i in dom do writeln(i);
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅for 循环指南