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

欢迎!请参阅关于页面以了解更多关于这个工作的信息。

0
Clojure

pmap 的代码为需要执行的地图操作集创建未来((future %) coll),然后显然以保持任何时候仅有 #CPUs+2 个未完成未来的方式作用于该序列。对于非分块输入序列,它确实以这种方式工作,但是当 pmap 接收到分块序列时,未来序列也变为分块。这导致在 #CPUs+2 窗口和块大小窗口交互时,会产生任意数量的已经实现的未来。

pmap 的文档字符串没有承诺任何特定的并行级别,但我想分块和非分块输入不一致的并行性构成了一个错误。

8 个答案

0

评论者:stu

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

0

评论者:jim.blomo

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

0

评论者:jafingerhut

尽管 Clojure/core 团队可以提供更权威的说法,但我相信,凭借最近基于 jsr166 代码的 reduce 性能增强,Clojure 1.5 很可能需要 Java 6 或更高版本,Java 5 将不再获得支持。

0

评论者:jim.blomo

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

在分块序列上强制预览
- + 没有改变线程池
- - 与分块背道而驰,这可能是出于某种原因

切换到固定大小的线程池
- + 降低分块序列上 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 主分支后不再干净应用。我认为唯一的问题是添加了测试后,上下文行已更改,因此如果有人想更新补丁,应该是快速修复。

0

评论者:jim.blomo

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

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