5

私はRubyで迅速/効率的なマンデルブロ実装を作成しようとしています。ずっと前に、それをスピードアップする1つの方法は、浮動小数点数の代わりに固定小数点整数を使用することでした。

そこで、乗算または二乗**オペランドを使用して、浮動小数点と整数の累乗を二乗と比較して、次のベンチマークを作成しました。

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の乗算が浮動小数点のほぼ2倍遅いことを明確に示しています。

2つの質問があります:

  • 誰かがこれを説明できますか?私が想像できる理由は、Fixnumの乗算は、Bignumに変換する必要があるかどうかを内部でチェックするために遅いためです。
  • 第二に、ルビーの簡単な整数乗算よりもありますか?
4

4 に答える 4

5

いくつかのことが頭に浮かびます。使用しているRuby実装を指定しません。WindowsでRuby1.8.6を実行しているので、Windowsワンクリックインストーラーを介してインストールされたMRIを使用していると仮定します。

これは一種の最悪のシナリオです。

  1. MRIはすべてのRuby実装の中で最も遅いです
  2. WindowsのMRIは、LinuxまたはOSXのMRIよりもさらに低速です。
  3. ワンクリックインストーラーは、1996年のMicrosoft Visual C ++ 6.0でコンパイルされたRuby-Lang.Orgのコンパイル済みバイナリを使用するため、Microsoft Visual C++10.0またはGCC4.xでコンパイルされたWindowsのMRIよりもさらに低速です。 GCC3.xですら。

パフォーマンスを向上させるためのヒントをいくつか紹介します。

  • MSVC6の代わりにGCC3.xでコンパイルされたインタープリターを使用するRubyInstallerプロジェクトを使用します。
  • おそらく、GCC 4.xおよび/またはさまざまな最適化オプション(RubyInstallerは中程度の最適化オプションと汎用386 CPU用にコンパイルされます)を使用して、インタープリターを自分で再コンパイルします( RubyInstallerプロジェクトによって提供されるRakefilesではそれほど難しくありません)。
  • 1.8.6よりも新しいバージョンのMRIを使用します。
  • Rubyの別の実装を使用します。

    • YARVはMRIよりも大幅に高速です(残念ながら、Ruby 1.9のみを実装しているため、コードを変更する必要がある場合があります)。
    • JRubyは、多くのシナリオでYARVよりも大幅に高速であり、Ruby1.8とRuby1.9の両方を実装しています(-fastコマンドラインオプションもあり、Rubyとは少し互換性がありませんが、算術パフォーマンスを含むパフォーマンスが向上します)。
    • ワークロードによっては、IronRubyの方がYARVよりも高速な場合もあります。

後者の2つのケースでは、ベンチマークを少し修正することをお勧めします。どちらも最終的にRubyコードをネイティブマシンコードにコンパイルできますが、時間がかかる場合があります。たとえば、JRubyはメソッドが20回実行された後にJVMバイトコードにコンパイルされ、HotSpotServerは20000回実行された後にJVMバイトコードをネイティブマシンコードにコンパイルします。また、コンパイル自体には時間がかかるため、パフォーマンスを向上させてそのコストを取り戻すには、プログラムをしばらく実行する必要があります。

特に、JRubyのリード開発者の1人であるCharles Oliver Nutterは、ワークロードによっては、JRubyがフルスピードに達するまでに最大5〜15秒かかる可能性があると述べています。あなたのベンチマークは約100倍速すぎます(これはあなたが毎日聞いていない文です...)。

于 2009-11-25T02:42:12.377 に答える
3

1.8.6は、この領域では遅いです。1.8.7は少し良くなり、1.9.1はさらに良くなります。理由はわかりませんが、rvmは1.8.6が奇妙に遅いとあなたとPavelに同意します。

1.8.6:
リハーサル------------------------------------------------
float-multip 0.140000 0.000000 0.140000(0.141560)
フロートスクエア0.1500000.0000000.150000(0.146286)
int-multip 0.220000 0.000000 0.220000(0.223255)
int-multip 0.180000 0.000000 0.180000(0.183850)
---------------------------------------合計:0.690000秒

1.8.7:
リハーサル------------------------------------------------
float-multip 0.090000 0.000000 0.090000(0.092346)
フロートスクエア0.0800000.0000000.080000(0.080335)
int-multip 0.070000 0.000000 0.070000(0.068012)
int-multip 0.080000 0.000000 0.080000(0.081713)
---------------------------------------合計:0.320000秒

1.9.1:
リハーサル------------------------------------------------
float-multip 0.070000 0.000000 0.070000(0.065532)
フロートスクエア0.0800000.0000000.080000(0.081620)
int-multip 0.060000 0.000000 0.060000(0.065371)
int-multip 0.070000 0.000000 0.070000(0.065761)
---------------------------------------合計:0.280000秒
于 2009-11-24T21:02:30.220 に答える
0

私はあなたのテーブルを説明することはできません。しかし、私は私のことを説明することができます(ルビー1.8.7):

                   user     system      total        real
float-multip   0.600000   0.000000   0.600000 (  0.612311)
float-square   0.650000   0.000000   0.650000 (  0.649399)
int-multip     0.450000   0.010000   0.460000 (  0.457004)
int-multip     0.690000   0.000000   0.690000 (  0.692879)

おっと。整数の乗算は浮動小数点の乗算よりも優れています。

あなたのプロセッサは私のものより5倍遅いので(私はあなたのベンチマークの繰り返しの数を10倍に増やしました)、ルビーに関係のない何かがあるに違いありません。

**操作はおそらく浮動小数点演算(exp(x * ln(2))を使用したため、他の浮動小数点操作と同じくらい低速です。

于 2009-11-24T18:29:12.933 に答える
0

jrubyは、C(例: http://segment7.net/projects/ruby/inline_optimization.html)でも実行するより高速な演算(または1.9.x)を備えている可能性があり、明らかに速度を向上させるのに役立ちます

于 2011-04-14T17:32:25.027 に答える