运行 使用块分布进入未解决的访问错误
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 个其他问题:
gridSpace
只定义了类型,没有值,实际上是一个空的分布式域。您可以通过使用 Space
: 的值对其进行初始化来解决此问题
const gridSpace: domain(2) dmapped Block(boundingBox=Space) = Space;
有关更多示例,请参阅 Distributions primer。
- 上面的
forall
循环中不需要do
。 do
仅在省略单个表达式 for 循环体的花括号时才需要,例如
for i in dom do writeln(i);
有关详细信息,请参阅 for-loops guide。
我在尝试使用 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 个其他问题:
gridSpace
只定义了类型,没有值,实际上是一个空的分布式域。您可以通过使用Space
: 的值对其进行初始化来解决此问题
const gridSpace: domain(2) dmapped Block(boundingBox=Space) = Space;
有关更多示例,请参阅 Distributions primer。
- 上面的
forall
循环中不需要do
。do
仅在省略单个表达式 for 循环体的花括号时才需要,例如
for i in dom do writeln(i);
有关详细信息,请参阅 for-loops guide。