Clojure:超出gc开销限制,延迟计算,pi序列
下一个代码:Clojure:超出gc开销限制,延迟计算,pi序列,clojure,garbage-collection,lisp,jvm,lazy-evaluation,Clojure,Garbage Collection,Lisp,Jvm,Lazy Evaluation,下一个代码: (ns clojure101.series) (defn avg [[x y]] (/ (+ x y) 2)) (defn avg-damp [seq] (map avg (partition 2 seq))) (defn avg-damp-n [n] (apply comp (repeat n avg-damp))) (defn sums [seq] (reductions + seq)) (defn Gregory-Leibniz-n [n
(ns clojure101.series)
(defn avg [[x y]] (/ (+ x y) 2))
(defn avg-damp
[seq]
(map avg (partition 2 seq)))
(defn avg-damp-n
[n]
(apply comp (repeat n avg-damp)))
(defn sums
[seq]
(reductions + seq))
(defn Gregory-Leibniz-n
[n]
(/ (Math/pow -1 n) (inc (* 2 n))))
(def Gregory-Leibniz-pi
(map #(* 4 (Gregory-Leibniz-n %)) (iterate inc 0)))
(println (first ((avg-damp-n 10) (sums Gregory-Leibniz-pi))))
我得到n=20的“超出gc开销限制”错误。
我怎样才能解决这个问题
更新:我更改了avg-damp-n功能
(defn avg-damp-n
[n seq]
(if (= n 0) seq
(recur (dec n) (avg-damp seq))))
现在我可以得到n=20的数字
(time
(let [n 20]
(println n (first (avg-damp-n n (sums Gregory-Leibniz-pi))))))
20 3.141593197943081
"Elapsed time: 3705.821263 msecs"
更新2
我修复了一些错误,现在工作正常:
(ns clojure101.series)
(defn avg [[x y]] (/ (+ x y) 2))
(defn avg-damp
[seq]
(map avg (partition 2 1 seq)))
(defn avg-damp-n
[n]
(apply comp (repeat n avg-damp)))
(defn sums
[seq]
(reductions + seq))
(defn Gregory-Leibniz-n
[n]
(/ (int (Math/pow -1 n)) (inc (* 2 n))))
(def Gregory-Leibniz-pi
(map #(* 4 (Gregory-Leibniz-n %)) (range)))
; π = 3.14159265358979323846264338327950288419716939937510...
(time
(let [n 100]
(println n (double (first ((avg-damp-n n) (sums Gregory-Leibniz-pi)))))))
输出:
100 3.141592653589793
"Elapsed time: 239.253227 msecs"
首先,尝试一个愚蠢的有效解决方案:增加java堆空间
;in your clojure launch script
java -Xmx2G ...other options...
程序中有一部分在分区中不是惰性的,但更改它使其惰性(通过取消对count
的调用)仍然会给我一个默认堆大小的OutOfMemoryError。将avg-damp-n的聪明度替换为减少计算的平均值
(take (integer-exponent 2 20) seq)
仍然会导致OutOfMemory错误。看看其他所有东西的来源,我没有看到任何其他东西看起来像是在消耗堆。嗯。。。这对我有用。在Windows XP上使用Clojure 1.2进行测试
user=> (defn avg
[xs & {:keys [n] :or {n 2}}]
(/ (reduce + xs) n))
#'user/avg
user=> (defn Gregory-Leibniz-n
[n]
(/ (Math/pow -1 n) (inc (+ n n))))
#'user/Gregory-Leibniz-n
user=> (->> (range)
(map #(* 4 (Gregory-Leibniz-n %)))
(reductions +)
(partition 20)
(map #(avg % :n 20))
first
println)
3.1689144018345354
这是正确的答案吗?我不知道这个Gregory Leibniz递归,所以我
我不确定这是否正确
我注意到一点:你太聪明了。也就是你的平均阻尼n
在惰性序列上堆叠惰性序列。由于可以插入任意值的n
,
您迟早会遇到中大型n
的堆栈溢出
这种情况。如果有一个直接的解决方案,你应该更喜欢
信息技术不过,我不确定这是不是你真正的问题。(正如我所说:相当于
这对我毫无帮助。)正如科塔拉克所说,在懒惰的序列上堆叠懒惰的序列似乎效率很低 关于GC。我可以在慢原子系统上重现这个问题。另见: 对我来说,Gregory Leibniz PI计算直接转换为Clojure代码,该代码只使用一个惰性序列:
(defn Gregory-Leibniz-pi [n]
(->> (range n)
(map (fn [n] (/ (Math/pow -1 n) (inc (* 2 n)))))
(apply +)
(* 4)))
考虑到这应该解决Pi问题,我认为这不是正确的答案@A你说得有道理(小编辑:但它可能仍然是OP期望的数字…(当然,对于
(分区2 1…
)更改,上面的代码不再有效。)