Clojure连续函数调用和记忆
我阅读了Chas Emerick、Brian Carper和Christophe Grand的《Clojure编程》一书 在关于记忆化的部分,我注意到在不使用记忆化的情况下,第二次(和其他)函数调用所花费的时间显著减少 当然,使用回忆录在数量级上减少了时间,但我感兴趣的是,如果Clojure在内部执行类似回忆录的操作 代码如下:Clojure连续函数调用和记忆,clojure,memoization,Clojure,Memoization,我阅读了Chas Emerick、Brian Carper和Christophe Grand的《Clojure编程》一书 在关于记忆化的部分,我注意到在不使用记忆化的情况下,第二次(和其他)函数调用所花费的时间显著减少 当然,使用回忆录在数量级上减少了时间,但我感兴趣的是,如果Clojure在内部执行类似回忆录的操作 代码如下: (defn prime? [n] (cond (== 1 n) false (== 2 n) true (even? n) false
(defn prime?
[n]
(cond
(== 1 n) false
(== 2 n) true
(even? n) false
:else (->> (range 3 (inc (Math/sqrt n)) 2)
(filter #(zero? (rem n %)))
empty?)))
(def n 123)
(time (prime? n))
(time (prime? n))
(let [m-prime? (memoize prime?)]
(time (m-prime? n))
(time (m-prime? n)))
以及输出:
"Elapsed time: 0.235977 msecs"
"Elapsed time: 0.054549 msecs"
"Elapsed time: 0.045127 msecs"
"Elapsed time: 0.003814 msecs"
那么,为什么第二次调用的速度几乎是第一次调用的5倍呢?第一次调用Clojure函数时,速度会慢一些。我认为Clojure会延迟一些内部链接或设置,直到调用函数为止 可能是准时制,但我不这么认为。这将在定义函数时生效
回忆录不是灵丹妙药。如果您调用的不是真的很慢,那么它实际上可能比只执行原始代码要慢。例如,当我编写锦标赛配对算法时,我对一个函数进行了记忆实验,该函数被反复调用并总是返回相同的结果,这大大降低了匹配算法的速度。使用Memorization时的速度是不使用Memorization时的2-3倍。第一次调用Clojure函数时,速度要慢。我认为Clojure会延迟一些内部链接或设置,直到调用函数为止 可能是准时制,但我不这么认为。这将在定义函数时生效
回忆录不是灵丹妙药。如果您调用的不是真的很慢,那么它实际上可能比只执行原始代码要慢。例如,当我编写锦标赛配对算法时,我对一个函数进行了记忆实验,该函数被反复调用并总是返回相同的结果,这大大降低了匹配算法的速度。有记忆时的速度是没有记忆时的2-3倍。内部每个clojure函数都由jvm类表示-第一次调用较长,因为类加载器必须加载类 正如前面的回答所说——这不是确定的JIT,因为大多数优化的JIT都有一定的阈值——可以使用XX:CompileThreshold进行更改——默认值设置为10000——这就是jvm在基准测试之前必须预热的原因之一
记住,记忆只是一种缓存。而且函数必须是“纯”的才能正确工作-编译器很难猜测哪一个函数可能会被自动记忆。内部每个clojure函数都由jvm类表示-第一次调用较长,因为类加载器必须加载类 正如前面的回答所说——这不是确定的JIT,因为大多数优化的JIT都有一定的阈值——可以使用XX:CompileThreshold进行更改——默认值设置为10000——这就是jvm在基准测试之前必须预热的原因之一
记住,记忆只是一种缓存。而且函数必须是“纯”的才能正确运行-编译器很难猜测哪一个函数可能会被自动记忆。我想你错过了JIT。我认为第一个性能提升是JIT的工作。好吧,也许有人可以建议你好好阅读一下Clojure是如何编译成Java字节码的?我想你错过了JIT。我认为第一次提高性能是JIT的工作。好吧,也许有人可以建议大家好好阅读一下Clojure是如何编译成Java字节码的?这个类是在读取函数时加载的,而不是在第一次调用它时加载的。使用
-verbose:class
选项运行repl,您可以看到。该类是在读取函数时加载的,而不是在第一次调用该函数时加载的。使用-verbose:class
选项运行repl,您可以看到。耶,我曾经分析过一个不适当的备忘录,它花费了大量时间对参数列表进行向量化、哈希和缓存搜索,甚至超过了一个简单的计算。耶,我曾经分析过一个不适当的备忘录,它花费了大量时间进行向量化、哈希,和缓存搜索甚至超过裸计算的arg列表。