请在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

根据您的需求,另一种选择是一个输入队列+一个工作者池+一个输出队列,例如通过java.util.concurrent.ExecutorsExecutorCompletionService

它们与clojure.core.pmap一样都不是懒惰的,但有一个原因。在 Slack 上已经有许多讨论(没有检查,但感觉它们每两个月发生一次),描述为什么将惰性与并行性结合起来不是一件好事。


编辑了
"块"确实是一个正确的词汇,谢谢。但我仍然看不出它如何回答这个问题。为什么我不能传递自定义块大小?有时,我需要的只是CPU数量的少许多一点。它可能是一个可选参数。插入一个额外的库是我最后的手段,我想。
鉴于每当在Slack上提到pmap时,人们往往会说“pmap几乎从不答案是”,我的感觉是,pmap在Clojure核心中是一个小小的错误,而不是添加旋钮和操纵杆来进一步鼓励它的使用,理想的做法是让人们远离pmap,转向使用底层的Java标准库和互操作性。
然而,当`pmap`确实是正确的答案时,它是非常好的答案。我同意在一个服务器环境中,`pmap`可能往往不是正确的答案,但对于快速和不洁的单次脚本,它非常方便,或者说,我想说的是,与其他降级到底层原语相比,很容易。
...