评论由:jim.blomo发表
当任务受CPU限制时,同时启动比CPU核心更多的线程不是一个好主意。目前(1.4)pmap 使用一个无界的线程池,因此分块序列将创建比预期更多的线程。最低侵入性变更是使用固定大小的线程池(例如ForkJoinPool)。pmap 与 core.reducers 区别在于它是懒的。这意味着它是按顺序一次提交一个线程 Pool 的模型,而不是递归的 fork/join 模型。权衡包括
在分块序列上强制预览
- 无需更改线程池
- 违背分块,这可能是出于某种原因而使用的
迁移到固定大小线程池
- 减少分块序列上 CPU 密集型函数的竞争
- 增加 I/O 密集型函数的总实现时间
使用 ForkJoinPool 作为固定线程池(而不是 newFixedThreadPool)
- 自动和动态并行性
- - 更复杂的设置(选择 Java 6 与 7 实现,与 core.reducers 共享池)
我认为使用传统的固定大小线程池是正确的选择。大部分时间,pmap 的所有结果都将被实现,因此我认为严格限制预览大小不值得。这也是 map 所做的决定。因为我们没有利用 ForkJoin 的主要优势(递归工作队列),我认为在 clojure.core 中设置它不值得。
我将使用 Agent/pooledExecutor 作为固定大小线程。
如果我不小心或误解了什么,请告诉我。