Chapel中的等价于numpy的`arange` / 等价于C for循环

3
什么是在Chapel中以固定增量循环一系列实数的最惯用方法?
C语言等效代码如下:
for (x = 0.0; x<1.0; x+=0.1) {}

在Python/Numpy中,有人可能会写成:
x = numpy.arange(0.0, 1.0, 0.1)

我可以想象编写以下迭代器,但语言/标准模块中是否有等效项呢?当然,还有编写此类并发版本的问题。
iter arange(start, stop, step) {
  var x = start;
  while (x < stop) {
     yield x;
     x += step;
  }
}

我不了解Chapel,但似乎你只需要使用基本词汇“iterate”或“loop”,就可以找到类似的东西。手册中有这些内容,它们看起来很“原始”,就像你所要求的:https://chapel-lang.org/docs/1.14/users-guide/base/forloops.html 编辑:我不确定那些范围值是否可以是小数..如果不行,你可能可以使用除法。 - Stephen J
2个回答

4

我来详细解释一下迭代器的选项:定义一个迭代器可以使你轻松地获取数组语义(感谢 Chapel!)。接下来,我们将使用一些测试用例来扩展上面的代码:

// Define the general case
iter arange(type t, start, stop, step=1:t) {
  assert(stop > start, "Stop must be greater than start");
  assert(step > 0, "Step must be greater than 0");
  var x : t = start;
  while (x < stop) {
    yield x;
    x += step;
  }
}

// Overload for type from arguments
iter arange(start:?t, stop:t, step:t=1:t) {
  for x in arange(t, start, stop, step) do yield x;
}

// Overload for no start and default step = 1
iter arange(type t, stop) {
  for x in arange(t, 0, stop, 1) do yield x;
}

// Overload for no start and default step = 1
iter arange(stop:?t) {
  for x in arange(t, 0, stop, 1) do yield x;
}


// Example of simple iteration
for xi in arange(0.0,1.0,0.1) do writef(" %r",xi);
writef("\n");
for xi in arange(real,0,1,0.1) do writef(" %r",xi);
writef("\n");


// But Chapel allows other wonderful things once you
// define an iterator

// Array assignment
var x = arange(real, 0, 1, 0.1);
writeln(x);

// Promote a scalar function
var y = sin(2*pi*arange(real, 0, 1, 0.1));
for yi in y do writef(" %.3r",yi);
writef("\n");

// Step is optional
writeln(arange(real, 0, 10));
writeln(arange(0.0, 10.0));

运行此代码将会产生:
 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
 0 0.588 0.951 0.951 0.588 1.22e-16 -0.588 -0.951 -0.951 -0.588 -1.13e-15
0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0

3
目前,Chapel没有内置支持迭代常规浮点值序列的功能。我们曾讨论过将Chapel的范围类型扩展到支持浮点索引类型,但目前为止尚未实现该想法。我相信目前也没有任何标准库支持这种模式。在 Chapel 的 GitHub 问题页面上提出这些特性请求都是合理的。
如果我今天编写此模式,我要么编写像你一样的迭代器,要么直接将while循环放入我的代码中。对于浮点值范围的并行迭代,创建一系列迭代器重载(如 Chapel 的 parallel iterators primer 中所述)将是解决问题的方法。

谢谢!跟进一下:如果并行迭代器不存在,Chapel会在forall循环中退回到串行迭代吗? - Nikhil Padmanabhan
1
好问题(而且时机恰当)!这个具体问题最近一直在讨论中。目前的想法是,在源代码中出现“forall”关键字的上下文中,缺乏并行迭代器将导致编译器错误。而在隐式并行性的情况下——例如提升调用、约简或约减表达式——缺乏并行迭代器将导致回退到串行迭代器。 - Brad
我应该补充一点的是,当我说“最近”时,我指的是自1.18.0版本发布以来一直在进行这个讨论,因此我所描述的可能不反映用户今天下载的情况。但意图是让下一个版本反映这些规则。 - Brad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接