1

Is Clojure is Still Fast?で遊んでいます。(そして前編Clojure is Fast ) コード。f微分方程式 ( ) をインライン化することが、パフォーマンスを改善するための手段の 1 つであることは残念なことに思えました。これを行わずに思いついた最もクリーン/最速のものは次のとおりです。

; As in the referenced posts, for giving a rough measure of cycles/iteration (I know this is a very rough
; estimate...)
(def cpuspeed 3.6) ;; My computer runs at 3.6 GHz
(defmacro cyclesperit [expr its]
  `(let [start# (. System (nanoTime))
         ret# ( ~@expr (/ 1.0 ~its) ~its )
         finish# (. System (nanoTime))]
     (println (int (/ (* cpuspeed (- finish# start#)) ~its)))))

;; My solution
(defn f [^double t ^double y] (- t y))
(defn mysolveit [^double t0 ^double y0 ^double h ^long its]
  (if (> its 0)
    (let [t1 (+ t0 h)
          y1 (+ y0 (* h (f t0 y0)))]
      (recur t1 y1 h (dec its)))
    [t0 y0 h its]))
; => 50-55 cycles/it

; The fastest solution presented by the author (John Aspden) is
(defn faster-solveit [^double t0 ^double y0 ^double h ^long its]
  (if (> its 0)
    (let [t1 (+ t0 h)
          y1 (+ y0 (* h (- t0 y0)))]
      (recur t1 y1 h (dec its)))
    [t0 y0 h its]))
; => 25-30 cycles/it

私のソリューションの型ヒントはかなり役に立ちます (224 サイクル/fまたはの型ヒントなしsolveit) が、それでもインライン バージョンよりも 2 倍近く遅くなります。最終的に、このパフォーマンスはまだかなりまともですが、このヒットは残念です.

なぜこのようなパフォーマンスヒットがあるのですか? それを回避する方法はありますか?これを改善する方法を見つける計画はありますか? 元の投稿でジョンが指摘したように、関数型言語で関数呼び出しが非効率的であることは、おかしな/残念なことに思えます。

注: 私は Clojure 1.5 を実行して:jvm-opts ^:replace []おり、project.clj ファイルを持っているので、速度を落とさずに lein exec/run を使用できます (これを行わないと、速度が低下することがわかりました...)

4

1 に答える 1