【问题标题】:Computing a long sum with Clojure futures使用 Clojure 期货计算长和
【发布时间】:2014-01-12 14:09:20
【问题描述】:

运行此代码:

(ns playfield.core)

(defn sum
  [start end]
  (reduce + (range start end)))

(def size 1e8)

(defn -main
  [& args]
  (println (time (sum 0 size)))
  (println (time (let [left (future (sum 0 (/ size 2)))
                       right (future (sum (/ size 2) size))]
                   (+ @left @right)))))

给我这个输出:

"Elapsed time: 2742.185 msecs"
4999999950000000
"Elapsed time: 2605.541 msecs"
4.99999995E15

我预计第二个将花费大约一半的时间,因为我将计算分布在两个线程上。我做错了什么?

【问题讨论】:

  • 由于使用了惰性序列,您似乎大部分时间都浪费在每一步的开销上。
  • 对我来说第二快两倍:12626.003474 msecs vs 6696.957308 msecs
  • 顺便说一句,你们必须用什么超级计算机来总结所有 0-1e8?我的机器需要很长时间,我已经取消了它。它在 2.3 GHz 4 核处理器上运行
  • 我得到了4563.518 msecs vs 2543.745 msecs(未来版本大约需要直接版本的 55% 的时间)。您正在测试的机器上确实有多个内核,对吗?您知道对 JVM 进行基准测试的技巧吗?也许改用criterium? @lgrapenthin,我有一个 2.3 GHz Intel Core i7(Retina Macbook Pro,2012 年中)。
  • 是的,我没有使用 criterium 进行基准测试,我只是尝试了一段时间,并且一直持续。这可能是 leiningens 默认的 JVM 设置。

标签: concurrency clojure future


【解决方案1】:

我稍微修改了您的示例(在-main 的末尾添加了(shutdown-agents))并在两台机器上运行(lein run -m playfield.core):

Retina Macbook Pro,2012 年中

  • 2.3 GHz 英特尔酷睿 i7
  • 16 GB 内存
  • Java(TM) SE 运行时环境(内部版本 1.7.0_45-b18)

结果:

serial:   2678.034 msecs
parallel: 1943.153 msecs
Parallel takes 72.3% of baseline.

请注意,这些结果与我原来的评论不同。该数据是从 REPL 运行的。

联想 Thinkstation S20

  • 3.07GHz 英特尔至强 W3550
  • 8 GB 内存
  • Java(TM) SE 运行时环境(内部版本 1.7.0_45-b18)

结果:

Serial:   12390.296313 msecs
Parallel:  6856.656525 msecs
Parallel takes 55.3% of baseline.

我可以想到您在进行基准测试时可能遇到的两个问题:

  1. 机器没有多个内核/Java 仅限于一个内核/内核以其他方式加载。
  2. 对 JVM 进行基准测试很棘手。一般推荐使用criterium。但是,我上面的数字是使用 time 生成的,所以我不确定它是否会在这里发挥作用。

编辑

我还有一些想法:

正如@lgrapenthin 提到的,JVM 选项会影响时间。例如,lein 对improve startup time 使用以下两个选项:-XX:+TieredCompilation -XX:TieredStopAtLevel=1。对于这种情况,改变它有明显的不同:

$ LEIN_JVM_OPTS="" lein run -m 'speed.core'
Serial:   2496.435288 msecs
Parallel: 2045.084565 msecs
Parallel takes 81.9% of baseline. 

@Giuseppe 的评论指出正在积极使用 4 个内核(我认为这意味着充分利用)。可能那个JVM内存压力大,CPU占用是垃圾收集器疯狂地工作以腾出一些内存。但是,我无法在本地重现此内容。

【讨论】:

  • @Giuseppe 该图是显示整个系统的 CPU 使用率,还是仅限于 Java 进程?如果是前者,那就不是很有用了,我建议专门看一下java进程列出的CPU百分比。
  • 它显示了整个系统的CPU使用率,但它应该足以表明核心未饱和并且所有核心都已使用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-22
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多