2013-03-18 10 views
14

GHCIは、対話セッション中に関数の結果をキャッシュするようです。気付くのは簡単ですが、時間のかかる機能を2回呼び出すだけです。 2回目には、すぐに結果が表示されます。ghciの関数結果キャッシュをクリアするには?

GHCI内からこのキャッシュを消去する方法はありますか?再起動する必要はありませんか?私はいくつかの詳細なパフォーマンスの比較をquick'n'dirtyしているので、代わりにSystem.CPUTimeを使用することは過度の作業です。

+2

キャッシュされた特定の関数呼び出しの例を挙げてください。 – dave4420

+0

'' let f = 1:map(2 *)f''を実行してから '' last $ show $ f !! 200000''。最初はマシンで約15秒かかりますが、2回目にすぐに計算されます。 – user42179

+6

これは機能ではありません。 –

答えて

4

コメント注意点として、あなたは関数を適用した結果である名前をバインドするletを使用しています。値を保持したい場合は、letに名前を付けないでください! (または、letですでに計算した値を参照しないでください)。

+0

これは必ずしも単純ではありません。例えば、提供されるOPの例は再帰的なものなので、 'fix'がなければ' let 'を定義するのが難しいです。 – amindfv

+5

'let f = foo f'がバインディングを与えます。 'let f = foo f in f'はできません。シンプル! – sclv

13

コマンド:rを使用して、作業中のモジュールをいつでもリロードすることができます。これは、あなたが作ったインタラクティブなバインディングを捨て去ります。それは、ちょうどぶつけているのであれば、必ずしも実用的ではないかもしれません。これは実際にモジュールを使用していない場合にも機能します。

3

GHCiのは、あなたがやりたいはずである、according to the manual+rオプションがあります。

通常、トップレベルの式のいずれかの評価(そうでない場合は のCAFまたは一定のApplicativeフォームとして知られている)ロードされたモジュールであります評価の間に を保持しました。 +rをオンにすると、各評価後に最上位レベルの 式のすべての評価が破棄されます(単一評価ではまだ のままです)。

このオプションは、評価された最上位の式が で大量の領域を消費している場合、または反復可能な のパフォーマンス測定が必要な場合に役立ちます。

ここでは、機能ではなくconstant applicative formsについて説明しています。しかし、私はそれはあなたの例のために働くことを得ることができませんでした:どうやら

Prelude> :set +r 
Prelude> :set +s 
Prelude> let f = 1 : map (2*) f 
(0.01 secs, 1222216 bytes) 
Prelude> last $ show $ f !! 100000 
'6' 
(3.54 secs, 641914476 bytes) 
Prelude> last $ show $ f !! 100000 
'6' 
(0.04 secs, 1634552 bytes) 
Prelude> last $ show $ f !! 100000 
'6' 
(0.04 secs, 1603568 bytes) 

+r only works for compiled codeを、ドキュメントがこれを言及していないのに。

2

未定義を使用して
>>> let f = 1 : map (2*) f 
(0.01 secs, 1543272 bytes) 
>>> :show bindings 
f :: [Integer] = _ 
>>> last $ show $ f !! 50000 
'6' 
(0.55 secs, 170011128 bytes) 
>>> :show bindings 
f :: [Integer] = 1 : 2 : 4 : 8 : 16 : .... 
it :: Char = '6' 
>>> last $ show $ f !! 50000 
'6' 
(0.02 secs, 1562456 bytes) 

>>> :set +s -- activate performance 
>>> :r  -- reset all interactive binding 
Ok, modules loaded: none. 
>>> :show bindings -- check the binding state 

はのテストを始めましょう、要約すると、

>>> let f = undefined 
(0.01 secs, 565912 bytes) 
>>> :show bindings 
it :: Char = '6' 
f :: a = _ 
>>> let f = 1 : map (2*) f 
(0.01 secs, 513304 bytes) 
>>> last $ show $ f !! 50000 
'6' 
(0.94 secs, 170517840 bytes) 
>>> :show bindings 
f :: [Integer] = 1 : 2 : 4 : 8 : 16 : .... 
it :: Char = '6' 

は結合、

>>> :r 
>>> :show bindings 
Ok, modules loaded: none. 
0123をリセットまだキャッシュされた

別studieの場合、

>>> let h = (2*) 
(0.01 secs, 590232 bytes) 
>>> let f = 1 : map h f 
(0.01 secs, 1138792 bytes) 
>>> :show bindings 
it :: Char = '6' 
h :: Integer -> Integer = _ 
f :: [Integer] = _ 
>>> last $ show $ f !! 60000 
'6' 
(1.69 secs, 241802432 bytes) 
>>> last $ show $ f !! 60000 
'6' 
(0.03 secs, 2002432 bytes) 

、見にHの結合を変更、

>>> let h = (3*) 
(0.01 secs, 547208 bytes) 
>>> last $ show $ f !! 60000 
'6' 
(0.03 secs, 2029592 bytes) 
>>> :show bindings 
f :: [Integer] = 1 : 2 : 4 : 8 : 16 : .... 
h :: Integer -> Integer = _ 
it :: Char = '6' 

は関係なく行い、また、Fを再定義する必要があり、

>>> let f = 1 : map h f 
(0.01 secs, 552048 bytes) 
>>> last $ show $ f !! 60000 
'1' 
(4.36 secs, 374064760 bytes) 

>>> let f = let h = (2*) in 1 : map h f 
(0.02 secs, 1068272 bytes) 
>>> last $ show $ f !! 60000 
'6' 
(3.90 secs, 242190168 bytes) 
>>> last $ show $ f !! 60000 
'6' 
(4.89 secs, 242271560 bytes) 
>>> last $ show $ f !! 60000 
'6' 
(5.71 secs, 242196976 bytes) 
>>> :show bindings 
h :: Integer -> Integer = _ 
f :: Num a => [a] = _ 
it :: Char = '6' 
関連する問題