【问题标题】:Clojure performance, large looping over large vectorsClojure 性能,大型向量上的大型循环
【发布时间】:2013-05-08 04:07:33
【问题描述】:

我正在对大小约为 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)))))

【问题讨论】:

    标签: performance loops clojure


    【解决方案1】:

    试试这个:

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

    一些注意事项:

    • mapping 一个函数到多个集合使用每个集合中的一个元素作为函数的参数 - 为此无需 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
    

    【讨论】:

      【解决方案2】:

      如果您对大型向量运算的良好性能感兴趣,您应该考虑采用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 下每对元素 - 这非常快:如果不求助于低级数组摆弄代码,你将很难击败它。

      【讨论】:

      • int-arrays: (defn xor-sum [^ints xs, ^ints ys] (areduce xs i ret (int 0) (unchecked-add ret (bit-xor (aget xs i) (aget ys i))))) ` 上使用的数组摆弄示例(不检查相同长度)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多