java - Clojure 性能优化与等效 Java

标签 java performance clojure

加速此功能的最佳简单方法是什么?根据 Criterium,Java 中的等效代码快了近 50 倍。

我敢打赌,如果我使用 java 数组并减少装箱量,这都会有所帮助,但我想我应该先在这里发帖,看看我是否犯了任何可以轻松修复的基本错误。注意我已经为 Clojure 指出了 (double...),这极大地提高了性能,但仍然不像 Java。我还首先在函数内使用 (double-array...) 而不是使用 (vec ...) 转换了 seq,这也提高了性能,但同样,与 Java 不同。

(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 都是 seq,每个包含 200 个 Double。在 java 版本中,它们作为 double[] args 传递。

最佳答案

使用 (double 0) 不会带来直接指定 0.0( double 文字)无法获得的性能优势。

如果您将 mamb 作为 double-array 传递,并将参数提示为 double,您将获得显着更好的性能,不要通过vec将它们转换为 vector ,并使用aget来进行元素查找。这应该会让您获得非常接近 Java 代码性能的结果。

如果您使用 double 组作为函数参数,则不需要 let block 内的 double 调用。

最终结果应该如下所示:

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

关于java - Clojure 性能优化与等效 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27735980/

相关文章:

android - 将边距设置为抽屉导航的默认分隔线

optimization - Hadoop计数器-调整和优化

java - 将数字放在算法的效率上

java - 字段方法在带有多个子 block 的 let 中不起作用

java - 减少相同异常的记录

java - Kafka connect 是否为 Cassandra 提供 java 驱动程序

Mac 上针对 Java6 的 JavaFX 构建

clojure - try 和 catch 可以在不同的(但嵌套的)宏中吗?

intellij-idea - 如何在 IntelliJ 中调试 Clojure 文件?

java - 如何运行 pom.xml 中定义的依赖项的 buildr (buildr + eclipse + maven : integration)