遅延評価

[id:lethevert:20051123:p5]
昨日の計算は、無駄な計算が多いと思ったので、コードをシンプルにして、もう一度再計算してみた。

module sine

import StdEnv

Start
	= doCalc 0.0 0
where
	calcs = getCalc
	where
		getCalc
			= [calc x \\ x <- [0..]]

	doCalc :: !Real Int -> Real
	doCalc res 10000000
		= res
	doCalc res x
		= doCalc (res + (calcs!!i)) (x+1)
		//= doCalc (res + (calc i)) (x+1)
	where
		i = x rem 4

calc x
	= iter 10 sin ((toReal x) / 1000.0)

計算結果

計算結果を再利用した場合

$ time ./sine.exe
14999.850003575

real    0m0.921s
user    0m0.020s
sys     0m0.030s

毎回、再計算した場合

$ time ./sine.exe
14999.850003575

real    0m27.371s
user    0m0.020s
sys     0m0.030s

今度ははっきりと再利用の影響が分かる。

考察

昨日、再利用した方の計算時間が長かったのは、リストアクセス速度がボトルネックになっていたためのようだ。
ためしに、

i = x rem 4

i = 1000 + (x rem 4)

としてみると、3分たっても、計算が終わらない・・・