运行 使用块分布进入未解决的访问错误

Running into a unresolved access error using Block distribution

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

error: unresolved access of '[BlockDom(3,int(64),false,unmanaged DefaultDist)] real(64)' by '[int(64), int(64)]'
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
        }
    }
}

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

例如,

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

将打印:

(1, 1)
(1, 2)
(2, 1)
(2, 2)

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

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

这告诉我们,我们正试图索引到一个块分布的二维数组 ([BlockDom(2,int(64),false,unmanaged DefaultDist)]) 的实数 (real(64)) 与 2 元组的 2 个整数 ([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];
        }
    }
}

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

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

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

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

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

我注意到上面的代码还有 2 个其他问题:

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

有关更多示例,请参阅 Distributions primer

  1. 上面的forall循环中不需要dodo 仅在省略单个表达式 for 循环体的花括号时才需要,例如
for i in dom do writeln(i);

有关详细信息,请参阅 for-loops guide