Raku vs Perl使用质数进行基准测试



这是一个从这里的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,可悲的是,它没有像操作员/方法一样多的字符串,但只是字节的一个块。

相关内容

  • 没有找到相关文章

最新更新