给定一些对 1 到 500000 之间的每个数字进行一些数学/转换的代码,我们有选择:
简单的for循环:for ^500000 -> $i { my $result = ($i ** 2).Str; }
。在我的不科学基准测试中,这需要 2.8 秒。
最规范的并行版本在一个Promise
,然后等待结果。await do for ^500000 -> $i { start { my $result = ($i ** 2).Str; } }
需要 19 秒。这很慢!创建一个新的 Promise 必须有太多的开销,对于如此简单的计算来说是不值得的。
使用并联map
操作速度相当快。在 2.0 秒时,该操作似乎慢到足以利用并行化:(^500000).race.map: -> $i { my $result = ($i ** 2).Str; }
第三种选择似乎是最好的。不幸的是,它读起来就像一个黑客。我们不应该写map
在接收器上下文中迭代的代码,因为在源中读取“map”的其他人可能会假设目的是构建一个列表,这根本不是我们的意图。使用起来沟通很差map
这边走。
有没有任何规范的快速方法来使用 Perl 6 的内置并发性?如果超级运算符可以接受块而不是仅接受函数,那么它就是完美的:
(^500000)».(-> $i { my $result = ($i ** 2).Str; }) # No such method 'CALL-ME' for invocant of type 'Int'
如果您想将 for 与 hyper 或 race 操作一起使用,则必须拼写它hyper for @blah.hyper(:batch(10_000))
or race for @blah.race(:batch(10_000))
。或者不带参数:hyper for @blah
, race for @blah
.
决定这样做是因为您可能有类似的代码for some-operation() { some-non-threadsafe-code }
where some-operation
是图书馆或其他东西的一部分。现在您无法再判断 for 循环中是否可以包含线程不安全代码,即使您知道该库不会返回HyperSeq
那时,如果库作者想出这个怎么办?好想法使some-operation
通过超级化来更快?
这就是为什么“并行运行这个 for 循环是安全的”的指示符需要在代码所在的位置,而不仅仅是创建序列的位置。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)