2014-09-16 5 views
2

다음 코드는 기본적으로 (function (range n))과 같은 것을 병렬로 실행하도록합니다.미래는 어떻게 될까요?

(experiment-with-agents 10000 10 #(filter prime? %)) 

예를 들어, 10 개의 에이전트로 0과 10000 사이의 소수를 찾습니다.

(experiment-with-futures 10000 10 #(filter prime? %)) 

선물과 동일합니다.

이제 문제는 선물이있는 솔루션이 더 많은 선물로 더 빨리 실행되지 않는다는 것입니다. 예 :

; Futures 
(time (experiment-with-futures 10000 1 #(filter prime? %))) 
"Elapsed time: 33417.524634 msecs" 

(time (experiment-with-futures 10000 10 #(filter prime? %))) 
"Elapsed time: 33891.495702 msecs" 

; Agents 
(time (experiment-with-agents 10000 1 #(filter prime? %))) 
"Elapsed time: 33048.80492 msecs" 

(time (experiment-with-agents 10000 10 #(filter prime? %))) 
"Elapsed time: 9211.864133 msecs" 

왜? 내가 뭔가 잘못 했습니까 (아마도 Clojure에 새로 왔고 그냥 물건으로 놀아 라 ^^)? 왜냐하면 나는 미래가 실제로 그 시나리오에서 선호된다고 생각했기 때문입니다.

자료 :

(defn setup-agents 
    [coll-size num-agents] 
    (let [step (/ coll-size num-agents) 
     parts (partition step (range coll-size)) 
     agents (for [_ (range num-agents)] (agent [])) 
     vect (map #(into [] [%1 %2]) agents parts)] 
    (vec vect))) 

(defn start-agents 
    [coll f] 
    (for [[agent part] coll] (send agent into (f part)))) 

(defn results 
    [agents] 
    (apply await agents) 
    (vec (flatten (map deref agents)))) 

(defn experiment-with-agents 
    [coll-size num-agents f] 
    (-> (setup-agents coll-size num-agents) 
     (start-agents f) 
     (results))) 

(defn experiment-with-futures 
    [coll-size num-futures f] 
    (let [step (/ coll-size num-futures) 
     parts (partition step (range coll-size)) 
     futures (for [index (range num-futures)] (future (f (nth parts index))))] 
    (vec (flatten (map deref futures))))) 
+2

'(concat ... 적용')은'항상'(flatten ...)'과'(flatten (map ...))'보다 대체적으로' (mapcat ...)' – noisesmith

+1

'(map # ([[% 1 % 2]) 부분)'은'(map vector agents parts)'와 동일합니다. – soulcheck

답변

5

당신은 forexperiment-with-futures의 내부 게으른 시퀀스를 생성한다는 사실에 의해 넘어지고 있습니다. 특히이 코드는 다음과 같습니다.

(for [index (range num-futures)] (future (f (nth parts index)))) 

모든 선물은 즉시 생성되지 않습니다. 시퀀스의 내용이 실현 될 때까지 선물을 생성하지 않는 지연 시퀀스를 반환합니다. 게으른 순서를 실현하는 코드는 다음과 같습니다

여기
(vec (flatten (map deref futures))) 

map 미래의 게으른 순서에 의해 뒷받침 간접 참조 된 미래의 결과를 게으른 시퀀스를 반환합니다. vecmap에 의해 생성 된 시퀀스의 결과를 소비하기 때문에 이전의 새로운 미래가 완료 될 때까지 각각의 새로운 미래가 처리를 위해 제출되지 않습니다.

병렬 처리를 얻으려면 지연 생성을 지연해야합니다. doall 안에 선물을 만들 때 for 루프를 래핑 해보십시오.

상담원과의 개선 사항을 확인하는 이유는 상담원 결과를 수집하기 직전에 (apply await agents)을 호출하기 때문입니다. 또한 start-agents 함수는 지연 시퀀스를 반환하며 실제로는 에이전트 작업을 전달하지 않습니다. apply의 구현 세부 사항은 전달 된 작은 시퀀스 (20 개 항목 이하)를 완전히 실현한다는 것입니다. agentsapply으로 전달하는 부작용은 시퀀스가 ​​실현되고 모든 에이전트 조치가 await으로 전달되기 전에 전달된다는 것입니다.

관련 문제