Clojure를 처음 사용했습니다.Clojure : 대형 게으름 수집을 줄이면 메모리가 늘어납니다.
(defn generator [seed factor]
(drop 1 (reductions
(fn [acc _] (mod (* acc factor) 2147483647))
seed
; using dummy infinite seq to keep the reductions going
(repeat 1))))
순서대로 각 숫자는 이전 계산에 따라 달라집니다 : 나는 숫자의 무한 게으른 시퀀스를 만드는 다음 코드를 가지고있다. 모든 중간 결과가 필요하기 때문에 reductions
을 사용하고 있습니다.
나는 다음과 같이 두 개의 발전기를 인스턴스화 :
(def gen-a (generator 59 16807))
(def gen-b (generator 393 48271))
나는 다음 큰 N에 대해,이 시퀀스의 n
연속적인 결과를 비교, 그들은 동일한 횟수를 반환합니다.
는 처음 엔 내가 좋아하는 일을했다 : 그것은 너무 오래 복용하고 있었고, 난이 약 4GB로 프로그램의 메모리 사용 스파이크를 보았다
(defn run []
(->> (interleave gen-a gen-b)
(partition 2)
(take 40000000)
(filter #(apply = %))
(count)))
. 아직도
(defn run-2 []
(reduce
(fn [acc [a b]]
(if (= a b)
(inc acc)
acc))
0
(take 40000000 (partition 2 (interleave gen-a gen-b)))))
: 일부 println
들과 함께 나는 약 1000 만 반복 후 정말 느린있어 것을보고, 그래서 어쩌면 count
메모리에 전체 시퀀스를 저장하기 위해 필요하다고 생각하고 있었다, 그래서 나는 사용 reduce
그것을 변경 그것은 많은 메모리를 할당하고 수백만의 처음 몇 후 상당히 느려졌어요. 나는 그것이 메모리에 전체 게으른 시퀀스를 저장하는 것하지만 난 이유를 잘 모르겠어요 것을 확신 해요, 그래서 수동으로 머리를 던져하려고 :
(defn run-3 []
(loop [xs (take 40000000 (partition 2 (interleave gen-a gen-b)))
total 0]
(cond
(empty? xs) total
(apply = (first xs)) (recur (rest xs) (inc total))
:else (recur (rest xs) total))))
다시 동일한 결과를. 이것은 내가 내 xs
시퀀스를 만드는 데 사용하고있는 모든 함수가 게으르다는 것을 읽었 기 때문에 나에게 당황 스럽습니다. 그리고 현재의 아이템만을 사용하고 있기 때문에 상수 메모리를 사용할 것으로 기대하고 있습니다.
파이썬 배경에서 오는 것은 기본적으로 Python Generators을 에뮬레이트하려고합니다. 아마도 뭔가 명백한 것이 빠졌을 것입니다. 감사!
감사합니다. 나는'generator '가 2 -> 무한대의 게으른 시퀀스를 리턴했다고 생각했다. 편집 : 신경 쓰지 마라, 나는'def'가 서열의 머리를 잡고 있다는 것을 몰랐다. – orangeblock
@orangeblock, 문제는 전역 (수집 할 수없는) var에서 지연 목록의 헤드를 참조했다는 것입니다. 편집 : 예, 그게 무슨 뜻이야 :-) –