期货以某种方式慢于代理? [英] Futures somehow slower then agents?

查看:124
本文介绍了期货以某种方式慢于代理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码实际上只是让你像(function(range n))并行执行。

The following code does essentially just let you execute something like (function (range n)) in parallel.

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

在0到10000之间有10个代理。

This for example finds the prime numbers between 0 and 10000 with 10 agents.

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

与futures相同。

Same just with futures.

是期货的解决方案不会运行得更快,更多的期货。示例:

Now the problem is that the solution with futures doesn't run faster with more futures. Example:

; 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,只是玩的东西^^)?因为我认为期货实际上是在这种情况下优先的。

Why? Did I do something wrong (probably, new to Clojure and just playing around with stuff^^)? Because I thought that futures are actually prefered in that scenario.

资料来源:

(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 在里面产生一个延迟序列的事实让你感到厌烦。 c $ c>。特别是,这段代码:

You're getting tripped up by the fact that for produces a lazy sequence inside of experiment-with-futures. In particular, this piece of code:

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

不会立即创建所有期货;它返回一个延迟序列,它不会创建期货,直到序列的内容被实现。实现延迟序列的代码是:

does not immediately create all of the futures; it returns a lazy sequence that will not create the futures until the contents of the sequence are realized. The code that realizes the lazy sequence is:

(vec (flatten (map deref futures)))

这里, map 返回引用的未来结果的延迟序列由未来的懒惰序列。由于 vec map 产生的序列中消耗结果,因此每个新的future都不会提交处理,直到前一个完成为止。

Here, map returns a lazy sequence of the dereferenced future results, backed by the lazy sequence of futures. As vec consumes results from the sequence produced by map, each new future is not submitted for processing until the previous one completes.

要进行并行处理,您需要不要懒惰地创建期货。尝试包装 for 循环,其中在 doall 中创建期货。

To get parallel processing, you need to not create the futures lazily. Try wrapping the for loop where you create the futures inside a doall.

您看到代理改进的原因是在收集代理结果之前立即调用(应用await代理)。您的 start-agents 函数也会返回延迟序列,并不会实际调度代理操作。 apply 的实现细节是它完全实现了传递给它的小序列(小于20个项目)。将代理更改为的 c>的副作用是,序列被实现,并且所有代理操作在被处理之前被分派到 await

The reason you're seeing an improvement with agents is the call to (apply await agents) immediately before you gather the agent results. Your start-agents function also returns a lazy sequence and does not actually dispatch the agent actions. An implementation detail of apply is that it completely realizes small sequences (under 20 items or so) passed to it. A side effect of passing agents to apply is that the sequence is realized and all agent actions are dispatched before it is handed off to await.

这篇关于期货以某种方式慢于代理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆