4

私は、乗算関数のばかげた非末尾再帰バージョンを作成し、それが適切な TCO のものとどのように比較されるかを確認しようと考えました。ただし、REPL (java -cp <classpath> clojure.main構成済みの Emacs を使用していますinferior-lisp) とコマンドラインからプログラムを呼び出すときの両方で、何らかの最適化/メモ化が行われているようです。実際、結果は REPL の方がはるかに顕著です。

(defn mult-silly [n m]
  (if (> n 0)
    (+ m (mult-silly (dec n) m))
    0))

(dotimes [_ 5]
  (println (time (mult-silly 5000 4)))) 

上記はREPLで生成されます:

user=> #'user/mult-silly
user=> "経過時間: 10.697919 ミリ秒"
20000
"経過時間: 3.069106 ミリ秒"
20000
"経過時間: 2.301474 ミリ秒"
20000
"経過時間: 1.285696 ミリ秒"
20000
"経過時間: 415855ミリ秒"
20000

なぜ私はこれを見るのですか?

4

1 に答える 1

4

@MariusDanila がコメントで指摘したように、これは JIT が開始されたためです。

これを確認するには、オプションを指定して java を実行し-Xintます。これにより、解釈のみのモードで実行されるため、ネイティブ コードには何もコンパイルされません (そのネイティブ コードに対して最適化は確実に行われません)。

だから、これが私がJavaを正常に実行しているものです:

"Elapsed time: 4.175 msecs"
20000
"Elapsed time: 2.548 msecs"
20000
"Elapsed time: 7.746 msecs"
20000
"Elapsed time: 1.919 msecs"
20000
"Elapsed time: 1.72 msecs"
20000

ここでは、3 回目の実行で時間が実際に増加していることに注意してください。これは、コンパイルが同時に行われているためだと思います。一方、-Xint:

"Elapsed time: 31.463 msecs"
20000
"Elapsed time: 30.844 msecs"
20000
"Elapsed time: 30.643 msecs"
20000
"Elapsed time: 29.972 msecs"
20000
"Elapsed time: 30.617 msecs"
20000

2 番目のケースでわかるように、高速化はありません。

これが、マイクロベンチマークのルール 1が、測定値からウォームアップ時間を常に除外することである理由です。

于 2013-09-09T15:37:58.030 に答える