运行此代码:
(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
我期待第二个占用大约一半的时间,因为我在两个线程上分配计算。我做错了什么?
答案 0 :(得分:1)
我稍微修改了您的示例(在(shutdown-agents)
末尾添加-main
)并在两台计算机上运行(lein run -m playfield.core
):
Retina Macbook Pro,2012年中期
结果:
serial: 2678.034 msecs
parallel: 1943.153 msecs
Parallel takes 72.3% of baseline.
请注意,这些结果与我原来的评论不同。该数据来自REPL。
联想Thinkstation S20
结果:
Serial: 12390.296313 msecs
Parallel: 6856.656525 msecs
Parallel takes 55.3% of baseline.
我可以想到在基准测试时你可能遇到的两个问题:
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使用率是垃圾收集器疯狂地工作以使一些内存可用。然而,我无法在本地重现这一点。