Raku 比较如何才能提高性能?

问题描述 投票:0回答:1

我想在学习 Raku 的同时对 Python 和 Raku 进行一些比较。

本来我想要一个更大的脚本,但由于差异已经很大,我现在就寻求指导。

我尝试忠实地翻译这个 Python 脚本,同时应用不应该损害性能的 Raku 知识:

from collections import deque
from itertools import count, islice


def primes_wheel():
    yield 2
    composites = {}
    for candidate in count(3, step=2):
        prime = composites.pop(candidate, 0)
        if prime:
            while True:
                candidate += prime + prime
                if candidate not in composites:
                    composites[candidate] = prime
                    break
        else:
            composites[candidate * candidate] = candidate
            yield candidate


def last(itr):
    return deque(itr, 1).pop()


LENGTH = 99999

print(last(islice(primes_wheel(), 0, LENGTH)))

我到达了这个:

sub primes_wheel {
    my %composite;

    gather {
        take 2;
        for 3,5…* -> $candidate is copy {
            my $prime = %composite{$candidate}:delete;
            if $prime.defined {
                loop {
                    $candidate += $prime + $prime;
                    if not %composite{$candidate}:exists {
                        %composite{$candidate} = $prime;
                        last;
                    }
                }
            }
            else {
                %composite{$candidate * $candidate} = $candidate;
                take $candidate;
            }
        }
    }
}

constant LENGTH = 99999;

say primes_wheel[LENGTH - 1];

结果确实对 Raku 不利(

-OO
对于 Python 来说没有太大区别,但
--optimize=3
使 Raku 变慢):

% hyperfine 'raku primes.raku' 'python -OO primes.py'
Benchmark 1: raku primes.raku
  Time (mean ± σ):      4.953 s ±  0.050 s    [User: 4.986 s, System: 0.040 s]
  Range (min … max):    4.899 s …  5.036 s    10 runs

Benchmark 2: python -OO primes.py
  Time (mean ± σ):     291.3 ms ±  13.8 ms    [User: 125.2 ms, System: 15.2 ms]
  Range (min … max):   266.4 ms … 315.9 ms    10 runs

Summary
  python -OO primes.py ran
   17.01 ± 0.82 times faster than raku primes.raku

我是否错过了什么或没有以正确的方式使用东西?我希望 Raku 能赶上。我对性能改进和 Rakuisms 都很感兴趣。

performance generator primes raku
1个回答
0
投票

在我看来,你应该利用编程语言的优势,而不是试图模仿其他语言的方法。在这种情况下:

constant LENGTH = 99999;
my @primes = (^Inf).grep(*.is-prime);
say @primes[LENGTH - 1];

或者,如果您对两者之间的值并不真正感兴趣:

say (^Inf).grep(*.is-prime).skip(LENGTH - 1).head;

在我的 M1 MacMini 上运行大约需要 0.56 秒。然而,这种管道方法允许使用多个 CPU 来进行超级操作:

say (^Inf).hyper(batch => 2048).grep(*.is-prime).skip(99998).head;

这对我来说大约需要 0.24 秒。减去 0.11 的启动开销,速度大约是原来的 3.5 倍。这在 4 核机器上还算不错。

© www.soinside.com 2019 - 2024. All rights reserved.