Chapel 的一个很好的特性是它区分了数组的域和它的分布。检查两个数组是否具有相同的域和分布(通常想要的)的最佳方法是什么?
我能看到的最好的方法是检查D1==D2
和D1.dist==D2.dist
,如果D1
和D2
都是域。
特别地,请考虑以下代码:
const Dom = {1..5, 1..5};
const BDom = newBlockDom(Dom);
var x : [Dom] int;
var y : [BDom] int;
test(x,y);
proc test(a : [?Dom1] int, b : [Dom1] int) {
}
Run Code Online (Sandbox Code Playgroud)
这编译并运行得很好,如果函数声明中的查询语法只是测试域相等性,而不是分布相等性(即使Dom1
也知道如何a
分布),这是有道理的。在这种情况下检查分布相等的唯一方法是做a.domain.dist==b.domain.dist
什么?
要检查两个域是否描述 Chapel 中的相同分布式索引集,您使用D1 == D2
和是正确的D1.dist == D2.dist
。Chapel 中的域相等检查两个域是否描述相同的索引集,因此独立于域映射/分布。类似地,两个域映射/分布之间的相等检查检查它们是否相同地分布索引。
请注意,在 Chapel 中,域和发行版都有身份概念,因此如果您创建了两个分布式域,如下所示:
var BDom1 = newBlockDom(Dom),
BDom2 = newBlockDom(Dom);
Run Code Online (Sandbox Code Playgroud)
它们将通过上述相等性检查,但具有不同的域值。在某些情况下,想知道两个域表达式是否引用相同的域实例可能是合理的,但我相信今天在 Chapel 中没有面向用户的官方方法来做到这一点。如果对此感兴趣,值得在我们的GitHub 问题页面上提交功能请求。
关于您的代码示例:
const Dom = {1..5, 1..5};
const BDom = newBlockDom(Dom);
var x : [Dom] int;
var y : [BDom] int;
test(x,y);
proc test(a : [?Dom1] int, b : [Dom1] int) {
}
Run Code Online (Sandbox Code Playgroud)
这里有一个微妙的地方需要一些解释。首先,请注意,如果您反转例程的参数test()
,它将无法编译,其行为可能更类似于您所期望的(TIO):
test(y,x);
Run Code Online (Sandbox Code Playgroud)
原因是没有显式域映射的域在形式数组参数中被特殊对待。具体来说,在定义 Chapel 时,我们不想有一个像这样声明的正式参数X
:
proc foo(X: [1..n] real) { ... }
Run Code Online (Sandbox Code Playgroud)
要求实际的数组参数是非分布式的/具有默认的域映射。换句话说,我们希望用户能够传入一个从中索引的块分布或循环分布数组,1..n
以便形式约束数组的索引集而不是其分布。相反,如果形式参数的域是根据显式域映射定义的,例如:
proc bar(X: [BDom] int) { ... }
Run Code Online (Sandbox Code Playgroud)
(使用上面的块分布式定义BDom
),它需要实际的数组参数来匹配该域。
这样做的效果是,在您的示例中,由于Dom1
与具有默认域映射的域匹配,b
因此同样松散地约束为具有任何分布的相同索引集。而当第一个实际参数是块分布时(如我的调用中),Dom1
对该分布进行编码并将约束应用于b
.
如果你对此的反应是感觉混乱/不对称,我倾向于同意。我相信我们已经讨论过在这方面以不同于匿名域的方式对待声明/命名域(因为X: [1..n]
我们在采用此规则时重点关注的是域的匿名性,并且它在像这样的情况下应用于查询域Dom1
是一些事情)当前实施的副作用)。同样,GitHub 问题对于质疑/挑战这种行为来说是完全公平的。