首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Clojure性能优化与等效Java

Clojure性能优化与等效Java
EN

Stack Overflow用户
提问于 2015-01-02 00:17:20
回答 2查看 409关注 0票数 2

加速这个功能的最简单的方法是什么?根据Criterium的说法,java中的等效代码快近50倍。

我打赌如果我使用了java并减少了所有这些都有帮助的装箱量,但我想我应该先在这里发布,看看我犯的任何基本错误是否可以很容易地修复。注:我已经指出(加倍.)这大大提高了性能,但仍然不像Java。我还首先使用(双数组.)转换了seq。而不是使用(vec .)内部的函数,这也提高了性能,但同样,不像Java。

代码语言:javascript
运行
复制
(defn cosine-similarity [ma mb]
  (let [va (vec ma), vb (vec mb)]
    (loop [p (double 0)
           na (double 0)
           nb (double 0)
           i (dec (count va))]
      (if (neg? i)
        (/ p (* (Math/sqrt na) (Math/sqrt nb)))
        (let [a (double (va i))
              b (double (vb i))]
          (recur (+ p (* a b))
                 (+ na (* a a))
                 (+ nb (* b b))
                 (dec i)))))))

请注意,ma和mb都是seqs,每个包含200个双倍。在java版本中,它们作为double[] args传递。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-02 00:39:52

使用(double 0)没有从直接指定0.0 (双文本)中获得的性能好处。

如果将mamb作为double-array传递,并提示args为doubles,不要通过vec将它们转换为向量,并使用aget进行元素查找,您将获得更好的性能。这将给您留下一些与java代码性能非常接近的东西。

如果使用双数组作为函数args,则不需要let块中的double调用。

最终结果应该如下所示:

代码语言:javascript
运行
复制
(defn cosine-similarity [^doubles ma ^doubles mb]
  (loop [p 0.0
         na 0.0
         nb 0.0
         i (dec (count va))]
    (if (neg? i)
      (/ p (* (Math/sqrt na) (Math/sqrt nb)))
      (let [a (aget va i)
            b (aget vb i)]
        (recur (+ p (* a b))
               (+ na (* a a))
               (+ nb (* b b))
               (dec i))))))
票数 5
EN

Stack Overflow用户

发布于 2015-01-02 00:49:37

你试过加法了吗?

代码语言:javascript
运行
复制
(set! *unchecked-math* true)

因为你知道范围,你可能会用它来获得额外的速度。

编辑:@噪音匠是正确的,双数组和输入输入会产生巨大的变化。

Edit2:在亚历克斯·米勒的评论之后,获得了惊人的成绩。

代码语言:javascript
运行
复制
(set! *unchecked-math* true)

(defn ^double cosine-similarity
  [^doubles va ^doubles vb] 
    (loop [p 0.0
    na 0.0
    nb 0.0
    i  (dec (alength va))]
  (if (< i 0)
    (/ p (* (Math/sqrt na) (Math/sqrt nb)))
    (let [a  (aget va i)
          b  (aget vb i)]
       (recur (+ p (* a b))
         (+ na (* a a))
         (+ nb (* b b))
         (dec i))))))

 (defn rand-double-arr [n m]
   (double-array
     (take n (repeatedly #(rand m)))))

 (def ma (rand-double-arr 200 10000))
 (def mb (rand-double-arr 200 10000))

 ; using do times
 (dotimes [_ 30] (time (cosine-similarity ma mb)))
 ; ...
 ; "Elapsed time: 0.003537 msecs"

 ; using criterium: [criterium "0.4.3"]
 (use 'criterium.core)
 (quick-bench (cosine-similarity ma mb))
 ; 
 ; Execution time mean           : 2.072280 µs
 ; Execution time std-deviation  : 214.653997 ns
 ; Execution time lower quantile : 1.765412 µs ( 2.5%)
 ; Execution time upper quantile : 2.284536 µs (97.5%)
                   Overhead used : 6.128119 ns

第一个版本在500~1000毫秒范围内。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27735980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档