2015-06-27 7 views
5

Qual è il modo più efficiente e idiomatico di combinare due o più vettori di grandi dimensioni insieme? Questo è quello che ho fatto. Nella mia applicazione sto usando le matrici, quindi ogni operazione è un po 'più costosa dell'aggiunta di due doppi. Usare range per guidare la piega si sente un po 'goffo.Riduttori clojure - applicano efficacemente la funzione a due vettori in parallelo

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

calcolando inoltre che range potrebbe finire per essere il bit più costoso su CPU multi-core poiché è l'unica parte non paralleli e coinvolgere sequenze.

+1

Penso che sia 'mapv' invece di' vmap'? –

+0

A e b sono effettivamente matrici invece di vettori? –

+0

Puoi descrivere ulteriormente la forma dei tuoi dati e il calcolo reale? È possibile che qualcosa come core.matrix possa essere una soluzione migliore. –

risposta

0

In realtà sembra che Clojure 1.8 abbia una buona risposta, con lo schema già in Clojure 1.7 utilizzando map-index.

Idealmente mi piacerebbe un map-index che richiede più raccolte come map, ma questo lo farà. Sembra piuttosto clojuresque, a differenza del mio kludgy fold su un range.

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

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

solo bisogno di aspettare per 1.8 per le prestazioni: http://dev.clojure.org/jira/browse/CLJ-1553

Ecco alcuni tempi su una CPU 6 nucleo:

(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 
Problemi correlati