我试图弄清楚如何使用 clojure 将一个简单的操作有效地并行应用于一个大序列。我希望能够使用并行解决方案来利用我机器上的多个内核来实现一些加速。
我正在尝试将 pmap 与 partition-all 结合使用,以减少为输入序列中的每个项目创建未来的开销。不幸的是,partition-all 强制对每个分区序列进行完整评估。这会在我的机器上导致 OutOfMemoryError。
(defn sum [vs]
(reduce + vs))
(def workers
(+ 2 (.. Runtime getRuntime availableProcessors)))
(let
[n 80000000
vs (range n)]
(time (sum vs))
(time (sum (pmap sum (partition-all (long (/ n workers)) vs)))))
如何将 sum 应用于大型输入集,并超越串行实现的性能?
解决方案
感谢 @Arthur Ulfeldt 指出 reducers 库。这是使用减速器的解决方案。此代码显示了在多核机器上运行时预期的性能改进。(注意:我已将 vs 更改为一个函数,以使时间更准确)
(require '[clojure.core.reducers :as r])
(let
[n 80000000
vs #(range n)]
(time (reduce + (vs)))
(time (r/fold + (vs)))