Why is Haskell so slow compared to C for Fibonacci sequence?

本秂侑毒 提交于 2019-12-20 07:46:40

问题


I am just beginner in Haskell. And I writing a code to display the N numbers in the Fibonacci sequence. Here is my code in Haskell,

fib_seq 1 = 1:[]
fib_seq 2 = 1:1:[]
fib_seq n = sum(take 2 (fib_seq (n-1))):fib_seq (n-1)

When I run this code for higher numbers like fib_seq 40 in GHCI, it takes a long time to evaluate it and my computer hangs and I have to interrupt. However, when I write the same exact logic in C, (I just print instead of saving it in the list),

#include<stdio.h>

int fib_seq (int n){
    if(n==1)        return 1;
    else if(n==2)   return 1;
    else            return fib_seq(n-1)+fib_seq(n-2);   }


void print_fib(int n){
    if(n==0)    return;
    else        printf("%i ", fib_seq(n));
                print_fib(n-1);     }

int main(int argn, char* argc){
    print_fib(40);
    return 0;     }

The code is very fast. Takes about 1 second to run when compiled with GCC. Is Haskell supposed to be this slow than C? I have looked up other answers on the internet and they say something about memoization. I am beginning Haskell and I don't know what that means. What I am saying is that the C code and Haskell code I wrote both do the same exact steps and Haskell is so much slower than C, it hangs my GHCI. A 1-2 seconds difference is something I will never worry about, and if C also had taken the same exact time as Haskell, I would also not worry about. But Haskell crashing and C doing it in 1 seconds is unacceptable.


回答1:


The following program, compiled with ghc -O2 test.hs, is +/-2% the speed of the C code you posted, compiled with gcc -O2 test.c.

fib_seq :: Int -> Int
fib_seq 1 = 1
fib_seq 2 = 1
fib_seq n = fib_seq (n-1) + fib_seq (n-2)

main = mapM_ (print . fib_seq) [40,39..1]

Some comments:

  1. Unlike you, I implemented the exact same logic. I doubt this is the real difference, though; see the remaining comments for much more likely causes.
  2. I specified the same types as C uses for the arithmetic. You didn't, which is likely to run into two problems: using Integer instead of Int for largenum arithmetic, and having a class-polymorphic type instead of a monomorphic one adding overhead on every function call.
  3. I compiled. ghci is built to be interactive as quickly as possible, not to produce quick code.
  4. I don't have the right version of llvm installed at the moment, but it will often crunch through heavily-numeric code like this much better than ghc's own codegen. I wouldn't be too surprised if it ended up being faster than gcc.

Of course using one of the many well-known better algorithms for fibonacci is going to trump all this nonsense.




回答2:


Guess what happens if "fib_seq (n-1)" is evaluated twice on each recursion. And then try this:

fib_seq 1 = 1:[]
fib_seq 2 = 1:1:[]
fib_seq n = sum(take 2 f):f
            where f = fib_seq (n-1)


来源:https://stackoverflow.com/questions/42771348/why-is-haskell-so-slow-compared-to-c-for-fibonacci-sequence

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!