0

Lua コードのマイクロベンチマークをいくつか試してみましたが、信じられないほど厄介な問題に遭遇しました。一貫した結果が得られないようです。

例: 以下は単純なフィボナッチ関数の時間を測定することになっている単純な Lua プログラムです。

function pfibs(n)
  if n ~= math.floor(n) then return 0
  elseif n < 0 then return pfibs(n + 2) - pfibs(n + 1)
  elseif n < 2 then return n
  else return pfibs(n - 1) + pfibs(n - 2)
  end
end
t = os.clock()
pfibs(30)
t = os.clock() - t
print("time: "..t)

続けて数回実行しようとすると、次のようなことが起こります。

$ lua fib.lua
time: 1.265
$ lua fib.lua
time: 1.281
$ lua fib.lua
time: 1.343
$ lua fib.lua
time: 1.437
$ lua fib.lua
time: 1.562
$ lua fib.lua
time: 1.578
$ lua fib.lua
time: 1.64
$ lua fib.lua
time: 1.703
$ lua fib.lua
time: 1.75
$ lua fib.lua
time: 1.797
$ lua fib.lua
time: 1.796
$ lua fib.lua
time: 1.812
$ lua fib.lua
time: 1.89

(これは単なる例であり、簡潔にするために省略されていますが、私が見ている減速曲線の種類を表しています)

約 1.1 秒から始まる時間は、2 秒をはるかに超えて終了します。私がやっているのは、ここに座って上とエンターを繰り返し押していることだけです。Lua クロックを使用する代わりに の呼び出しでテストをラップしtimeたり、数秒かかるように数回ループさせたりすると、同じようなことが起こります。比例して遅くなるようです。しばらく放置すると、時間が戻ってしまうことがあります。そうでない場合もあります(おそらく、どれくらい放置するかわからないためです)。

これは Windows+MSYS 上にあります。Ubuntu (同じマシン) でこれを試すと、別のパターンにつながりますが、依然として一貫性がなく、使用できない結果が得られます (たとえば、テストには 2 秒、次に 3.5 秒、次に 4 秒、次に 2.5 秒かかります...)。タスク マネージャー/トップは、どちらの場合も、バックグラウンドで CPU を消費していないことを示しています。CPU 速度の切り替えは無効です。

私は何を間違っていますか?私のマシンは古いですが、それほど壊れているわけではありませんマシンのせいで、すべてのプログラムが毎秒非常に遅くなった場合、使用できないことに気付くでしょう...)。


私が実際にやろうとしていること:

私がやりたかったのは、バニラの Lua から始めて、変更がインタープリターのパフォーマンスにどのような影響を与えるかを微調整することによって、インタープリターの実装について学ぶことでした。ご覧のとおり、「コントロールの確立」はまだ完了していないため、実際にはまだ何も行っていません。ベンチマークの分散が上記のように高いため、行った変更はすべて完全に失われます。ノイズ。私が Lua を選んだ理由は、現実世界のプログラムでありながら、小さくて読みやすく、変更しやすいからです。これを行うためのより良い基本インタープリター、またはインタープリターのパフォーマンスをベンチマークするための確立された最良の方法がある場合は、回答にそれに関する提案を自由に追加してください。


編集:C従来のCタイミングユーティリティを使用するCプログラムでも同じことが発生しているため、タグを追加します。例:

#include <time.h>
#include <stdio.h>

int fib(int n) {
    return n > 2 ? fib(n - 1) + fib(n - 2) : n;
}

int main(void) {
    clock_t t1, t2; const int ITNS = 30;
    for (int i = 0; i < ITNS; i ++) {
        t1 = clock();
        fib(38);
        t2 = clock();
        printf("time: %d\n", (int)((t2 - t1) / (CLOCKS_PER_SEC / 1000)));
    }
    return 0;
}

...次を出力します。

time: 687
time: 688
time: 687
time: 688
time: 671
time: 688
time: 687
time: 688
time: 672
time: 687
time: 688
time: 687
time: 672
time: 688
time: 687
time: 688
time: 672
time: 796
time: 766
time: 719
time: 969
time: 1000
time: 1015
time: 1000
time: 1016
time: 1000
time: 1000
time: 1015
time: 1000
time: 1000

これは、効果が個別の実行に限定されないことを示しています。これは、マシンまたは OS に問題があることを意味していると思います。

4

3 に答える 3

3

あなたのプログラムは、Xeon E7-4850 を搭載した私のマシンで非常に安定しているようです

time: 0.97
time: 0.98  
time: 1
time: 0.98
time: 1.01
time: 1
time: 0.98
time: 0.98
time: 1.02
time: 0.98

ただし、ベンチマークを実行するときに、 cpu-frequency-scalingまたはターボ ブーストのようなものが有効になっているかどうかを確認することをお勧めします。以前にも同様の問題に遭遇しましたが、cpu-frequency-scaling をオフにすると、ベンチマークが安定しました。Linux では、cpufrequtils を使用してオフにすることができます。

さらに、AMD マシンを使用している場合は、Intel マシンに切り替えることをお勧めします。これは、CPU 周波数が固定されていても、Opteron 8431 では lua プログラムのパフォーマンスがまだ安定していないためです。したがって、この問題はハードウェア プラットフォームに依存している可能性がありますが、 Lua インタープリター自体。

編集:

周波数が安定していることを確認するために、各反復後に現在の CPU 周波数を (/proc/cpuinfo または /dev/cpu/#/msr から) 読み取って出力する方がよいと思います。

C プログラムでの結果には、明確な安定段階が 2 つあります。run19 と CPU 周波数がスケールダウンした後に何かが起こったようです。

ここに画像の説明を入力

于 2013-05-27T03:37:38.700 に答える