如何有效地并行应用中等重量的功能

时间:2009-11-09 18:05:11

标签: clojure parallel-processing

我希望将一个适度昂贵的函数映射到一个大型的懒惰seq并行。 pmap很棒,但我对上下文切换很不满意。我想我需要增加传递给每个线程的工作块的大小。

我写了一个函数来将seq分解为块并将函数pmap到每个块上并重新组合它们。这“有效”,但结果并不壮观。原始代码基本上如下所示:

(pmap eval-polynomial (range x) coificients)

如何在保持懒惰的同时真正挤压它?

4 个答案:

答案 0 :(得分:6)

如何使用partition功能分解range序列?在http://www.fatvat.co.uk/2009/05/jvisualvm-and-clojure.html

上有一篇关于类似问题的有趣帖子

答案 1 :(得分:3)

我从http://www.braveclojure.com/zombie-metaphysics/查看ppmap函数。它允许您在指定块大小时进行pmap。

  

解决这个问题的方法是增加粒度,或者   每个并行化任务完成的工作量。在这种情况下,任务   是将映射函数应用于集合的一个元素。   粒度不是以任何标准单位来衡量的,但你要说的是   默认情况下,pmap的粒度为1。将粒度增加到两个   意味着你将映射函数应用于两个元素   而不是一个,所以任务所在的线程正在做更多的工作。   [...]只是为了好玩,我们可以将这项技术概括为一个功能   称为ppmap,用于分区pmap。它可以收到多个   集合,就像地图:

(defn ppmap
  "Partitioned pmap, for grouping map ops together to make parallel
  overhead worthwhile"
  [grain-size f & colls]
  (apply concat
   (apply pmap
          (fn [& pgroups] (doall (apply map f pgroups)))
          (map (partial partition-all grain-size) colls))))
(time (dorun (ppmap 1000 clojure.string/lower-case orc-name-abbrevs)))
; => "Elapsed time: 44.902 msecs"

答案 2 :(得分:1)

如果你不介意一些有点异国情调的东西(以换取一些非常明显的加速),你可能还想看一下Penumbra-library的作者所做的工作,它提供了easy access to the GPU。< / p>

答案 3 :(得分:0)

我会看一下Fork/Join库,它将被集成到JDK 7中。它是一个轻量级的线程模型,针对数据集上的非阻塞,分而治之的计算进行了优化,使用线程池,工作 - 窃取调度程序和绿色线程。

Some work已完成将Fork / Join API包装在par分支中,但尚未合并到main(yet)。