2010-10-17 29 views
5

Đối với các mã tiếp theo:Clojure: giới hạn gc overhead vượt quá, đánh giá lười biếng, pi chuỗi

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

tôi nhận được "giới hạn gc overhead vượt quá" lỗi cho n = 20. Làm cách nào để khắc phục sự cố này?

CẬP NHẬT: Tôi đã thay đổi chức năng trung bình-ẩm-n

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

bây giờ tôi có thể nhận được số với 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" 

UPDATE 2 tôi cố định một số lỗi và bây giờ nó hoạt động tốt:

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

OUTPUT:

100 3.141592653589793 
"Elapsed time: 239.253227 msecs" 

Trả lời

2

Hmm ... Điều này phù hợp với tôi. Thử nghiệm với Clojure 1.2 trên Windows XP.

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 

Đó có phải là câu trả lời đúng không? Tôi không biết đệ trình Gregory-Leibniz này, vì vậy tôi là không chắc liệu điều này có đúng không.

Một điểm tôi lưu ý: Bạn đang cố gắng quá thông minh. Cụ thể là của bạn avg-ẩm-n ngăn xếp lười biếng seq trên lười biếng seq. Vì bạn có thể plugin các giá trị tùy ý của n, , bạn sẽ sớm hay muộn cũng gặp phải tình trạng tràn ngăn xếp cho số lớn n trong trường hợp như vậy. Nếu có giải pháp thẳng về phía trước, bạn nên chọn . Tôi không chắc chắn rằng đây là vấn đề thực tế của bạn, mặc dù. (Như tôi đã nói: thay vì một cách vô ích, nó hoạt động cho tôi.)

+1

Xét này có nghĩa vụ phải giải quyết để Pi, tôi don' Tôi nghĩ đó là câu trả lời đúng.;) –

+0

@ataggert Bạn có điểm ở đó. ;) (Chỉnh sửa nhỏ: Nhưng nó vẫn có thể là số OP mong đợi ...) (Và tất nhiên với '(phân vùng 2 1 ...)' thay đổi ở trên không hoạt động nữa.) – kotarak

2

Trước hết, hãy thử các giải pháp ngu ngốc mà làm việc: tiết kiệm dung lượng java đống của bạn.

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

Có một phần của chương trình mà không phải là lười biếng trong phân vùng, nhưng thay đổi nó để nó là lười biếng (bằng cách loại bỏ một cuộc gọi đến count) vẫn mang lại cho tôi một OutOfMemoryError cho kích thước heap mặc định. Thay thế độ thông minh của avg-damp-n với mức trung bình được tính toán giảm trên

(take (integer-exponent 2 20) seq) 

vẫn gây ra lỗi OutOfMemoryError. Nhìn vào nguồn của mọi thứ khác, tôi không thấy bất kỳ thứ gì khác trông giống như họ nên tiêu thụ đống.

3

Như kotarak đã nói, việc xếp chồng của những người lười biếng lười biếng có vẻ khá kém hiệu quả liên quan đến GC. Tôi có thể tái tạo vấn đề này trên một hệ thống nguyên tử chậm. Xem thêm:

Error java.lang.OutOfMemoryError: GC overhead limit exceeded

Đối với tôi Gregory-Leibniz PI caclulation trực tiếp biến thành Mã Clojure này mà chỉ sử dụng một chuỗi lười biếng:

(defn Gregory-Leibniz-pi [n] 
    (->> (range n) 
     (map (fn [n] (/ (Math/pow -1 n) (inc (* 2 n))))) 
     (apply +) 
     (* 4))) 
Các vấn đề liên quan