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

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

0
Clojure

标准pmap函数不允许指定自己的窗口大小。它默认取可用CPU数量+2。

(+ 2 (.. Runtime getRuntime availableProcessors))

我想知道为什么没有提供传递自定义N的方法?为了绕过这个限制,我有一个像这样的函数

(defn pmap+
  "
  Like pmap but accepts a custom size of a parallel
  window. Lazy. Takes only one collection of arguments
  at the moment.
  "
  [n func items]
  (lazy-seq
   (let [[head tail]
         (split-at n items)]
     (when (seq head)
       (let [futures
             (for [item head]
               (future (func item)))]
         (concat
          (->> futures
               doall
               (map deref))
          (pmap+ n func tail)))))))

这在通过HTTP API处理第三方服务时非常有帮助。我的问题是,我们能否有一个可选的N参数的pmap,或者可能添加一个新函数?

谢谢,
Ivan

1 个答案

0

pmap+不会使整个CPU饱和 - 它可能等待批次中的最后一个future,而不是在悬挂的future变为窗口中的第一个时继续执行。因此,实际上它使用的是一块而不是并行窗口。

你可能已经注意到了,但有一个库提供了一个更好的pmaphttps://github.com/clj-commons/claypoole/blob/master/src/clj/com/climate/claypoole.clj#L406

根据你为什么需要pmap+,另一个替代方案是输入队列+工作池+输出队列,例如通过java.util.concurrent.ExecutorsExecutorCompletionService

这些都不是惰性的,就像clojure.core.pmap中那样,但原因不同。关于为什么将惰性与并行性结合起来不是一件好事,已经有很多人在Slack上讨论过了(没有去检查,但感觉大约每隔两个月就会有一次)。


编辑过
“块”确实是正确的说法,谢谢。但仍然无法理解它如何回答问题。为什么我不能传入自定义块大小?有时候,我需要的只是比CPU数量多一点点。这可以是一个可选项。插入一个额外的库是最后的手段,我认为。
鉴于每次在Slack上提到pmap时,人们总是倾向于说“pmap几乎从不是答案”,我的感觉是,pmap在Clojure核心中确实是一个小错误,与其添加可能进一步鼓励其使用的旋钮和调件,不如将人们推向使用底层Java标准库和互操作。
然而,当`pmap`确实是正确答案时,它是一个非常好的答案。我同意在服务器环境中,`pmap`可能非常经常不是正确答案,但对于快速简便的一次性脚本,它非常方便,或者我敢 say,相对于降低到底层的原语,这要容易得多,因为这些原语简单,但并不那么容易。
...