2013-05-14 20 views
8

Wykonuję operacje elementarne na dwóch wektorach rzędu 50 000 elementów i mających niezadowalające problemy z wydajnością (kilka sekund). Czy są jakieś oczywiste problemy z wydajnością, takie jak użycie innej struktury danych?Clojure performance, duże pętle nad dużymi wektorami

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

Odpowiedz

11

Spróbuj tego:

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

Kilka uwag:

  • map ping funkcją kilku kolekcjach wykorzystuje element od siebie jako argumenty do funkcji - nie trzeba interleave i partition do tego.
  • Jeśli dane są 1 i 0, a następnie xor będzie szybsze niż bezwzględną różnicę

Tymczasowy przykład:

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

Po rozgrzewce 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

Powinieneś spojrzeć na przyjęcie core.matrix, jeśli jesteś zainteresowany dobrą wydajnością w przypadku dużych operacji wektorowych.

W szczególności biblioteka vectorz-clj (implementacja core.matrix) ma kilka bardzo szybkich implementacji dla większości typowych operacji wektorowych z wartościami 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 

tj pod 20ns za parę elementów - to dość szybko: Ci być ciężko pokonać, że bez uciekania się do niskopoziomowego kodu array-błahy.

+1

Przykład szuflady tablic (bez kontroli dla tej samej długości) do użycia w 'int-array's:' (defn xor-sum [^ ints xs,^ints ys] (areduce xs i ret (int 0) (niezaznaczone - dodaj ret (bit-xor (aget xs i) (aget ys i))))) ' ' –