Clojure性能,大型矢量大循环

时间:2013-05-14 01:18:46

标签: performance loops clojure

我在两个向量上执行元素操作,大小为50,000个元素,并且具有不令人满意的性能问题(几秒钟)。是否有任何明显的性能问题,例如使用不同的数据结构?

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

2 个答案:

答案 0 :(得分:11)

试试这个:

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

一些注意事项:

  • map ping函数到多个集合使用每个集合中的元素作为函数的参数 - 不需要interleavepartition
  • 如果您的数据是1和0,那么xor将比绝对差异快

定时示例:

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

预热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

答案 1 :(得分: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每对元素下 - 这很快:你很难在不诉诸低级数组代码的情况下击败它。