Clojure 期货比经纪人慢?

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

下面的代码实际上只是让您并行执行(函数(范围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)))))

你会被这样一个事实绊倒,
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代理部分)