49

GHC は複数のスレッド (明示的なスレッド、またはスパークを評価する内部スレッド) によってアクセスされるサンクをどのように処理しますか? 複数のスレッドが同じサンクを評価し、作業が重複することはありえますか? または、サンクが同期されている場合、パフォーマンスが低下しないようにするにはどうすればよいでしょうか?

4

3 に答える 3

22

コメントでリンクされている記事を要約すると: GHC のサンクは複数のスレッド間で厳密に原子的ではありません: 競合状態で複数のスレッドが同じサンクを評価し、作業が重複する可能性があります。しかし、これは実際には大したことではありません。

  1. 純粋性が保証されているということは、サンクが 2 回評価されるかどうかは、プログラムのセマンティクスの観点から問題にならないことを意味します。unsafePerformIOそれが問題になる可能性があるケースですがunsafePerformIO、同じ IO アクションの再実行を避けるように注意していることがわかりました。
  2. すべての値がサンクであるため、ほとんどのサンクは非常に小さいことがわかります。そのため、ときどき作業を複製して 1 つのサンクを強制することは、プログラム速度の点で大したことではありません。たとえば、last [1,2..10000000]その計算全体が高価であるため、複製には費用がかかると想像するかもしれません。しかし、もちろん、最も外側のサンクは別のサンクに解決されます。たとえば、次のようになります。

    case [1,2..10000000] of 
      [x] -> x
      (_:xs) -> last xs
      [] -> error "empty list"
    

    そして、2 つのスレッドが作業を複製して への呼び出しをlastの使用に変える場合case、それは物事の壮大な計画においてかなり安上がりです。

于 2015-08-12T19:40:16.353 に答える