Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 为什么函数调用在clojure中会减慢速度?_Performance_Clojure - Fatal编程技术网

Performance 为什么函数调用在clojure中会减慢速度?

Performance 为什么函数调用在clojure中会减慢速度?,performance,clojure,Performance,Clojure,我一直在玩弄(和前传)代码。很不幸,内联微分方程(f)是提高性能的步骤之一。我能想到的最干净/最快的方法是: ; 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 [e

我一直在玩弄(和前传)代码。很不幸,内联微分方程(
f
)是提高性能的步骤之一。我能想到的最干净/最快的方法是:

; 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
我的解决方案中的类型暗示有相当大的帮助(在
f
solveit
上都没有类型暗示,但是它仍然比内联版本慢近2倍。最终,这一表现仍然相当不错,但这一打击是不幸的

为什么会有这样的性能冲击呢?有办法绕过它吗?有没有计划找到改进的方法?正如John在最初的帖子中指出的,函数调用在函数语言中效率低下似乎很有趣/不幸


注意:我正在运行Clojure 1.5,并且在project.clj文件中有
:jvm opts^:replace[]
,这样我就可以使用lein exec/run,而不会让事情变慢(如果你不这样做,我发现…)

在JIT编译器中进行基准测试是很棘手的;你真的必须考虑一段热身期,但是你也不能只是在一个循环中运行它,因为它可能会被证明是一个无操作的优化过程。在Clojure中,通常的解决方案是使用Hugo Duncan的


对两个版本的
solveit
运行
(solveit 0.0 1.0(/1.0 1000000)1000000)
的Criteriam基准测试会在我的机器上产生几乎完全相同的计时(
mysolveit
~3.44毫秒,
更快的solveit
~3.45毫秒)。这是在64位JVM中运行的,
-XX:+useConMarkSweepGC
,使用Criterium 0.4.2(
Criterium.core/bench
)。大概热点只是内联线
f
。在任何情况下,都不会对性能造成任何影响。

在JIT编译器存在的情况下进行基准测试是很棘手的;你真的必须考虑一段热身期,但是你也不能只是在一个循环中运行它,因为它可能会被证明是一个无操作的优化过程。在Clojure中,通常的解决方案是使用Hugo Duncan的


对两个版本的
solveit
运行
(solveit 0.0 1.0(/1.0 1000000)1000000)
的Criteriam基准测试会在我的机器上产生几乎完全相同的计时(
mysolveit
~3.44毫秒,
更快的solveit
~3.45毫秒)。这是在64位JVM中运行的,
-XX:+useConMarkSweepGC
,使用Criterium 0.4.2(
Criterium.core/bench
)。大概热点只是内联线
f
。在任何情况下,性能都不会受到任何影响。

哇。。。非常感谢你。我曾读到clojure中的性能评测是JVM的一个小问题,但我认为差异很小。我刚刚分析了一个函数,它使用时间与工作台的差异约为20倍!哇!非常感谢你。我曾读到clojure中的性能评测是JVM的一个小问题,但我认为差异很小。我刚刚分析了一个函数,它使用时间与工作台的差异约为20倍!