2

在下面的代码中,我试图A通过使用varor来获取数组的第一行和第二行ref。在这里,我的理解是var总是创建一个新数组,同时ref在右侧创建一个别名(或引用)。

var A: [1..2, 1..3] int;
A = 0;

var row1 = A[ 1, .. ];
ref row2 = A[ 2, .. ];

row1 = 10;
row2 = 20;

writeln( "row1 = ", row1 );
writeln( "row2 = ", row2 );

writeln( "A = ", A );

结果如预期(即第一行A没有修改):

row1 = 10 10 10
row2 = 20 20 20
A = 0 0 0
20 20 20

但是如果我打印的类型row1row2

writeln( "row1.type = ", row1.type: string );
writeln( "row2.type = ", row2.type: string );

我得到这个结果:

row1.type = [ArrayViewRankChangeDom(1,int(64),false,2*bool,2*int(64),ArrayViewRankChangeDist(DefaultDist,2*bool,2*int(64)))] int(64)
row2.type = [ArrayViewRankChangeDom(1,int(64),false,2*bool,2*int(64),ArrayViewRankChangeDist(DefaultDist,2*bool,2*int(64)))] int(64)

这有点令人惊讶,因为我假设row1它是一个“普通”数组(即,不是别名)。例如,以下vec(我称之为“普通”数组)

var vec: [1..3] int;
writeln( "vec.type = ", vec.type: string ); 

vec.type = [domain(1,int(64),false)] int(64)

所以我想知道row1vec(作为数组类型)之间是否有一些区别......?

4

1 回答 1

2

我想知道 row1 和 vec (作为数组类型)之间是否有一些区别......?

存在差异,尽管您是否认为它是类型的差异在某种程度上取决于您对类型的概念。每个 Chapel 阵列都是根据域映射定义的,该映射指定如何定义它(以及如何定义它的域)。如果未指定域映射,则使用默认域映射。数组的域映射在技术上是其类型的一部分,但在实践中,它往往是影响数组实现方式的一个方面,而不是可应用于数组的操作。

因此,在您的示例中,是一个由 s 索引的元素vec的一维数组(并且其索引是不可跨步的,这是其域签名中的代表),并且其域映射是默认域映射。同时,您的切片表达式也是由 s 索引的元素的一维数组(并且也是不可跨步的),但它们的域映射是. 这是一个内部域映射,它表示另一个数组的排名变化别名(“视图”)。int(64)int(64)falseA[i, ..]int(64)int(64)ArrayViewRankChange

[使用这个不同的域映射来表示数组的等级变化切片的简短版本是这样的:如果原始二维数组是分布式的(比如说),它的一维切片应该也应该类似地分布 - - 这表明它不应该是默认域映射(未分发),也不是原始数组的分布(描述如何实现 2D 事物)。所以选择要么让秩变化切片需要域映射来创建它们自己的新的低维域映射(这往往介于具有挑战性和不可能之间),要么使用一个知道如何从一维索引转换的新域映射到原始分布的二维索引。这就是ArrayViewRankChange域映射的作用。更长版本的基本原理可以在从幻灯片 27(“阵列视图”)开始的1.15 发行说明。]

row2鉴于上述情况,它可能也表示ArrayViewRankChange其域映射是有意义的,因为它是对秩变化切片表达式的引用。但它可能更令人惊讶row1,因为它是一个全新的阵列,导致阵列的深层副本,ArrayViewRankChange因此可以使用传统的默认阵列存储。但是在分布式情况下可以再次看到基本原理,其中新数组变量应该(可能)具有与原始数组相同的分布——我们这样做的方法是通过ArrayViewRankChange.

如果你想强制一个数组切片成为“一个普通数组”,你可以使用更精确的声明来做到这一点:

var row1b: [A.domain.dim(2)] A.eltType = A[1, ..];

此时其类型将匹配vecs:

row1b.type = [domain(1,int(64),false)] int(64)

说了这么多,希望你会发现你可以使用row1并且row2在大多数你可以使用的地方vec。如果没有,请提出后续问题或在 GitHub 上提交问题。

作为结束语,可以说编译器可以/应该更好地打印数组类型,或者至少为打印出其类型的详细程度提供不同的选项(例如,在许多情况下,可能识别域map 是不必要的,或者域类型可以更简单地打印出来?)

于 2017-06-06T04:33:54.403 回答