Dictionary clojure pmap vs map

Dictionary clojure pmap vs map,dictionary,clojure,pmap,Dictionary,Clojure,Pmap,我在cojure REPL中测试了clojure函数映射和pmap,如下所示。这让我感到困惑:为什么并行pmap比map慢 user=> (def lg (range 1 10000000)) user=> (time (def rs (doall (pmap #(* % %) lg)))) "Elapsed time: **125739.056** msecs" # ----------------------------------------------

我在cojure REPL中测试了clojure函数映射和pmap,如下所示。这让我感到困惑:为什么并行pmap比map慢

user=> (def lg (range 1 10000000))
user=> (time (def rs (doall (pmap #(* % %) lg))))

"Elapsed time: **125739.056** msecs"

# -------------------------------------------------------
user=> (def lg (range 1 10000000))
user=> (time (def rs (doall (map #(* % %) lg))))

"Elapsed time: **5804.485** msecs"

**PS: the machine has 8 cores**

创建线程、在线程之间分配工作负载和重新组装结果都会有一些开销。你需要一个比
#(*%%)
运行时间长得多的函数才能从
pmap
看到速度的提高(当然这也取决于你在问题中没有指定的CPU内核数量)。

Rörd是正确的,使用pmap会有很大的开销。考虑使用减缩器代替:

(def l (range 10000000))

(time (def a (doall (pmap #(* % %) l))))
"Elapsed time: 14674.415781 msecs"

(time (def a (doall (map #(* % %) l))))
"Elapsed time: 1119.107447 msecs"

(time (def a (doall (into [] (r/map #(* % %) l)))))
"Elapsed time: 1049.754652 msecs"

对于每个并行处理任务,由于任务协调,会有一些开销
pmap
将映射函数分别应用于不同线程中的每个元素。由于使用了
pmap
返回的惰性序列,使用者线程必须与生产者线程协调。通过定义
pmap
的方式,产生的每个元素都会产生这种开销

考虑到这一点,当您使用
pmap
来计算一个简单函数(例如,在您的示例中,对一个数字进行平方运算)时,线程协调其活动所需的时间将超过实际计算该值所需的时间。正如docstring所说,
pmap
仅适用于计算密集型函数,其中f的时间占协调开销的主导地位(empasis补充)。在这些情况下,
pmap
将花费比
map
更长的时间,无论您有多少内核

要真正看到
pmap
的好处,您必须选择一个“更难”的问题。在某些情况下,这可能与将输入序列划分为块一样简单。然后可以使用
pmap
处理块序列,然后运行
concat
以获得最终输出

例如:

(defn chunked-pmap [f partition-size coll]
  (->> coll                           ; Start with original collection.

       (partition-all partition-size) ; Partition it into chunks.

       (pmap (comp doall              ; Map f over each chunk,
                   (partial map f)))  ; and use doall to force it to be
                                      ; realized in the worker thread.

       (apply concat)))               ; Concatenate the chunked results
                                      ; to form the return value.
但是,对序列进行分区并在最后连接块也会有开销。例如,至少在我的机器上,
chunked pmap
的执行量仍然大大低于
map
。不过,它可能对某些功能有效

提高
pmap
有效性的另一种方法是在整个算法中的不同位置划分工作。例如,假设我们对计算点对之间的欧几里德距离感兴趣。虽然将平方函数并行化已被证明是无效的,但我们可能会幸运地将整个距离函数并行化。实际上,我们希望在更高的层次上划分任务,但这是其要点


简言之,并行算法的性能对任务的划分方式非常敏感,您选择的测试级别过于精细。

请务必与系统上的
(time(def a(mapv#(*%%)l))
和Clojure版本进行比较