pmap
函数的文档让我对于像在网络上获取一系列XML源文件这样的操作是否高效感到困惑。我不知道pmap会同时启动多少个抓取操作以及最大值是多少。
pmap
函数的文档让我对于像在网络上获取一系列XML源文件这样的操作是否高效感到困惑。我不知道pmap会同时启动多少个抓取操作以及最大值是多少。
> (use 'clojure.repl)
> (source pmap)
(defn pmap
"Like map, except f is applied in parallel. Semi-lazy in that the
parallel computation stays ahead of the consumption, but doesn't
realize the entire result unless required. Only useful for
computationally intensive functions where the time of f dominates
the coordination overhead."
{:added "1.0"}
([f coll]
(let [n (+ 2 (.. Runtime getRuntime availableProcessors))
rets (map #(future (f %)) coll)
step (fn step [[x & xs :as vs] fs]
(lazy-seq
(if-let [s (seq fs)]
(cons (deref x) (step xs (rest s)))
(map deref vs))))]
(step rets (drop n rets))))
([f coll & colls]
(let [step (fn step [cs]
(lazy-seq
(let [ss (map seq cs)]
(when (every? identity ss)
(cons (map first ss) (step (map rest ss)))))))]
(pmap #(apply f %) (step (cons coll colls))))))
(+ 2 (.. Runtime getRuntime availableProcessors))
是一个重要的提示。 pmap 将会获取前 (+ 2 processors)
个任务并通过 future
异步地运行它们。因此,如果你有2个核心,它将同时启动4个任务,试图保持一定的领先优势,但最大值应该是 2+n。
future
最终使用代理 I/O 线程池,该线程池支持无限数量的线程。当有工作需要处理时,线程池将会增长;若线程闲置,它也会缩小。
在Alex出色的回答基础上,解释了pmap的工作原理,这里是针对你情况的建议:
(doall
(map
#(future (my-web-fetch-function %))
list-of-xml-feeds-to-fetch))
理由:
deref
未来,以便您知道何时完成所有操作。 - Joe看起来 pmap 的操作似乎每次只能同时运行 32 个线程,无论您拥有多少处理器,问题在于 map 会比计算快出 32 倍,并且 futures 是在它们自己的线程中启动的。(示例)
(defn samplef [n]
(println "开始 " n)
(Thread/sleep 10000)
n)
(def result (pmap samplef (range 0 100)))
; 您将等待 10 秒钟并看到 32 个打印,然后当您取第 33 个时,另外 32 个打印,这意味着您每次最多可以并发运行 32 个线程 ; 对我来说这不是完美的 ; SALUDOS Felipe
pmap
对于分派大量网络调用和处理响应非常适用吗?有什么注意事项吗? - danfn
参数来以不同的方式控制线程数量(例如对于每个工作线程消耗的内存是一个问题的情况,以及一般情况下)。 - matanster