Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.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
Clojure连续函数调用和记忆_Clojure_Memoization - Fatal编程技术网

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

我阅读了Chas Emerick、Brian Carper和Christophe Grand的《Clojure编程》一书

在关于记忆化的部分,我注意到在不使用记忆化的情况下,第二次(和其他)函数调用所花费的时间显著减少

当然,使用回忆录在数量级上减少了时间,但我感兴趣的是,如果Clojure在内部执行类似回忆录的操作

代码如下:

(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列表。