【问题标题】:Clojure number crunching performanceClojure 数字运算性能
【发布时间】:2010-06-26 15:11:47
【问题描述】:

我不确定这属于 StackOverflow 还是 Clojure Google 组。不过群里好像在忙着讨论numeric improvements for Clojure 1.2,所以我这里试试:

http://shootout.alioth.debian.org/ 有许多针对各种语言的性能基准。

我注意到 Clojure 不见了,所以我制作了 n-body problem 的 Clojure 版本。

我能够生成的最快代码可以是 found here,并且基准测试似乎是说对于数字处理 Clojure 是

  • 比 Python/Ruby/Perl 快 10 倍
  • 比 C/Java/Scala/Ada 慢约 4 倍
  • 与 OCaml、Erlang 和 Go 大致相当

我对这种水平的表现非常满意。

我对 Clojure 大师的问题是

  • 我是否错过了明显的改进,无论是在速度方面,还是在代码简洁性或可读性方面(不牺牲速度)?
  • 您是否认为这是 Clojure 性能与 Python/Ruby/Perl 和 Java/C 的对比?

更新

更多用于枪战here 的 Clojure 1.1 基准程序,包括 n 体问题。

【问题讨论】:

  • 我不得不想象 JVM 将在这里发挥重要作用。你用的是什么JVM?你用的是和枪战一样的吗?
  • Java 1.6.0,OS X 10.6 附带的标准 java。它大约是相同的 JVM(我:1.6.0_20,枪战:1.6.0_18),但与枪战不同的计算机。我在本地运行 Clojure 和枪战 Java 实现。我通过使用 Java 作为基准并相应地缩放枪战结果来估计相对性能。
  • 您的代码看起来不错。随着 1.2 中的原始改进,我希望您能够非常接近 Java 时代。您是否尝试过通过探查器运行它?我的怀疑是某处增加了对您造成伤害的装箱或函数调用开销。
  • 啊,这是一个很酷的项目,对你提到的当前激烈的辩论做出了巨大贡献。我将等待更深入的答案...我还想知道您的代码在新分支上骑行时会如何运行。可能会试一试——或者你会吗?顺便说一句,所有这些对 ggroup 来说都是绝对感兴趣的,尤其是现在;也许您可以将其发布到我在下面提到的线程中?
  • @mikera:根据分析器,intCast(Object) 大约有 4% 的 CPU,我还无法追踪到。另一个 5% 到 doubleCast(double),它可能会被消除。所以可能会提高约 10%。除此之外,分析器没有显示任何容易获得的成果。

标签: performance clojure benchmarking


【解决方案1】:

这里没有大量的回复 :) 但显然有些兴趣,所以我将尝试用过去几天学到的知识来回答我自己的问题:

  • 使用 1.1 优化方法(Java 原语和可变数组)比优化后的 Java 慢约 4 倍。
  • 1.2 构造 definterfacedeftype速度是 Java 的两倍以上,与 1.1 相比,代码更短、更简单、更简洁,是 Java 的约 1.7 倍 (+70%)。

以下是实现:

More details 包括“经验教训”、JVM 版本和分析截图。

从主观上来说,优化 1.2 代码与优化 1.1 相比是轻而易举的事,所以这对于 Clojure 数字处理来说是个好消息。 (实际上接近惊人:)

1.2 测试使用当前的 master 分支,我没有尝试任何新的数字分支。从我能收集到的目前正在讨论的新想法中

  • 可能会使未优化的数值更快
  • 可能会加快此基准的 1.1 版本
  • 可能不会加速 1.2 版本,它已经尽可能“接近金属”了。

免责声明:

  • Clojure 1.2 尚未发布,因此 1.2 基准测试结果是初步的。
  • 这是物理计算的一项特殊基准。它与浮点数运算有关,但与字符串解析、并发或 Web 请求处理等领域的性能无关。

【讨论】:

  • 您应该尝试使用数字分支,查看您的代码,我发现您会在 1.2 主分支下不必要地获得拳击。
  • 感谢您的提示。 equiv 分支对 1.1 版本有一些影响,对于 1.2 版本没有明显差异。可能存在差异更显着的替代实现。 equiv 分支看起来仍然不错,尤其是原始类型提示和 :static。
  • 非常感谢您非常有趣的贡献。我特别喜欢阅读详细的分析。我编译了 1.2 版本,并在几次运行中将它与 Java 示例进行了比较,它平均只慢了 1.5 倍。我提出了两个问题。正如您在分析中所述,代码不是惯用的,因为它使用了可变变量。如果使用不可变变量,代码的执行速度会慢多少?并行化可变或不可变版本需要多少努力?
  • 谢谢,很高兴你喜欢它。 1.5x:听起来不错,我们在彼此的球场上。可变与不可变:我还没有尝试过不可变,请随意尝试。我希望介于“可变 1.2”和“可变 1.1”之间,但很难猜测。并行化:这个特殊问题在任何情况下都很难并行化。一般来说,使用可变值的多线程比使用不可变值要困难得多,这也是 Clojure 默认为不可变的部分原因。
  • 顺便说一句:这是一个涉及并发性和日志文件解析的更大基准测试的 Clojure 实现:meshy.org/2009/12/13/widefinder-2-with-clojure.html 如果您喜欢大规模性能,那么值得一读。
【解决方案2】:

我想知道Cantor 是否对您有用——它是 Clojure 的高性能数学库。另请参阅 Google 小组上的 this thread,这是关于新原始算术内容背景下的类似项目。

【讨论】:

  • 康托尔看起来很有用,我去看看。谢谢!
【解决方案3】:

这是一个有点老的问题,现有的答案有些过时了,所以我想为那些对 Clojure 中的“数字运算”感兴趣的人添加一个截至 2013 年年中的更新

Clojure 数值计算领域发生了很多事情:

  • Clojure 1.5 现已发布,它对数值运算有很多改进的支持。在大多数情况下,现在可以非常接近纯 Java 速度
  • 专门的新闻组 - Numerical Clojure
  • core.matrix 现在为矩阵数学/数值计算提供惯用 API,支持多种后端实现(包括本机 BLAS 库)

免责声明:我是上述几项的维护者/贡献者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-03
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多