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成为窗口中的第一个。因此,它实际上不是使用并行窗口,而是一个块。

你可能已经知道,但有一个库有一个更好的pmap:[链接](https://github.com/clj-commons/claypoole/blob/master/src/clj/com/climate/claypoole.clj#L406)

根据你的需要,另一个替代方案是输入队列加工人池加输出队列,例如通过java.util.concurrent.ExecutorsExecutorCompletionService

它们都不是像clojure.core.pmap那样懒,但有一个原因。关于为什么将惰性与并行性相结合不是一件好事,已经有了大量的讨论(我没有检查,但感觉它们大约每两个月发生一次)。


编辑
“块”确实是合适的词汇,谢谢。但仍然不明白它如何回答问题。为什么我不能传递自定义块大小?有时候,我需要的比CPU数量稍多一点。这可以是一个可选参数。添加额外的库是最后的手段,我认为。
鉴于每次在Slack上提到pmap时,人们往往会说“pmap几乎 never 是答案”,我觉得pmap是Clojure core中的一个小错误,与其为其添加可能进一步鼓励其使用的旋钮和按钮,不如让人远离pmap并使用底层的Java标准库和互操作。
然而,当 `pmap` 确实是正确答案时,它是一个非常棒的答案。我同意在服务器环境中,`pmap` 可能常常是错误答案,但对于快速而简陋的一次性脚本来说,它非常方便,或者我敢说,很简单,相比之下,下降到底层的原语更复杂,尽管简单。
...