2013-05-14 3 views
8

크기가 50,000 개이고 성능 문제 (수 초)가 불충분 한 두 벡터에 대해 요소 단위 작업을 수행하고 있습니다. 다른 데이터 구조를 사용하는 것과 같은 명백한 성능 문제가 있습니까?Clojure 성능, 큰 벡터에 대해 큰 루핑

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

답변

11

이 시도 :

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

일부 노트 : 여러 컬렉션에

  • map 핑 (ping) 함수는 함수의 인수로 각에서 요소를 사용 - interleave 필요하고 이것에 대해서는 partition입니다. 데이터 인 경우
  • 는 1과 0의 다음 xor 절대 차이보다 빨라집니다

시간 초과 예 : JVM을 예열 한 후

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

...

(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

대규모 벡터 작업에 대한 좋은 성능에 관심이 있다면 core.matrix을 채택해야합니다.

특히, vectorz-clj 라이브러리 (core.matrix 구현)는 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 

즉, 요소의 쌍 당 20ns에서 - 그 꽤 빠른 : 당신이 하드 낮은 수준의 배열 손보는 코드에 의존하지 않고 이길 누르면 될 것입니다.

+1

'int-array's에 사용하기위한 array-fiddling (같은 길이의 체크 안함)의 예 : (defn xor-sum [^ ints xs,^ints ys] (areduce xs i ret (int 0)) (체크되지 않은 add ret (bit-xor (aget xs i) (aget ys i)))))) ' –