评论者:jim.blomo
当工作受CPU限制时,启动比CPU核心数量更多的线程并不是一个好主意。目前(1.4版)pmap使用一个无界的线程池,因此分块序列将会创建比预期更多的线程。做出的最微创变是使用固定大小的线程池(ForkJoinPool就是一个例子)。pmap与core.reducers的区别在于它是惰性的。这意味着它采用单线程提交模型,而不是递归的分解/合并模型。权衡包括
即使在分块序列中强制预览
- + 不需要更改threadPool
- - 与分块作对,而分块可能是出于某种原因而使用的
转移到固定大小线程池
- + 减少分块序列上CPU绑定函数的竞争
- - 增加I/O密集型函数的总实现时间
使用ForkJoinPool作为固定线程池(而不是newFixedThreadPool)
- + 自动和动态并行
- - 更复杂的设置(选择Java 6 vs 7实现,与core.reducers共享池)
我认为使用传统的固定大小线程池是正确选择。大多数时候,pmap的所有结果都将被实现,所以我认为没有必要对预览大小过于严格。这也是决策map所做的决定。由于我们没有使用ForkJoin的主要优势(递归工作队列),我认为在clojure.core中设置它并不值得。
我将对Agent/pooledExecutor作为固定大小的线程。
如果有什么遗漏或误解的地方,请通知我。