检查/确保两个数组具有相同的域和分布的最佳方法是什么?

Nik*_*han 5 chapel

Chapel 的一个很好的特性是它区分了数组的域和它的分布。检查两个数组是否具有相同的域和分布(通常想要的)的最佳方法是什么?

我能看到的最好的方法是检查D1==D2D1.dist==D2.dist,如果D1D2都是域。

特别地,请考虑以下代码:

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什么?

Bra*_*rad 3

要检查两个域是否描述 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 问题对于质疑/挑战这种行为来说是完全公平的。

  • 布拉德 - 感谢您非常详细的回答。我打开了一个 github 问题 (https://github.com/chapel-lang/chapel/issues/15877) 只是为了捕获设计讨论。 (2认同)