这是一个从这里的HN线程进行的讨论,关于使用算法使用算法来实现Sundaram的筛子以寻找质数。
的基准测试。以下是原始线程中的原始代码:
perl5 0m0.156s
perl6 0m6.615s
问题在于,与Perl5实现相比,Perl6版本要花太长时间才能找到素数。它的一部分是由于使用浮子作为输入,但它仍然太慢。
目的不一定是优化算法,而是要确定与其他语言相比,perl6如此慢。
事实证明,即使素数是整数,在您的perl 6版本中,每个计算都是通过使用浮点来完成的。这是由对子例程的呼吁造成的。如果您这样做:
sieve_sundaram(1000)
而不是:
sieve_sundaram(1e3)
然后,突然变成4倍。在Perl 5中,您永远不知道您在价值观方面处理什么。在Perl 6中,如果您告诉它使用浮点,它将感染所有计算以后在浮点处。1e3
是浮点值。1000
是Perl 6中的整数。
另外,您似乎具有一个优化算法:第二个foreach
不需要从1..$n
转移,但可以从$i..$n
转。这将Perl 5版本的代码的运行时间降低到我的89毫秒。
由于您的程序在Perl 5版本中不使用BigInt,因此基本上是使用本机整数。在Perl 6中,所有整数计算始终是bigint,除非您将其标记为本地。如果我为此调整您的perl 6版本,则此版本的运行时从4671毫秒下降到414毫秒:
sub sieve_sundaram(int $n) {
my %a;
my int @s = 2;
my int $m = $n div 2 - 1;
for 1..$n -> int $i {
for $i..$n -> int $j {
my int $p = $i + $j + 2 * $i * $j;
if $p < $m {
%a{$p} = True;
}
}
}
for 1..$m -> int $k {
if ! %a{$k} {
my int $q = 2 * $k + 1;
@s.push($q);
}
}
return @s;
}
sieve_sundaram(1000);
所以,比以前快约11倍。
不像Perl 5版本那样慢的5倍。在perl 6中获得素数的最惯用版本是:
(1..1000).grep( *.is-prime )
对我来说,在您的原始Perl 5算法的噪声中执行。对于多CPU机器上的较大值,我将其写为:
(1..2500).hyper.grep( *.is-prime )
大约2500大约hyper
的速度更快,因此工作会自动分布在多个CPU上。
我认为我不能为莉兹所说的添加更多。除了:
"但是为了基于多种语言,我需要运行相同的 到处都是"
...中,"相同"定义为英语中的相似语法,是非常 差的标准差异很差。Perl 6在下面执行非常不同的语义时,与Perl 5具有非常相似甚至相同的语法。整个语言已通过默认的语法而不是最佳行为调整为正确性。另一个很好的例子是Perl 6弦,它们非常慢,它们总是完全归一化的Unicode,而不是一串普通字节。对它们的所有操作都考虑素描的Unicode概念,而不是字节和字节偏移。这太好了!但是,与C/Perl 5字符串更等同的类型可能是Buf
,可悲的是,它没有像操作员/方法一样多的字符串,但只是字节的一个块。