Frage

Ich versuche, eine schnelle / effiziente Implementierung Mandelbrots in Ruby zu machen. Ein lange lange her, eine Möglichkeit, es zu beschleunigen, wurde Fixpunkt ganze Zahlen anstelle von Schwimmern.

Also ich folgendes Ziel gemacht, den Vergleich Float und Integer-Anhebung auf ein Quadrat, mit Multiplikation oder quadratisch ** Operanden.

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

und dies erzeugt die folgende Ausgabe:

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)

, die eindeutig die die Fixnum Multiplikation zeigt fast doppelt so langsam wie Punkt schweben.

Ich habe zwei Fragen:

  • Kann mir jemand das erklären? Ein Grund kann ich mir vorstellen, dass Fixnum Multiplikation wegen der internen Kontrolle langsamer ist, ob es zu einem Bignum umgewandelt werden muss.
  • zweitens ist es als eine schnelle Integer-Multiplikation für Ruby?
War es hilfreich?

Lösung

1.8.6 ist nur langsamer in diesem Bereich. 1.8.7 tut ein wenig besser und 1.9.1 tut noch besser. Ich konnte nicht sagen, warum, aber rvm stimmt mit Ihnen und Pavel, dass 1.8.6 seltsam langsam ist.

1.8.6: 
Rehearsal ------------------------------------------------
float-multip   0.140000   0.000000   0.140000 (  0.141560)
float-square   0.150000   0.000000   0.150000 (  0.146286)
int-multip     0.220000   0.000000   0.220000 (  0.223255)
int-multip     0.180000   0.000000   0.180000 (  0.183850)
--------------------------------------- total: 0.690000sec

1.8.7:
Rehearsal ------------------------------------------------
float-multip   0.090000   0.000000   0.090000 (  0.092346)
float-square   0.080000   0.000000   0.080000 (  0.080335)
int-multip     0.070000   0.000000   0.070000 (  0.068012)
int-multip     0.080000   0.000000   0.080000 (  0.081713)
--------------------------------------- total: 0.320000sec

1.9.1:
Rehearsal ------------------------------------------------
float-multip   0.070000   0.000000   0.070000 (  0.065532)
float-square   0.080000   0.000000   0.080000 (  0.081620)
int-multip     0.060000   0.000000   0.060000 (  0.065371)
int-multip     0.070000   0.000000   0.070000 (  0.065761)
--------------------------------------- total: 0.280000sec

Andere Tipps

Ein paar Dinge in den Sinn kommen. Sie nicht angeben, welche Ruby-Implementierung Sie verwenden. Da Sie Ruby-1.8.6 unter Windows laufen, ich gehe davon aus, dass Sie MRT verwenden über den Windows installiert One-Click-Installer.

Dies ist eine Art von einem Worst-Case-Szenario:

  1. Die MRT ist die langsamste von allen Ruby-Implementierungen
  2. MRT unter Windows ist noch langsamer als MRI unter Linux oder OSX
  3. Die One-Click-Installer die vorkompilierte Binaries von Ruby-Lang.Org verwendet, die mit Microsoft Visual C ++ 6.0 kompiliert werden, von 1996, und somit sind noch langsamer als MRI unter Windows kompilieren mit Microsoft Visual C ++ 10.0 oder GCC 4.x oder sogar GCC 3.x.

Hier ein paar Tipps, die Sie könnten versuchen, die Leistung zu verbessern:

  • verwenden, um die RubyInstaller Projekt, das Dolmetscher kompiliert mit GCC 3.x verwendet statt MSVC6,
  • vielleicht neu kompiliert den Interpreten selbst (es ist nicht so schwer, mit den Rakefiles zur Verfügung gestellt von dem RubyInstaller Projekt ) mit GCC 4.x und / oder verschiedenen Optimierungsoptionen (RubyInstaller mit moderaten Optimierungsmöglichkeiten und für generischen 386 CPUs kompiliert wird)
  • verwenden, um eine neuere Version von MRI als 1.8.6,
  • eine andere Implementierung von Ruby verwenden:

    • YARV ist deutlich schneller als MRI (leider nur implementiert Ruby 1.9, so dass Sie Ihren Code ändern könnte müssen),
    • JRuby ist deutlich schneller als YARV in vielen Szenarien, und es implementiert sowohl Ruby 1.8 und Ruby 1.9 ( es hat auch eine -fast Kommandozeilenoption, die mit Ruby-leicht nicht kompatibel ist, aber die Leistung verbessert, einschließlich Rechenleistung) und
    • IronRuby auch schneller sein könnten als YARV, je nach Auslastung.

In den letzten beiden Fällen Sie möchten Ihre Benchmarks ein wenig revidieren. Beide schließlich kann Ruby-Code zu nativen Maschinencode kompilieren, aber es könnte eine Weile dauern. JRuby zum Beispiel compiliert zu JVM-Bytecode nach einer Methode 20-mal und HotSpot Server kompiliert JVM-Bytecode nativen Maschinencode ausgeführt wurde, nachdem es 20000 mal ausgeführt wird. Auch Kompilation selbst braucht Zeit, so das Programm braucht eine Weile zu laufen, dass die Kosten durch eine verbesserte Leistung zurück zu gewinnen.

Insbesondere Charles Oliver Nutter, einer der JRuby führenden Entwickler, sagte, dass je nach Auslastung, JRuby auf 5-15 Sekunden dauern könnte auf volle Geschwindigkeit zu. Ihre Benchmarks sind etwa 100x zu schnell (hier ist ein Satz, den Sie nicht jeden Tag hören ...).

Ich kann nicht Ihre Tabellen erklären. Aber ich kann meine erklären (Rubin 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)

Whoops. Integer-Multiplikation Beats Gleitkomma Einsen.

Da Ihr Prozessor 5-mal langsamer als meine (I erhöhte die Anzahl der Wiederholungen in Ihrer Benchmark in zehn mal), es ist etwas nicht rubin betroffen sein muss.

** Betrieb wahrscheinlich verwendet Gleitkomma-Arithmetik (exp (x * ln (2)), so dass es so langsam wie andere Gleitkommaoperationen.

jruby kann schnelle Arithmetik (oder 1.9.x) auch in C tun (ex: http : //segment7.net/projects/ruby/inline_optimization.html ) Geschwindigkeiten offensichtlich helfen würde,

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top