关于域的索引如何映射到程序的语言环境的具体细节不是由 Chapel 语言本身定义的,而是由用于声明域的域映射的实现来定义的。在您的问题下的评论中,您提到您指的是Block
分发,因此我将在我的回答中重点关注这一点(在此处记录),但请注意,任何其他域映射都可以采用不同的方法。
该Block
分布采用一个可选targetLocales
参数,允许您指定要定位的语言环境集,以及它们的虚拟拓扑。例如,如果我声明并填充一些语言环境数组:
var grid1: [1..3, 1..2] locale, // a 3 x 2 array of locales
grid2: [1..2, 1..3] locale; // a 2 x 3 array of locales
for i in 1..3 {
for j in 1..2 {
grid1[i,j] = Locales[(2*(i-1) + j-1)%numLocales];
grid2[j,i] = Locales[(3*(j-1) + i-1)%numLocales];
}
}
然后我可以将它们作为targetLocales
参数传递给一个Block
分布式域的几个实例:
use BlockDist;
config const n = 8;
const D = {1..n, 1..n},
D1 = D dmapped Block(D, targetLocales=grid1),
D2 = D dmapped Block(D, targetLocales=grid2);
每个域将其n
行分配到其targetLocales
网格的第一个维度,将其n
列分配到第二个维度。我们可以通过在这些域上声明整数数组并并行分配它们以使每个元素存储其拥有的区域设置 ID 来查看此分布的结果,如下所示:
var A1: [D1] int,
A2: [D2] int;
forall a in A1 do
a = here.id;
forall a in A2 do
a = here.id;
writeln(A1, "\n");
writeln(A2, "\n");
在六个或更多语言环境 ( ./a.out -nl 6
) 上运行时,输出如下,揭示了底层网格结构:
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
2 2 2 2 3 3 3 3
2 2 2 2 3 3 3 3
2 2 2 2 3 3 3 3
4 4 4 4 5 5 5 5
4 4 4 4 5 5 5 5
0 0 0 1 1 1 2 2
0 0 0 1 1 1 2 2
0 0 0 1 1 1 2 2
0 0 0 1 1 1 2 2
3 3 3 4 4 4 5 5
3 3 3 4 4 4 5 5
3 3 3 4 4 4 5 5
3 3 3 4 4 4 5 5
For a 1-dimensional targetLocales
array, the documentation says:
If the rank of targetLocales
is 1
, a greedy heuristic is used to reshape the array of target locales so that it matches the rank of the distribution and each dimension contains an approximately equal number of indices.
For example, if we distribute to a 1-dimensional 4-element array of locales:
var grid3: [1..4] locale;
for i in 1..4 do
grid3[i] = Locales[(i-1)%numLocales];
var D3 = D dmapped Block(D, targetLocales=grid3);
var A3: [D3] int;
forall a in A3 do
a = here.id;
writeln(A3);
we can see that the target locales form a square, as expected:
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
2 2 2 2 3 3 3 3
2 2 2 2 3 3 3 3
2 2 2 2 3 3 3 3
2 2 2 2 3 3 3 3
The documentation is intentionally vague about how a 1D targetLocales
argument will be reshaped if it's not a perfect square, but we can find out what's done in practice by using the targetLocales()
query on the domain. Also, note that if no targetLocales
array is supplied, the entire Locales
array (which is 1D) is used by default. As an illustration of both these things, if the following code is run on six locales:
var D0 = D dmapped Block(D);
writeln(D0.targetLocales());
we get:
LOCALE0 LOCALE1
LOCALE2 LOCALE3
LOCALE4 LOCALE5
illustrating that the current heuristic matches our explicit grid1
declaration above.