有谁知道如何让这个Haskell代码更快乐?我在做Project Euler #14。 此代码在4.029秒内运行:
collatz :: Int -> Int64 -> Int
collatz c 1 = c
collatz c k
| even k = collatz (c+1) (k `div` 2)
| otherwise = collatz (c+1) (3*k + 1)
main = do
print $ maximum (map (\i -> (collatz 1 i, i)) [1..1000000])
记住collatz函数实际上会增加运行时间,所以我没有做任何memoization。 可比的C代码在0.239秒内运行:
int main(int argc, char *argv[])
{
int maxlength = 0;
int maxstart = 1;
for (int i = 1; i <= 1000000; i++) {
unsigned long k = i;
int length = 1;
while (k > 1) {
length += 1;
if (k % 2 == 0)
k = k / 2;
else
k = 3*k + 1;
}
if (length > maxlength) {
maxlength = length;
maxstart = i;
}
}
printf("%d, %d\n", maxlength, maxstart);
return 0;
}
Haskell代码使用ghc -O3编译,C代码使用gcc -std = c99 -O3编译。
答案 0 :(得分:5)
我注意到这个问题主要是一个转贴。请参阅here。
代码的主要问题是ghc默认不优化整数除法。 要手动修复我的代码,
collatz c k
| k .&. 1 == 0 = collatz (c+1) (k `shiftR` 1)
| otherwise = collatz (c+1) (3*k + 1)
但是,如果计算机上安装了LLVM,则可以使用
编译原始代码ghc -O2 -fllvm code.hs
LLVM进行必要的优化。这两种解决方案都使我的代码运行大约0.420秒,这更接近于可比较的C代码。
答案 1 :(得分:0)
以下是haskell wiki的解决方案:
import Data.Array
import Data.List
import Data.Ord (comparing)
syrs n =
a
where
a = listArray (1,n) $ 0:[1 + syr n x | x <- [2..n]]
syr n x =
if x' <= n then a ! x' else 1 + syr n x'
where
x' = if even x then x `div` 2 else 3 * x + 1
main =
print $ maximumBy (comparing snd) $ assocs $ syrs 1000000
我机器上的计算时间:
haskell|master⚡ ⇒ ghc -O2 prob14_memoize.hs
[1 of 1] Compiling Main ( prob14_memoize.hs, prob14_memoize.o )
Linking prob14_memoize ...
haskell|master⚡ ⇒ time ./prob14_memoize
(837799,524)
./prob14_memoize 0.63s user 0.03s system 99% cpu 0.664 total
与原版相比:
haskell|master⚡ ⇒ ghc -O2 prob14_orig.hs
[1 of 1] Compiling Main ( prob14_orig.hs, prob14_orig.o )
Linking prob14_orig ...
haskell|master⚡ ⇒ time ./prob14_orig
(525,837799)
./prob14_orig 2.77s user 0.01s system 99% cpu 2.777 total