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…
)更改,上面的代码不再有效。)