Clojure reducers - 高效地将函数并行应用于两个向量
Clojure reducers - efficiently apply function to two vectors in parrallel
将两个或多个大向量组合在一起的最有效和最惯用的方法是什么?这就是我一直在做的。在我的应用程序中,我使用的是矩阵,因此每个操作比添加两个双精度数要贵一些。使用 range
来驱动折叠感觉有点笨拙。
(require '[clojure.core.reducers :as r])
(def a (mapv (fn [_] (rand 100)) (range 100000)))
(def b (mapv (fn [_] (rand 100)) (range 100000)))
(r/foldcat (r/map #(+ (a %) (b %)) (range (count a))))
还计算 range
最终可能成为多核 CPU 上成本最高的位,因为它是唯一的非并行部分并且涉及序列。
实际上看起来 Clojure 1.8 有一个很好的答案,该模式已经在 Clojure 1.7 中使用 map-index
。
理想情况下,我想要一个像 map
那样需要多个集合的 map-index
,但这样就可以了。它看起来相当古怪,不像我在一个范围内的笨拙折叠。
(defn combine-with [op a-coll] (fn [i b-el] (op (a-coll i) b-el)))
(map-indexed (combine-with + a) b)
只需要等待1.8的性能:http://dev.clojure.org/jira/browse/CLJ-1553
以下是 6 核上的一些时序 CPU:
(def irange (vec (range (count a)))) ; precompute
(c/quick-bench (def ab (r/foldcat (r/map #(+ (a %) (b %)) irange))))
Execution time mean : 1.426060 ms
(c/quick-bench (def abt (into [] (map-indexed (combine-with + a)) b)))
Execution time mean : 9.931824 ms
将两个或多个大向量组合在一起的最有效和最惯用的方法是什么?这就是我一直在做的。在我的应用程序中,我使用的是矩阵,因此每个操作比添加两个双精度数要贵一些。使用 range
来驱动折叠感觉有点笨拙。
(require '[clojure.core.reducers :as r])
(def a (mapv (fn [_] (rand 100)) (range 100000)))
(def b (mapv (fn [_] (rand 100)) (range 100000)))
(r/foldcat (r/map #(+ (a %) (b %)) (range (count a))))
还计算 range
最终可能成为多核 CPU 上成本最高的位,因为它是唯一的非并行部分并且涉及序列。
实际上看起来 Clojure 1.8 有一个很好的答案,该模式已经在 Clojure 1.7 中使用 map-index
。
理想情况下,我想要一个像 map
那样需要多个集合的 map-index
,但这样就可以了。它看起来相当古怪,不像我在一个范围内的笨拙折叠。
(defn combine-with [op a-coll] (fn [i b-el] (op (a-coll i) b-el)))
(map-indexed (combine-with + a) b)
只需要等待1.8的性能:http://dev.clojure.org/jira/browse/CLJ-1553
以下是 6 核上的一些时序 CPU:
(def irange (vec (range (count a)))) ; precompute
(c/quick-bench (def ab (r/foldcat (r/map #(+ (a %) (b %)) irange))))
Execution time mean : 1.426060 ms
(c/quick-bench (def abt (into [] (map-indexed (combine-with + a)) b)))
Execution time mean : 9.931824 ms