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 core中出现是个错误,与其增加可能进一步鼓励其使用的旋钮和调节器,不如推动人们远离pmap,转向使用底层Java标准库和互操作。
然而,当`pmap`是正确答案时,它是一个非常好的答案。我同意在服务器环境中,`pmap`可能是错误的答案,但对于快速简单的单次脚本,它非常方便,或者我敢说很简单,与降级到底层原语相比,底层原语简单,但不那么容易。
...