私はHaskellを学んでいて、Cでできる限り速くコードを書こうとしています。この演習では、単純な1次元物理システム用のオイラー積分器を作成しています。
- CコードはGCC4.5.4およびでコンパイルされてい
-O3
ます。1.166秒で実行されます。 - HaskellコードはGHC7.4.1とでコンパイルされてい
-O3
ます。21.3秒で実行されます。 - Haskellをでコンパイルすると、 4.022秒
-O3 -fllvm
で実行されます。
それで、Haskellコードを最適化するための何かが欠けていますか?
PS:私は次の引数を使用しました:1e-8 5
。
Cコード:
#include <stdio.h>
double p, v, a, t;
double func(double t) {
return t * t;
}
void euler(double dt) {
double nt = t + dt;
double na = func(nt);
double nv = v + na * dt;
double np = p + nv * dt;
p = np;
v = nv;
a = na;
t = nt;
}
int main(int argc, char ** argv) {
double dt, limit;
sscanf(argv[1], "%lf", &dt);
sscanf(argv[2], "%lf", &limit);
p = 0.0;
v = 0.0;
a = 0.0;
t = 0.0;
while(t < limit) euler(dt);
printf("%f %f %f %f\n", p, v, a, t);
return 0;
}
Haskellコード:
import System.Environment (getArgs)
data EulerState = EulerState !Double !Double !Double !Double deriving(Show)
type EulerFunction = Double -> Double
main = do
[dt, l] <- fmap (map read) getArgs
print $ runEuler (EulerState 0 0 0 0) (**2) dt l
runEuler :: EulerState -> EulerFunction -> Double -> Double -> EulerState
runEuler s@(EulerState _ _ _ t) f dt limit = let s' = euler s f dt
in case t `compare` limit of
LT -> s' `seq` runEuler s' f dt limit
_ -> s'
euler :: EulerState -> EulerFunction -> Double -> EulerState
euler (EulerState p v a t) f dt = (EulerState p' v' a' t')
where t' = t + dt
a' = f t'
v' = v + a'*dt
p' = p + v'*dt