2010-10-17 10 views
5

:Clojure: aşılması gc üst sınırı, yavaş değerlendirme, pi Dizi, bir sonraki kodu için

(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)))) 

Elde n = 20 hatası "gc üst sınırın aşılması". Bunu nasıl düzeltebilirim?

GÜNCELLEME: Ben ort-nemli-n işlevini değiştirdi

(defn avg-damp-n 
    [n seq] 
    (if (= n 0) seq 
     (recur (dec n) (avg-damp seq)))) 

şimdi 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" 

GÜNCELLEME 2 için sayı bazı hata sabit ve şimdi alabilirsiniz gayet güzel çalışıyor:

(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))))))) 

ÇIKIŞ: Herşeyden

100 3.141592653589793 
"Elapsed time: 239.253227 msecs" 

cevap

2

Hmm ... Bu benim için çalışıyor. Windows XP'de Clojure 1.2 ile test edilmiştir.

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 

Doğru cevap bu mu? Bu Gregory-Leibniz tekrarını bilmiyorum, bu yüzden bu doğru olup olmadığından emin değilim . Not aldığım bir nokta: Çok zeki olmaya çalışıyorsunuz. Yani avg-nemli-n yığınları tembel sekmede tempolu seq. Eğer n, keyfi değerleri eklentisi beri er ya da geç de yığın Böyle bir senaryoda büyük n için taşıyor yaşayacaksınız. Düz ileri bir çözüm varsa, 'u tercih etmelisiniz. Bunun gerçek problemin olduğuna emin değilim. (Dediğim gibi:. Doğrusu unhelpfully benim için çalışır)

+1

, I don' Bu doğru cevap bu düşünün.;) –

+0

@ataggert Orada işaret ettiniz. ;) (Küçük düzenleme: Ama yine de OP'nin beklediği sayı olabilir ...) (Ve elbette ki (bölüm 2 1 ...) 'ile değiştirmek artık işe yaramıyor.) – kotarak

2

Öncelikle çalışır aptal çözümü deneyin: java yığın alanını arttırır.

;in your clojure launch script 
java -Xmx2G ...other options... 

Orada bölümünde tembel değildir programının bir parçasıdır, ancak (count bir çağrı kurtularak) tembel böylece hala bana varsayılan yığın boyutu için bir OutOfMemoryError verir değiştirmeyi.

(take (integer-exponent 2 20) seq) 

bir azaltmak hesaplanan ortalama ort-nemli-n akıllılık değiştirilmesi yine de bir OutOfMemoryError neden olur. Diğer her şeyin kaynağına baktığımda, yığın tüketmesi gerektiği gibi görünen başka hiçbir şey görmüyorum.

3

olarak ifade tembel seq yılların üzerinde tembel seq yılların yığma GC bakımından oldukça verimsiz görünmektedir kotarak. Bu sorunu yavaş bir atom sistemi üzerinde yeniden üretebilirim. Ayrıca bakınız: Benim için Gregory-Leibniz PI caclulation doğrudan tek tembel dizisini kullanan bu Clojure Kanunu dönüşür

Error java.lang.OutOfMemoryError: GC overhead limit exceeded

: Pi çözümlemek gerekiyordu Bu göz önüne alındığında

(defn Gregory-Leibniz-pi [n] 
    (->> (range n) 
     (map (fn [n] (/ (Math/pow -1 n) (inc (* 2 n))))) 
     (apply +) 
     (* 4))) 
İlgili konular