【问题标题】:faster Fixnum multiplication in ruby?ruby中更快的Fixnum乘法?
【发布时间】:2012-08-22 21:44:20
【问题描述】:

使用 ruby​​ 1.9.2p290(2011-07-09 修订版 32553)[x86_64-linux]

我已经做了很多分析,我注意到 ruby​​ Fixnum 乘法真的很慢。

通过一些分析,我了解到这是(部分)因为对 Fixnum#* 的每次调用都涉及对 Kernel#kind_of 的 6 次调用

我知道您可以编写 C 扩展,但这些乘法分布在整个代码中。那么,有没有办法在 Ruby 中避免这种开销?

谢谢

【问题讨论】:

  • 这很有趣。你用什么来分析代码?我会猜到原生 Ruby 乘法是相对有效的。
  • @BlakeTaylor 我正在使用 ruby​​-prof

标签: ruby performance multiplication


【解决方案1】:

我严重怀疑这些测量结果是否准确,原因如下:

  1. 您没有说明您使用的是哪个 Ruby 实现,但 ruby-prof 是一个 Ruby 分析器。它分析 Ruby 代码。我不知道Fixnum#* 是Ruby 代码在哪里的Ruby 实现。在 MRI、YARV、MRuby 和 tinyrb 中是 C 代码,在 Rubinius 中是 C++ 代码,在 MacRuby 中是 Objective-C 代码,在 JRuby 和 XRuby 中是 Java 代码,在 RubyGoLightly 中是 Go 代码,在 IronRuby 和 Ruby 中。 NET 是 C# 代码,在 MagLev 和 SmallRuby 中是 Smalltalk 代码,在 Cardinal 中是 PASM 代码。 ruby-prof 可以分析 Ruby 代码,它不能分析 C、C++、Objective-C、Java、C#、Go、Smalltalk 或 PASM。只有红宝石。因此,它只是无法配置Fixnum#*

  2. Fixnum#* 无需多次检查类。它知道self 是一个Fixnum,因为否则调用不会首先被分派到Fixnum#* 方法,所以它只需要检查参数。它还需要检查结果是否适合Fixnum,但它会在内部完成,而不是通过调用kind_of?(事实上,这甚至没有意义:为了能够要在乘法的结果上调用方法,它首先必须构造结果对象,并且为了构造结果对象,它必须知道它是否适合Fixnum)。

  3. 它不会通过调用 kind_of? 并遍历整个 Ruby 方法查找和方法分派机制来进行类检查。它是 Ruby 实现的内部函数,它可以访问所有私有的内部实现细节,它只会直接检查类或调用一些内部解释器函数,而不是 Ruby 方法kind_of?

  4. 我在各种流行的 Ruby 实现中检查了 Fixnum#* 的实现,但没有发现 任何kind_of? 的调用。不幸的是,您没有说明您使用的是哪个 Ruby 实现。

【讨论】:

  • 感谢您的回复。我肯定是错的。这是我看到的分析器输出:23.52% 9.49% 5.17 2.08 0.00 3.08 808533 Fixnum#*2.27 2.27 0.00 0.00 4851198/5355534 Kernel#kind_of?我不确定您是否熟悉 ruby​​-prof 图形输出,但方法名称下方的行是从该方法调用的方法。我不知道我正在使用什么实现。它要么是 Ubuntu 自带的,要么是我从 apt-get 获得的。你知道我怎么知道吗?
  • 你是对的,顺便说一句。如果您对发生的事情感到好奇,请参阅我的回答。
【解决方案2】:

好吧,我想我想通了。我正在使用 GSL 库,它似乎使用您可以在此处看到的代码修补了 Fixnum#*:https://github.com/romanbsd/rb-gsl/blob/master/lib/gsl/oper.rb#L15

此代码包括...等待它... 6 调用 Kernel#kind_of?在一个大的“或”声明中。

我不会假装完全理解它的工作原理或发生原因,但代码路径与分析器输出完美匹配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-10
    • 1970-01-01
    • 1970-01-01
    • 2010-10-17
    • 2011-05-31
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    相关资源
    最近更新 更多