7

我在 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**
4

3 回答 3

18

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

考虑到这一点,当您用于pmap计算一个简单的函数(例如对一个数字进行平方,如您的示例中所示)时,线程协调其活动所需的时间会超过实际计算该值所需的时间。正如文档字符串所说,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是将工作划分在整个算法的不同位置。例如,假设我们对计算点对之间的欧几里得距离感兴趣。虽然并行化 square 函数已被证明是无效的,但我们可能会幸运地并行化整个距离函数。实际上,我们希望在更高级别上划分任务,但这就是要点。

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

于 2013-11-14T08:02:30.287 回答
3

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"
于 2013-11-13T14:26:12.093 回答
2

创建线程、在它们之间拆分工作负载和重新组装结果会产生一些开销。您将需要一个运行时间明显长于#(* % %)查看速度改进的函数pmap(当然,它还取决于您在问题中未指定的 CPU 的内核数量)。

于 2013-11-13T12:10:10.017 回答