gpt4 book ai didi

chapel - 记录数组上的域大小调整挂起

转载 作者:行者123 更新时间:2023-12-04 18:01:18 25 4
gpt4 key购买 nike

我有一个带有两个数组的超图数据结构,一个用于边,一个用于顶点(类似于二部图)。我在调整数组大小时遇到​​问题,因此我尝试了简化示例:

ar dom = {0..0};

var arr: [dom] int;

writeln(arr);

dom = {0..#2};

writeln(arr);

dom = {0..#1};

writeln(arr);

record Vertex {}
record Edge {}

record Wrapper {
type nodeType;
type idType;
var id: idType;
}

record NodeData {
type nodeIdType;

var ndom = {0..-1};
var neighborList: [ndom] nodeIdType;

proc numNeighbors() return ndom.numIndices;
var lock$: sync bool = true;

// This method is not parallel-safe
proc addNodes(vals) {
lock$; // acquire lock
neighborList.push_back(vals);
lock$ = true; // release the lock
}

proc readWriteThis(f) {
f <~> new ioLiteral("{ ndom = ") <~> ndom <~> new ioLiteral(", neighborlist = ") <~> neighborList <~> new ioLiteral(", lock$ = ") <~> lock$.readFF() <~> new ioLiteral(" }");
}
}

type vType = Wrapper(Vertex, int);
type eType = Wrapper(Edge, int);

var dom1 = {0..0};
var arr1: [dom1] NodeData(eType);

writeln(arr1);

dom1 = {0..#2};

writeln(arr1);

dom1 = {0..#1};

writeln(arr1);

当我尝试运行此代码时,它会挂起以下输出:
$ ./resize -nl 1
salloc: Granted job allocation 15015
0
0 0
0
{ ndom = {0..-1}, neighborlist = , lock$ = true }

所以调整整数数组的大小工作得很好,但我无法调整我的记录数组的大小。我究竟做错了什么?

附带说明一下,当我尝试在我的完整代码中调整域大小时,我看到域发生了变化,但我使用域的数组根本没有变化。至少代码不会挂起。

编辑

我尝试了另一个例子,它实际上更好地说明了我原来的问题:
class Test {
var dom;

var ints: [dom] int;

proc resize(size) {
dom = {dom.low..size};
}
}

var test = new Test(dom = {0..-1});
writeln(test);
test.resize(1);
writeln(test);

这是我看到的输出:
$ ./resize -nl 1
salloc: Granted job allocation 15038
{dom = {0..-1}, ints = }
{dom = {0..1}, ints = }
salloc: Relinquishing job allocation 15038

所以我的问题是 resize方法没用。它确实会更改域,但不会更改成员数组。

最佳答案

以下是对您在 EDIT 示例中看到的问题的回应:

我担心你在 1.17 版本中陷入了编译器的一个黑暗角落,我很遗憾它的存在,尽管我认为我们可以让你摆脱它。

从一些背景和重要上下文开始:从一开始,Chapel 就支持类和记录的构造函数(例如, proc C(...) 表示 class C),但这些在设计上很幼稚,尤其是 w.r.t.通用类和记录。在过去的几个版本中,我们一直在从构造函数转向初始化器(例如, proc init(..) 代表 class C)来解决这些限制。

截至今天发布的 1.17 版,初始值设定项处于相当好的状态(例如,我现在将它们用于我编写的所有新代码并且很少对它们发誓),但是如果您既没有提供初始值设定项也没有提供构造函数(如您的示例中所示) ,编译器将创建一个默认构造函数(而不是默认初始值设定项),因此可能会与这些长期存在的一些问题发生冲突。对于 1.18 版,目标是让编译器默认创建初始化器并完全弃用构造器。

因此,这里有一些方法可以解决 EDIT 中较小测试程序的问题,所有这些方法似乎都能在 Chapel 1.17 版中为我生成正确的输出:

1)使类不那么通用。在这里,我给了 dom字段一个初始值,以便编译器可以确定其类型,这显然有助于它使用默认构造函数足以生成预期的输出:

class Test {
var dom = {0..-1};

var ints: [dom] int;

proc resize(size) {
dom = {dom.low..size};
}
}

var test = new Test(dom = {0..-1});
writeln(test);
test.resize(1);
writeln(test);

2) 编写一个显式初始化程序。在这里,我要走了 dom通用但创建一个初始化程序,将其分配为匹配您的签名 new称呼:
class Test {
var dom;

var ints: [dom] int;

proc init(dom: domain(1)) {
this.dom = dom;
}

proc resize(size) {
dom = {dom.low..size};
}
}

var test = new Test(dom = {0..-1});
writeln(test);
test.resize(1);
writeln(test);

3)(最后的手段)请求编译器为你创建一个默认的初始化程序(而不是默认的构造函数)。这种方法确实不适用于最终用户,不适用于所有情况,并且将来会消失,但在此期间可能会很方便。在这里,我将一个编译指示附加到该类,以告诉编译器创建一个默认初始化程序而不是默认构造函数。尽管默认情况下编译器不会创建默认初始化程序,但对于许多类和记录,如果您要求,它可以创建,这恰好是其中之一:
pragma "use default init"
class Test {
var dom;

var ints: [dom] int;

proc resize(size) {
dom = {dom.low..size};
}
}

var test = new Test(dom = {0..-1});
writeln(test);
test.resize(1);
writeln(test);

为节省篇幅,我在这里只讨论了较短的示例,而不是较长的示例,但希望这些技术也能对此有所帮助(如果需要,我很乐意花更多时间在较长的示例上)。

关于chapel - 记录数组上的域大小调整挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49682634/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com