ruby - ruby 中的快速/快速整数乘法?

标签 ruby multiplication mandelbrot

我正尝试在 Ruby 中快速/高效地实现 Mandelbrot。很久很久以前,一种加快速度的方法是使用定点整数而不是 float 。

所以我做了以下基准测试,使用乘法或平方 ** 操作数将 float 和整数提升到平方数进行比较。

require 'benchmark'

Benchmark.bmbm(10) do |x|  
  x.report("float-multip") do
    for z in 0..100000 
      zf = z.to_f
      y = zf*zf
    end
  end  

  x.report("float-square") do
    for z in 0..100000 
      zf = z.to_f
      y = zf**2
    end
  end  

  x.report("int-multip") do
    zo = 0
    for zi in 0..100000 
      y2 = zo*zo
      zo += 1
    end
  end   

  x.report("int-multip") do
    for zi in 0..100000 
      y2 = zi**2
    end
  end  
end

这会生成以下输出:

Rehearsal ------------------------------------------------
float-multip   0.125000   0.000000   0.125000 (  0.125000)
float-square   0.125000   0.000000   0.125000 (  0.125000)
int-multip     0.250000   0.000000   0.250000 (  0.250000)
int-multip     0.282000   0.000000   0.282000 (  0.282000)
--------------------------------------- total: 0.782000sec

                   user     system      total        real
float-multip   0.110000   0.000000   0.110000 (  0.110000)
float-square   0.125000   0.000000   0.125000 (  0.125000)
int-multip     0.219000   0.016000   0.235000 (  0.235000)
int-multip     0.265000   0.015000   0.280000 (  0.282000)

这清楚地表明 Fixnum 乘法几乎是 float 的两倍。

我有两个问题:

  • 谁能解释一下?我可以想象的一个原因是 Fixnum 乘法比较慢,因为内部检查它是否需要转换为 Bignum。
  • 其次,是否有 ruby​​ 的快速整数乘法?

最佳答案

我想到了一些事情。您没有指定正在使用的 Ruby 实现。由于您在 Windows 上运行 Ruby 1.8.6,我假设您使用的是通过 Windows 一键安装程序安装的 MRI。

这是一种最坏的情况:

  1. MRI 是所有 Ruby 实现中最慢的
  2. Windows 上的 MRI 甚至比 Linux 或 OSX 上的 MRI 慢
  3. 一键安装程序使用来自 Ruby-Lang.Org 的预编译二进制文件,这些二进制文件是使用 1996 年的 Microsoft Visual C++ 6.0 编译的,因此比使用 Windows 编译的 MRI 甚至慢 Microsoft Visual C++ 10.0 或 GCC 4.x 甚至 GCC 3.x。

这里有一些您可以尝试提高性能的提示:

  • 使用RubyInstaller项目,它使用用 GCC 3.x 而不是 MSVC6 编译的解释器,
  • 也许自己重新编译解释器(使用 RubyInstaller 项目提供的 Rakefile 并不难),使用 GCC 4.x 和/或不同的优化选项(RubyInstaller 使用适度的优化选项编译,适用于通用 386 CPU),
  • 使用比 1.8.6 更新的 MRI 版本,
  • 使用不同的 Ruby 实现:

    • YARV 比 MRI 快得多(不幸的是,它只实现了 Ruby 1.9,因此您可能需要更改代码),
    • JRuby在很多场景下明显比 YARV 快,并且它同时实现了 Ruby 1.8 和 Ruby 1.9(它还有一个 -fast 命令行选项,它与 Ruby 稍微不兼容,但是提高了性能,包括算法性能)和
    • IronRuby也可能比 YARV 更快,具体取决于工作量。

在后两种情况下,您可能需要稍微修改一下基准。两者最终都可以将 Ruby 代码编译为 native 机器代码,但这可能需要一段时间。例如,JRuby 在方法执行 20 次后编译为 JVM 字节码,HotSpot Server 在执行 20000 次后将 JVM 字节码编译为 native 机器码。此外,编译本身需要时间,因此程序需要运行一段时间才能通过提高性能来收回成本。

JRuby 的主要开发人员之一查尔斯·奥利弗·纳特 (Charles Oliver Nutter) 特别指出,根据工作负载,JRuby 可能需要 5-15 秒才能达到全速。您的基准测试速度大约快了 100 倍(这是您每天都不会听到的一句话......)。

关于ruby - ruby 中的快速/快速整数乘法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1791902/

相关文章:

java - ruby 将多个csv文件中的表数据合并到一个csv文件中

arrays - Ruby 二维数组到 csv?

javascript - 如何乘以包含自然值和货币的字段?

java - 使用BufferedImage绘制Mandelbrot集,只得到纯色

ruby-on-rails - 如何模拟 Rails::configuration

c++ - 为什么我的 for 循环应该找到数组中所有值的乘积,却一直告诉我每个数组值?

algorithm - 大于或等于目标的数的倍数之和,优化

c++ - c++ 中的线程不会在 mandelbrot 图像处理上产生加速

openmp - 使用 openMP 的曼德尔布罗

ruby - 将嵌套哈希转换为 Ruby 中以点分隔的字符串的一行代码?