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
by

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核心中有点错误,与其添加可能进一步鼓励其使用的旋钮和开关,不如鼓励人们远离pmap,并使用底层Java标准库和互操作。
然而,当`pmap`确实正确时,它是一个非常好的答案。我同意在服务器环境中`pmap`可能经常是错误的答案,但在快速且简单的脚本中,它非常方便,或者我敢说,简单,与使用底层原语相比,后者虽然简单,但不那么简单。
...