Warum ist Haskell schneller als C ++ für einen einfachen Fibonacci?

8

In der Regel sind Fragen im Haskell-Tag, warum Haskell so langsam im Vergleich zu X ist. Meistens können Sie das an die Verwendung von String anstatt Text oder ByteString binden. Nicht-strenge Bewertung oder Fehlen von Typ-Signaturen.

Aber hier habe ich einen einfachen Fibonacci-Rechner, der C ++ um etwa den Faktor 2 übertrifft. Das könnte entweder ein Mangel an C ++ - Wissen sein - aber ich habe den Code von einem Freund bekommen, der mehr als nur ein bisschen programmiert hat diese Sprache.

%Vor%

In der Haskell-Datei habe ich einfach eine strikte zipWith' und eine strikte add' -Funktion verwendet (hier wird die Erweiterung BangPatterns verwendet - es teilt dem Compiler lediglich mit, die Argumente x /% co_de auszuwerten % vor dem Hinzufügen) und eine explizite Typ-Signatur hinzufügen.

Beide Versionen verwenden bigint, das scheint mir vergleichbar zu sein, auch der C ++ - Code verwendet nicht die "Standard" -Recursion, die eine exponentielle Laufzeit hat, sondern eine Memo-Version, die sich gut verhalten sollte (zumindest denke ich das) - Bitte korrigieren Sie mich, wenn ich falsch liege.)

Das verwendete Setup ist:

  • Linux 64-bit (Mint) auf einem ziemlich neuen Laptop
  • ghc-7.10.3
  • g ++ 4.8.4 + libgmp-dev 2: 5.1.3 + dfsg-1ubuntu1

y

%Vor%

fib.cc

%Vor%     
epsilonhalbe 22.06.2016, 00:12
quelle

1 Antwort

9

Angesichts der wirklich großen Zahl, die Sie drucken, könnte die schlechte Standardleistung von Iostreams etwas damit zu tun haben. In der Tat, auf meinem System, setzen

%Vor%

am Anfang von main verbesserte die Zeit geringfügig (von 20 Sekunden auf 18).

Auch das Kopieren um die riesigen Zahlen wird so sehr verlangsamt. Wenn Sie stattdessen sowohl p1 als auch p2 in jedem Schritt aktualisieren, müssen Sie sie nicht kopieren. Sie brauchen auch nur halb so viele Schritte in der Schleife. So:

%Vor%

Dies beschleunigt mein System dramatisch (von 18 Sekunden auf 8).

Natürlich, um wirklich zu sehen, wie schnell es mit GMP gemacht werden kann, sollten Sie einfach die Funktion verwenden, die das tut:

%Vor%

Dies ist effektiv sofort auf meinem Gerät (und ja, es druckt die gleiche 208,989-stellige Nummer, die die anderen beiden Methoden tun).

    
Kundor 22.06.2016, 00:55
quelle

Tags und Links