【发布时间】:2013-02-11 17:59:50
【问题描述】:
我正在尝试弄清楚如何使用 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)))
【问题讨论】:
-
这些块是错误的方式吗?
(partition-all workers vs)创建长度为workers的(/ n workers)序列。你不想(partition-all (long (/ n workers)) vs)吗? -
@A.Webb,感谢您的更正。我会修改问题。此修复有助于使并行版本更快一些,但它仍然无法击败串行实现,并且在非常大的输入上仍然会耗尽内存。
标签: clojure parallel-processing