2011-01-02 5 views
29

Haskellで 'seq'または 'pseq'と 'par'が必要なのはなぜですか?私たちは、標準的なサンプルコードのすべての部分を必要とする理由を理解しようとしてい

a `par` b `pseq` a+b 

はなぜ以下は十分ではないのだろうか?

a `par` b `par` a+b 

上記の式は、非常にわかりやすいようだ:並列にabの両方を評価してみて、結果a+bを返します。効率の理由だけです:2回目のバージョンは1回ではなく2回発火しますか?

次の、より簡潔なバージョンはどうですか?

a `par` a+b 

なぜ我々はbがオリジナル、標準のコードのようにa+b前に評価されていることを確認する必要があるでしょうか?

答えて

29

要約するとhttp://community.haskell.org/~simonmar/papers/threadscope.pdf

a `par` b `par` a+b 

a `par` a+b 

評価の順序付けの欠如があるとの問題:私は、以下の論文は私の質問に答えると思います。どちらのバージョンでも、メインスレッドは即座に評価を開始したものを評価するためにスレッドを開始する必要がなくなるため、即座にスパークが発生し、a(または時にはb)で動作します。

オリジナルバージョン

a `par` b `pseq` a+b 

は、メインスレッドがa+bb上で動作します(または他の代わりにa評価を開始しているだろう)ので、用スレッドに実体化するスパークaのための機会を与え、確実に並行評価。

+6

これは正しいですし、 'seq'がこの問題には不十分な理由も説明しています。 'seq'は評価の順序付けを保証しません。 'seq b(a + b)'では、主スレッドは '(a + b)'が評価されるときに 'b'がWHNFにある限り、' b'の前に 'a'を評価することができます。 –

+2

私はその引数が 'par a(par b(a + b)) 'の問題をどのように記述しているのかわかりません - 確かに' a'か 'b'のどちらかがすぐに評価され、他のスパークは非常に生きていて、並列性を生み出すはずです。もちろん、スパークの作成は、これを実行する最も効率的な方法ではないかもしれませんが、それは動作し、評価則の質問をコンパイラに任せます。 – gereeter

+0

'par a(a + b)'の場合、実行時に 'b'が最初に選択された場合でも、' 'ラッキー ''の並列化が可能です。それから、 'a'火花が爆発することはありません。これはPDF:community.haskell.org/~simonmar/papers/threadscope.pdf(2ページ)に記載されています。 – CMCDragonkai

16
a `par` b `par` a+b 

はい、並列にaとbを評価し、+ Bを返します。

しかし、PSEQA + Bされる前 AとBの両方が評価されることを保証します。

このトピックの詳細については、this linkを参照してください。

6

a `par` b `par` a+bab両方に対して火花を作成しますが、a+bは(すなわち、それはメインスレッドで評価される)ので、スパークの一つが不首尾であろう直ちに到達します。この問題は効率が悪く、不必要なスパークが発生したためです。これを使用して並列割り算&を征服すれば、オーバーヘッドによってスピードアップが制限されます。

a `par` a+bは、単一のスパークを作成するだけなので、より良いようです。しかしながら、の前にaを評価しようとすると、aのためにスパークが鳴り、bはスパークを持たないので、a+bの逐次評価になります。順序をb+aに切り替えるとこの問題は解決しますが、コードとしては順序が強制されず、Haskellはそれをまだa+bと評価できます。

したがって、を評価する前に、a `par` b `pseq` a+bをメインスレッドでbの評価を強制するようにします。これにより、aが実現してからa+bと評価され、不要なスパークは作成されませんでした。

関連する問題