2024年Clojure状态调查中分享您的想法!

欢迎!请参阅关于页面以了解更多关于此功能的详细信息。

0 投票
Clojure

pmap代码为需要执行的操作集创建future,然后以显然要保留在任何给定时间只有#CPUs+2未完成future的方式处理这个序列。对于非分块输入序列,它正好以此方式工作,但当pmap接收到分块序列时,future序列也变为分块的。这导致在与#CPUs+2窗口和块大小窗口交互时,会实现任意数量的future。

pmap的doc-string没有承诺任何特定的并行级别,但我认为分块和非分块输入的不一致并行性是一个bug。

8 答案

0 投票

评论由:stu发表

下一个深入研究pmap的人可能还需要仔细考虑fork/join。

0 投票

评论由:jim.blomo发表

fork/join是Java 7的一个特性。如果提出的补丁需要能够回退到Java 5特性吗?

0 投票

评论由:jafingerhut发表

Clojure/core成员国可以更权威地说,但我相信随着最近依赖jsr166代码的减少增强,Clojure 1.5可能需要Java 6或更高版本,并且将不再支持Java 5。

0 投票

评论由:jim.blomo发表

当工作受CPU限制时,多启动线程数超过CPU核心数不是一个好主意。目前(1.4版本)pmap使用了一个无限制的线程池,因此分块序列将创建比预期更多的线程。最小的侵扰性更改是使用固定大小的线程池(ForkJoinPool是一个例子)。pmap与core.reducers的区别在于它是懒加载的。这意味着它采用了一个依次提交模型的ThreadPool.submit,而不是递归的fork/join模型。权衡包括

即使在分块序列上也强制执行预读
- + 不改变threadPool
- - 反对分块,这可能是出于某种原因而被使用的

迁移到固定大小线程池
- + 减少在分块序列上对CPU密集型函数的竞争
- - 增加I/O密集型函数的总实际化时间

使用ForkJoinPool作为固定线程池(而不是newFixedThreadPool)
- + 自动和动态并行性
- - 更复杂的设置(选择Java 6与7实现,与core.reducers共享池)

我认为使用传统的固定大小线程池是正确的选择。大多数时候,pmap的所有结果都会被实现,因此我认为不值得通过严格限制预读大小来节省工作量。这也是map所做出的决定。因为我们没有使用ForkJoin的主要优势(递归工作队列),所以我认为在clojure.core中设置它是不值得的。

我将使用Agent/pooledExecutor作为固定大小的线程。

如果我有遗忘或理解错误的地方,请告知。

0 投票

评论由:jim.blomo发表

2012年5月28日的pmap-chunking-862.diff使用固定大小线程池为pmap函数。

0 投票

评论由:jafingerhut发表

2012年5月28日的补丁pmap-chunking-862.diff在2014年1月11日 Clojure master的最新提交之后不再干净。我认为唯一的问题是添加的测试更改了上下文行,所以如果有人想要更新补丁,这将是一个快速的修复。

0 投票

评论由:jim.blomo发表

感谢更新,Andy。这个月我会尝试解决这个问题。

0 投票
参考: https://clojure.atlassian.net/browse/CLJ-862(由llasram报告)
...