2013-05-14 14 views
8

Sto eseguendo operazioni a livello di elemento su due vettori dell'ordine di 50.000 elementi in dimensioni e con problemi di prestazioni insoddisfacenti (alcuni secondi). Ci sono ovvi problemi di prestazioni da fare, come l'utilizzo di una diversa struttura dati?Prestazioni del Clojure, loop elevato su vettori di grandi dimensioni

(defn boolean-compare 
    "Sum up 1s if matching 0 otherwise" 
    [proposal-img data-img] 
    (sum 
    (map 
    #(Math/abs (- (first %) (second %))) 
    (partition 2 (interleave proposal-img data-img))))) 

risposta

11

Prova questo:

(apply + (map bit-xor proposal-img data-img))) 

Alcune note:

  • map ping una funzione per diverse collezioni utilizza un elemento da ciascuno come gli argomenti della funzione - non c'è bisogno di interleave e partition per questo.
  • Se i dati sono 1 e 0, quindi xor sarà più veloce di differenza assoluta

esempio temporizzata:

(def data-img (repeatedly 50000 #(rand-int 2))) 
(def proposal-img (repeatedly 50000 #(rand-int 2))) 
(def sum (partial apply +)) 

Dopo il riscaldamento la JVM ...

(time (boolean-compare proposal-img data-img)) 
;=> "Elapsed time: 528.731093 msecs" 
;=> 24802 

(time (apply + (map bit-xor proposal-img data-img))) 
;=> "Elapsed time: 22.481255 msecs" 
;=> 24802 
5

Si dovrebbe prendere in considerazione l'adozione di core.matrix se si è interessati a buone prestazioni per operazioni vettoriali di grandi dimensioni.

In particolare, la libreria vectorz-clj (un'implementazione core.matrix) ha alcune implementazioni molto veloci per la maggior parte delle operazioni vettoriali con i valori double.

(def v1 (array (repeatedly 50000 #(rand-int 2)))) 
(def v2 (array (repeatedly 50000 #(rand-int 2)))) 

(time (let [d (sub v2 v1)] ;; take difference of two vectors 
    (.abs d)     ;; calculate absolute value (mutate d) 
    (esum d)))    ;; sum elements and return result 

=> "Elapsed time: 0.949985 msecs" 
=> 24980.0 

vale a dire sotto 20ns per coppia di elementi - che è piuttosto veloce: si sarebbe difficile da battere che senza ricorrere a basso livello di codice array-giocherellare.

+1

Esempio di armagliature (senza controlli della stessa lunghezza) da utilizzare su 'int-array's:' (defn xor-sum [^ ints xs,^ints ys] (areduce xs i ret (int 0) (deselezionato-add ret (bit-xor (aget xs i) (aget ys i))))) ' ' –

Problemi correlati