Clojure 期货比经纪人慢?
下面的代码实际上只是让您并行执行(函数(范围n))之类的东西Clojure 期货比经纪人慢?,clojure,Clojure,下面的代码实际上只是让您并行执行(函数(范围n))之类的东西 (experiment-with-agents 10000 10 #(filter prime? %)) 例如,使用10个代理查找0到10000之间的素数 (experiment-with-futures 10000 10 #(filter prime? %)) 期货也是如此 现在的问题是,使用期货的解决方案不会在使用更多期货时运行得更快。例如: ; Futures (time (experiment-with-futures 1
(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)))))
你会被这样一个事实绊倒,
for
在期货实验中产生了一个惰性序列。特别是,这段代码:
(for [index (range num-futures)] (future (f (nth parts index))))
不会立即创建所有的期货;它返回一个惰性序列,在序列的内容实现之前不会创建未来。实现延迟序列的代码是:
(vec (flatten (map deref futures)))
在这里,map
返回一个延迟的未来结果序列,由延迟的未来序列支持。由于vec
使用由map
生成的序列的结果,因此在前一个未来完成之前,不会提交每个新未来进行处理
要获得并行处理,您不需要懒洋洋地创建未来。尝试将for
循环包装起来,在doall
中创建未来
在收集代理结果之前,立即调用(应用等待代理)
,这是您看到代理改进的原因。start agents
函数也会返回一个延迟序列,并且不会实际分派代理操作。apply
的一个实现细节是,它完全实现了传递给它的小序列(不到20项左右)。将代理传递给应用
的一个副作用是,在将其传递给等待
之前,实现了序列并调度了所有代理操作,(应用concat…
几乎总是比(展平…
和(展平(地图…)
可以(和应该)更好通常替换为(mapcat…
(map#(进入[][%1%2])代理部分)
也相当于(map vector代理部分)