Об улучшении производительности Haskell по сравнению с C в микро-тесте Фибоначчи

Я наткнулся на этот вопрос , в котором сравнивалась производительность различных компиляторов при вычислении чисел Фибоначи простым способом .

Я попытался сделать это с помощью Haskell, чтобы посмотреть, как он соотносится с C.

Код C:

#include 
#include 

int fib (int n) {
  if (n < 2) return 1;
  return fib (n-1) + fib (n-2);
}

int main (int argc, char* argv[]) {
  printf ("%i\n", fib (atoi(argv[1])));
  return 0;
}

Результат:

> gcc -O3 main.c -o fib
> time ./fib 40
165580141
real    0m0.421s
user    0m0.420s
sys 0m0.000s

Haskell:

module Main where
import System.Environment (getArgs)

fib :: Int -> Int
fib n | n < 2 = 1
      | otherwise = fib (n-1) + fib (n-2)

main = getArgs >>= print . fib . read . head

Результат:

> ghc -O3 -fllvm -optlo-O3 Main.hs -o fib
> time ./fib 40
165580141
real    0m1.476s
user    0m1.476s
sys 0m0.000s

Профилирование с помощью

> ghc -O3 -fllvm -optlo-O3 -prof -auto-all -caf-all -rtsopts Main.hs -fforce-recomp -o fib
> ./fib 40 +RTS -prof

показывает, что fib занимает 100% времени и памяти, что неудивительно. Я взял некоторый профиль кучи, но не знаю, что они подразумевают:

> ./fib 40 +RTS -hc

enter image description here

> ./fib 40 +RTS -hd

enter image description here

Итак, мой вопрос: могу ли я что-нибудь сделать со своей стороны, чтобы производительность этой программы на Haskell была ближе к C, или это просто способ GHC делает ли происходящее медленнее в этом микро-тесте? (Я не прошу асимптотически более быстрый алгоритм вычисления выдумок.)

Большое спасибо.

[EDIT]

Оказалось, что в этом случае ghc -O3 был быстрее, чем ghc -O3 -fllvm -optlo-O3 . Но размещение optlo-block дало заметную разницу для бэкэнда LLVM:

> ghc -O3 Main.hs -o fib -fforce-recomp
> time ./fib 40
165580141
real    0m1.283s
user    0m1.284s
sys 0m0.000s

> ghc -O3 -fllvm -optlo-O3 -o fib -fforce-recomp
> time ./fib 40
165580141
real    0m1.449s
user    0m1.448s
sys 0m0.000s

> ghc -O3 -fllvm -optlo-O3 -optlo-block-placement -o fib -fforce-recomp
> time ./fib 40
165580141
real    0m1.112s
user    0m1.096s
sys 0m0.016s

Причина, по которой я хотел исследовать это, заключалась в том, что и C, и OCaml были значительно быстрее, чем Haskell для этой программы. Я как бы не мог с этим согласиться и хотел узнать больше, чтобы убедиться, что я уже сделал все, что мог: D

> ocamlopt main.ml -o fib
> time ./fib 40
165580141
real    0m0.668s
user    0m0.660s
sys 0m0.008s

14
задан Community 23 May 2017 в 12:26
поделиться