2015-06-27 13 views
5

Jaki jest najbardziej wydajny i idiomatyczny sposób łączenia dwóch lub więcej dużych wektorów? Właśnie to robiłem. W mojej aplikacji używam macierzy, więc każda operacja jest nieco droższa niż dodanie dwóch podwójnych. Używanie range do kierowania zakładką jest nieco niezgrabne.Reduktory Clojure - efektywnie stosują funkcję do dwóch wektorów w równoleżniku

(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)))) 

obliczania też, że range może skończyć się najbardziej kosztowny nieco na wielordzeniowych procesorów, ponieważ jest to jedyna część nierównoległe i obejmują sekwencje.

+1

zakładam to 'mapv' zamiast' vmap'? –

+0

Czy a i b faktycznie macierze zamiast wektorów? –

+0

Czy możesz dalej opisać kształt swoich danych i rzeczywiste obliczenia? Możliwe, że coś w rodzaju core.matrix może lepiej pasować. –

Odpowiedz

0

Wygląda na to, że Clojure 1.8 ma całkiem niezłą odpowiedź, ze wzorem w Clojure 1.7 z użyciem map-index.

Idealnie chciałbym map-index, który zajmuje wiele zbiorów, takich jak map, ale to zrobi. Wygląda całkiem nieźle, w przeciwieństwie do mojego kludgy fold na odległość.

(defn combine-with [op a-coll] (fn [i b-el] (op (a-coll i) b-el))) 

(map-indexed (combine-with + a) b) 

prostu trzeba czekać na 1,8 do wykonywania: http://dev.clojure.org/jira/browse/CLJ-1553

Oto niektóre czasy na CPU 6 Rdzeń:

(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 
Powiązane problemy