【发布时间】:2020-05-10 12:23:51
【问题描述】:
我正在尝试在 Clojure 中使用 pmap 为我的地图使用并发,我需要根据程序在不同线程数下的效率做一些分析。
Clojure 中定义的线程数是在 pmap 函数中还是在项目文件中的某个位置?查看 pmap 文档,与 map 函数相比,没有其他参数。
例如,我需要在2、32、64等...线程下运行程序。
【问题讨论】:
标签: concurrency clojure
我正在尝试在 Clojure 中使用 pmap 为我的地图使用并发,我需要根据程序在不同线程数下的效率做一些分析。
Clojure 中定义的线程数是在 pmap 函数中还是在项目文件中的某个位置?查看 pmap 文档,与 map 函数相比,没有其他参数。
例如,我需要在2、32、64等...线程下运行程序。
【问题讨论】:
标签: concurrency clojure
您的问题似乎与以下内容密切相关: How many threads does Clojure's pmap function spawn for URL-fetching operations?
从Alex Miller的回答可以推断出pmap使用的线程数是<your number of core> + 2。我不知道为什么会有+ 2,但即使使用当前版本的 Clojure 1.10.0,pmap 函数的源代码仍然相同。
由于我的机器上有 4 个内核,pmap 应该使用 6 个线程。
-- 编辑
要真正回答您的问题,您可以定义一个自定义 pmap 函数 custom-pmap,它允许您指定要使用的线程数:
(defn custom-pmap
([f coll nb-thread]
(let [n nb-thread
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)))))
(custom-pmap inc (range 1000) 8)
;; => (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ....999 1000)
【讨论】:
您可以使用claypoole 的pmap,它将特定大小的线程池作为第一个参数。
# project.clj
[com.climate/claypoole "1.1.4"]
# or deps.edn
com.climate/claypoole {:mvn/version "1.1.4"}
现在让我们指定一些池大小,并在大小为 64 的集合上映射一个需要一秒钟的操作。
(ns demo
(:refer-clojure :exclude-clojure [pmap])
(:require [com.climate.claypoole :refer [threadpool pmap]]))
(def pool-sizes
[2 32 64])
(doseq [pool-size pool-sizes]
(time (doall (pmap (threadpool pool-size) (fn [n] (Thread/sleep 1000)) (range 64)))))
“经过时间:32113.704013 毫秒”
“经过时间:2013.242638 毫秒”
“经过时间:1011.616369 毫秒”
因此,大小为 2 的线程池需要一些开销和 32 秒,大小为 32 的线程池需要 2 秒,大小为 64 的线程池需要 1 秒。
【讨论】: