32

Rakudo Perl 6の新しいコピーをダウンロードするたびに、現在のパフォーマンスを把握するために、次の式を実行しました。

say [+] 1 .. 100000;

また、速度は向上していますが、毎回、計算に顕著な遅延(数秒)があります。比較として、Perl 5(または他のインタプリタ言語)でのこのようなものは、ほぼ瞬時に返されます。

use List::Util 'sum';

print sum(1 .. 100000), "\n";

またはRubyの場合(ほぼ瞬時に):

(1 .. 100000).inject(0) {|sum,x| sum+x}

式をPerl6として書き直すとloop、範囲を縮小する場合の約2倍の速度になりますが、単純な計算では、それでも非常に顕著な遅延(1秒以上)になります。

my $sum;
loop (my $x = 1; $x <= 100000; $x++) {$sum += $x}

だから私の質問は、Perl6実装のどの側面がこれらのパフォーマンスの問題を引き起こしているのかということです。そして、これは時間とともに改善する必要がありますか、それともこのオーバーヘッドは、Perl6が使用している「すべてがオブジェクトである」モデルの不幸な副作用ですか?

そして最後に、loop構成は[+]リダクション演算子よりも高速です。ループは、削減よりも合計操作数が多くなると思います。

編集:

できればmortiz、との両方の答えを受け入れます。すべてがメソッド呼び出しとして処理されているということは、なぜ遅いのかをhobbsより直接的に答えるので、それを取得できます。[+]

4

5 に答える 5

23

Rakudoがとても遅い理由は本当にいろいろあります。

最初の、そしておそらく最も重要な理由は、Rakudoがまだ最適化を行っていないことです。現在の目標は、新機能をさらに探求し、より堅牢になることです。あなたが知っている、彼らは「最初にそれを実行させ、次にそれを正しくし、そしてそれを速くする」と言います。

2番目の理由は、オウムがまだJITコンパイルを提供しておらず、ガベージコレクターが最速ではないことです。JITコンパイラの計画があり、人々はそれに取り組んでいます(前のコンパイラはi386のみであり、メンテナンスの悪夢だったため、取り外されました)。Rakudoを他のVMに移植することも考えられますが、それはきっと7月末まで待つでしょう。

結局、完全で十分に最適化されたPerl 6の実装がどれだけ速くなるかは、私たちがそれを手に入れるまで誰にもわかりませんが、今よりもはるかに優れていると思います。

ところで、あなたが引用したケースは、内省可能な範囲を返す[+] 1..$big_numberため、O(1)で実行することができます。したがって、ケース1..$big_numberに合計式を使用できます。[+] Range繰り返しますが、それは実行できることですが、まだ実行されていません。

于 2010-06-28T21:17:26.207 に答える
21

最適化の欠如について理解しなければならないもう1つのことは、それが複合されているということです。Rakudoの大部分はPerl6で書かれています。したがって、たとえば、[+]演算子は、内部ループとしてAny.reduce持つメソッド($expressionset toで呼び出される)によって実装されます。&infix:<+>

for @.list {
    @args.push($_);
    if (@args == $arity) {
        my $res = $expression.(@args[0], @args[1]);
        @args = ($res);
    }
}

言い換えれば、reduceのpure-perl実装であり、それ自体がRakudoによって実行されています。したがって、表示されているコードが最適化されていないだけでなくコードを実行していると表示されていないコードも最適化されていません。演算子のインスタンスでさえ+実際にはメソッド呼び出しです。+演算子onNumはParrotによって実装されていますが、Rakudoにはまだ2つあることを認識してNumメソッド呼び出しを最適化するものがないため、Rakudoが検出する前に完全な動的ディスパッチがあります。multi sub infix:<+>(Num $a, Num $b)そして、それが実際に行っているのは「追加」オペコードだけであることに気づきます。Perl 5よりも100〜1000倍遅いのは合理的な言い訳です:)

2010年8月23日更新

Perl6の「すべてがメソッド呼び出し」の性質を維持しながら物事を高速化するためにPerl6オブジェクトモデル(または少なくともRakudoの概念)で発生する必要のある変更の種類に関するJonathanWorthingtonからの詳細情報。

2019年1月10日更新

これがまだ注目されていることがわかるので...長年にわたって、Rakudo / MoarVMは、システムのあらゆる部分を最適化する多くの人々によって、JIT、インライン化、動的な特殊化、および大量の作業を取得してきました。その結果、これらのメソッド呼び出しのほとんどは「コンパイル」でき、実行時のコストはほぼゼロになります。Perl 6は、多くのベンチマークで2010年よりも数百倍または数千倍高速であり、場合によってはPerl5よりも高速です。

質問が始まった合計が100,000になる問題の場合、Rakudo2018.06はまだperl5.26.2よりも少し遅いです:

$ time perl -e 'use List::Util 'sum'; print sum(1 .. 100000), "\n";' >/dev/null

real    0m0.023s
user    0m0.015s
sys     0m0.008s

$ time perl6 -e 'say [+] 1 .. 100000;' >/dev/null

real    0m0.089s
user    0m0.107s
sys     0m0.022s

しかし、コードを10,000回実行して起動コストを償却すると、別の話がわかります。

$ time perl -e 'use List::Util 'sum'; for (1 .. 10000) { print sum(1 .. 100000), "\n"; }' > /dev/null

real    0m16.320s
user    0m16.317s
sys     0m0.004s

$ time perl6 -e 'for 1 .. 10000 { say [+] 1 .. 100000; }' >/dev/null

real    0m0.214s
user    0m0.245s
sys     0m0.021s

perl6は、起動とコンパイルでperl5よりも数百ミリ秒多く使用しますが、実際の合計を約70倍速く行う方法を理解します。

于 2010-06-29T04:11:09.403 に答える
6

それは確かにすべてがオブジェクトであるからではありません。それは他の多くの言語(Rubyなど)にも当てはまるからです。Perl6がPerl5やRubyのような他の言語よりも大幅に遅くなければならない理由はありませんが、実際のところ、RakudoはperlやCRubyほど成熟していません。速度の最適化はまだあまり行われていません。

于 2010-06-28T20:34:50.790 に答える
6

これで、テストケースがほぼ瞬時に返されるO(1)アルゴリズムに最適化され、週にいくつかの最適化が行われているように見えることを考慮してください。
私は全体的にかなりのパフォーマンスの向上を期待しています。

$ perl6 -e 'say [+] 1..10**1000; say now - INIT now'
5000000000000000000000000000000000000000000000 ...
0.007447

範囲に特別なケースがなかったとしても、それでも以前よりもかなり高速です。
これで、5分の1秒未満でテスト計算が実行されます。

$ perl6 -e 'say [+] (1..100000).list; say now - INIT now'
5000050000
0.13052975
于 2015-11-18T19:51:17.673 に答える
4

私はこれらを2008年12月にFefeの言語コンテストに提出しました。これwp.pugs.plはPerl5の例の直訳であり、wp.rakudo.plはるかに6つです。2つのプログラムは、仕様の異なるサブセットを実装しているため、2つのプログラムがあります。その間、ビルド情報は古くなっています。情報源:

#!/usr/bin/env pugs
# Pugs: <http://pugs.blogs.com/> <http://pugscode.org/>
# prerequisite: ghc-6.8.x, not 6.10.x
# svn co http://svn.pugscode.org/pugs/
# perl Makefile.PL
# make
# if build stops because of haskeline, do:
#   $HOME/.cabal/bin/cabal update ; $HOME/.cabal/bin/cabal install haskeline

# learn more: <http://jnthn.net/papers/2008-tcpw-perl64danoob-slides.pdf>

my %words;

for =<> {
    for .split {
        %words{$_}++
    }
}

for (sort { %words{$^b} <=> %words{$^a} }, %words.keys) {
    say "$_ %words{$_}"
}

#!/usr/bin/env perl6
# Rakudo: <http://rakudo.org/> <http://www.parrot.org/download>
# svn co http://svn.perl.org/parrot/trunk parrot
# perl Configure.pl
# make perl6

# Solution contributed by Frank W. & Moritz Lenz
# <http://use.perl.org/~fw/journal/38055>
# learn more: <http://jnthn.net/papers/2008-tcpw-perl64danoob-slides.pdf>

my %words;

$*IN.lines.split(/\s+/).map: { %words{$_}++ };

for %words.pairs.sort: { $^b.value <=> $^a.value } -> $pair {
    say $pair
}

これらは2008年の結果です。

$ time ./wp.pugs.pl < /usr/src/linux/COPYING > foo

real    0m2.529s
user    0m2.464s
sys     0m0.064s

$ time ./wp.rakudo.pl < /usr/src/linux/COPYING > foo

real    0m32.544s
user    0m1.920s
sys     0m0.248s

今日:

$ time ./wp.pugs.pl < /usr/src/linux/COPYING > foo

real    0m5.105s
user    0m4.898s
sys     0m0.096s

$ time ./wp.rakudo.pl < /usr/src/linux/COPYING > foo
Divide by zero
current instr.: '' pc -1 ((unknown file):-1)
Segmentation fault

real    0m3.236s
user    0m0.447s
sys     0m0.080s

最近の追加: Rakudoでスクリプトを実行しようとすると、「ゼロ除算」エラーが発生するのはなぜですか?でクラッシュが処理されました。。Rakudoプログラムは非効率的です。以下のコメントhttp://justrakudoit.wordpress.com/2010/06/30/rakudo-and-speed/を参照してください。

于 2010-06-28T21:51:00.250 に答える