我可以使用 Hyper 并行执行,并且它可以工作:
$ raku -e 'race for (^8).race(batch => 1, degree => 4) {sleep rand; .say}'
0
3
5
2
1
7
4
6
但是我怎样才能将收集/获取行为添加到这样的循环中?
在这种方法中,take 不会检测到它被包裹在 gather 上下文中:
$ raku -e '
my @x = gather race for (^8).race(batch => 1, degree => 4) {
sleep rand;
take $_;
};
@x.say
'
Died at:
take without gather
在这种方法中,gather 将消耗 HyperSeq 而不会真正对其进行“超级处理”:
$ raku -e '
my @x = race gather for (^8).race(batch => 1, degree => 4) {
sleep rand;
take $_;
};
@x.say
'
[0 1 2 3 4 5 6 7]
您所要求的是一种并行数据结构(在本例中是收集/获取结果的容器),用于保护来自多个线程的写入操作。虽然 raku 语法不会阻止这样的实现,但它并不旨在使标准数据结构原子化,因为这会增加大量开销和死锁的可能性。在这种要求下,raku 具有出色的并发语法,可帮助您跨多个进程映射/减少计算。
请参阅gather take 文档底部的注释,其中提到了与 react/whenever 类似的问题,即新线程上没有控制异常的处理程序。例如:
但仅限于星期二。我猜你已经知道我回答的第一部分,但编译器可以决定是否并行化。略微但公平地引用相关设计文档并强调:
----
再次引用设计文档:
也就是说,使用
race
意味着您已经自动免费获得gather
/take
行为,而无需实际使用gather
/take
。----
我不确定该如何看待这两种情况。
----
在回答Raku 提供了哪些并发机制? 时,Jonathan Worthington 提到了以下
gather
内容take
:我不太确定括号里的内容。我无法解析“这不属于任何涉及的上下文”,而且句子的后半部分似乎含糊不清。
----
让我印象深刻的一件事是
gather
/take
默认为lazy。使用 ofrace
应该覆盖它,并使其变为eager,但我心里想,Rakudo 可能有一个错误导致它处于 lazy 状态,并且想知道是否是 lazy 行为导致了代码中看到的行为race gather ...
。然而,我尝试在我认为可能需要的地方插入显式eager
,但我所做的一切都没有起到作用。