2017-06-06 81 views
2

在下面的代码中,我试图通过使用varref来获取数组A的第1行和第2行。在这里,我的理解是,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 

但如果我打印的row1类型和row2

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之间的一些差异(如数组类型) ...?

回答

2

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

虽然您是否认为它是类型上的差异,但还是有所不同,这取决于您的类型是什么。每个Chapel数组都根据域映射来定义,该映射指定了它如何定义(以及如何定义域)。如果未指定域映射,则使用默认域映射。数组的域映射在技术上属于其类型的一部分,但在实践中,它往往是一个应该影响数组如何实现的方面,而不是可应用于数组的操作。

所以vec在你的例子是int(64)小号索引int(64)元素的一维数组(和它的指数是不stridable这正是在其领域的签名false代表),其域图是默认域图。同时,您的切片表达式A[i, ..]也是int(64)元素的一维数组,其索引为int(64)(并且也不可变),但其域映射是ArrayViewRankChange。这是一个内部域映射,表示另一个数组的等级更改别名(“视图”)。使用这个不同的域映射表示数组的rank-change slice的基本原理的简短版本是这样的:如果原始的2D数组是分布式的(比如说),它的一维片段应该是相似的分布式 - 这表明它不应该是默认的域映射(不是分布式的),也不应该是原始数组的分布(描述如何实现2D事物)。所以选择要么是等级切换片需要域映射来创建它们自己的新的低维域映射(这往往是在具有挑战性和不可能的之间)或者使用知道如何从一维索引转换的新的域映射到原始分布的二维指标。这就是ArrayViewRankChange域映射所要做的。理的一个更长的版本可以在1.15 release notes开始幻灯片27(“阵意见”)。]

鉴于上述情况可以发现,它可能是有道理的,row2也将表明ArrayViewRankChange作为其领域的地图,因为它是一个参考等级切换片表达式。但row1可能会更令人惊讶,因为它是一个全新的阵列,导致ArrayViewRankChange阵列的深层副本,因此可以使用传统的默认阵列存储。但是在分布式情况下,可以再次看到这个基本原理,其中新的数组变量应该(可能)与原始变量具有相同的分布 - 我们的方法是通过ArrayViewRankChange

如果你想迫使一个数组片断是“一个正常的数组”,你可以这样做使用更精确的声明:

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

此时它的类型将匹配vec S:

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

所有这些说,希望你会发现,你可以使用row1row2在大多数地方,你可以使用vec。如果没有,请在GitHub上提出后续问题或提出问题。作为最后说明,可以说编译器可以/应该更好地更好地打印数组类型,或者至少为打印出类型的冗长级别提供不同的选项(例如,在很多情况下,也许识别域映射是不必要的,或者可能更简单地打印域类型?)