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

nat*_*vda 5 ruby multiplication mandelbrot

我试图在Ruby中快速/高效地实现Mandelbrot.很久很久以前,加速它的一种方法是使用定点整数而不是浮点数.

所以我做了以下基准测试,使用乘法或平方**操作数将浮点数和整数提升比较为平方.

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
Run Code Online (Sandbox Code Playgroud)

这会生成以下输出:

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)
Run Code Online (Sandbox Code Playgroud)

这清楚地表明Fixnum乘法几乎是浮点数的两倍.

我有两个问题:

  • 有谁能解释一下?我能想象的一个原因是Fixnum乘法因内部检查是否需要转换为Bignum而变慢.
  • 其次是ruby的快速整数乘法?

Jör*_*tag 5

有几件事情浮现在脑海中.您没有指定您正在使用的Ruby实现.由于您在Windows上运行Ruby 1.8.6,我将假设您使用通过Windows One-Click安装程序安装的MRI.

这是一种最糟糕的情况:

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

以下是您可以尝试提高性能的几个提示:

  • 使用RubyInstaller项目,它使用用GCC 3.x而不是MSVC6编译的解释器,
  • 或许可以自己重新编译解释器(使用RubyInstaller项目提供的Rakefiles并不难)使用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代码编译为本机机器代码,但可能需要一段时间.例如,JRuby在方法执行20次后编译为JVM字节码,HotSpot Server在执行20000次后将JVM字节码编译为本机机器码.此外,编译本身需要时间,因此程序需要运行一段时间才能通过提高性能来获得成本.

特别是,JRuby首席开发人员之一Charles Oliver Nutter表示,根据工作量的不同,JRuby可能需要5-15秒才能提升到全速.你的基准测试速度大约是100倍(这是你每天都听不到的句子......).


Chu*_*ose 3

1.8.6 在这方面只是速度较慢。1.8.7 做得更好一点,1.9.1 做得更好。我无法说出为什么,但 rvm 同意你和 Pavel 的观点,即 1.8.6 异常慢。

1.8.6:
排练------------------------------------------------
浮点数乘法 0.140000 0.000000 0.140000 ( 0.141560)
浮点平方 0.150000 0.000000 0.150000 ( 0.146286)
整数倍 0.220000 0.000000 0.220000 ( 0.223255)
整数倍 0.180000 0.000000 0.180000 ( 0.183850)
--------------------------------------- 总计:0.690000秒

1.8.7:
排练------------------------------------------------
浮点数乘法 0.090000 0.000000 0.090000 ( 0.092346)
浮点平方 0.080000 0.000000 0.080000 ( 0.080335)
整数倍 0.070000 0.000000 0.070000 ( 0.068012)
整数倍 0.080000 0.000000 0.080000 ( 0.081713)
--------------------------------------- 总计:0.320000秒

1.9.1:
排练------------------------------------------------
浮点数乘法 0.070000 0.000000 0.070000 ( 0.065532)
浮点平方 0.080000 0.000000 0.080000 ( 0.081620)
整数倍 0.060000 0.000000 0.060000 ( 0.065371)
整数倍 0.070000 0.000000 0.070000 ( 0.065761)
--------------------------------------- 总计:0.280000秒