元の質問
STMは初めてです。Haskellでやりたいことの1つは、大きなデータと、その大きなデータの小さな部分の読み取りと書き込みを行う多数の軽量スレッドです。読み取りおよび書き込みの場所は、本質的にランダムで小さいと見なすことができます。STMはこれには最適のようですが、問題をどのように攻撃するかについていくつか質問があります。私はいくつかの可能なアプローチを見て、それぞれにいくつかの欠点があり、いくつかは明らかに愚かなようです。これらに関するいくつかのコメント、または代替案に関する他のアイデアをいただければ幸いです。
簡単にするために、大きなデータがData.Vector a
であり、要素自体が小さいと仮定しましょう。
データ全体を1つに
TVar (Vector a)
。STMは、個々の書き込みが共有データ全体に影響を与えている可能性があると考えているため、これにより膨大なデータのコピーが大量に発生すると思います。確かに、読み取りと書き込みが非常にローカライズされていること、および大きなデータ全体での一貫性が必要ないことをSTMが識別する場合、魔法は起こりませんか?大量の
TVar a
s、基本的に各要素に1つ、完全にローカライズされたSTMを提供しますが、基本的に全体を複製しますVector a
。これはばかげているようです。TVar (Vector a)
データのサブベクトルに対応する妥当な数のsが得られるように、データをセグメント化することによる1と2の間の妥協点。このソリューションは、セグメントの大きさなど、ヒューリスティックに大きく依存していると思います。メッセージング。各ワーカーは、STMを使用してデータの読み取りと書き込みを行う代わりに、データの読み取り要求またはデータのチャンクをSTMメカニズムなどのSTMメカニズムを介して書き込むメッセージを書き込みます
TChan
。特別なスレッドがこれらのメッセージを受信し、別のスレッドを介して要求されたデータを渡すTChan
か、受信したデータを取得して共有データ構造に書き込みます。このソリューションは、ソリューション1〜3を悩ませている問題がないように見えますが、データの一貫性を維持するためにSTMの優れた機能を使用することを本質的に諦めているようにも見えます。むしろ、それは単なるメッセージパッシングです。確かに、メッセージパッシング部分はSTMで実装されていますが、私の本当の問題はメッセージパッシングで解決されます。STMはとても素晴らしいようです、メッセージパッシングはとても...まあ。
私はこれについて正しく考えていますか?誰かが何かヒントや他の提案がありますか?
私はSTMの経験がなく、上記の解決策をまだ試したことがないことを覚えておいてください。肘掛け椅子から降りますが、何かを試す前にこれらのことを考えておくとよい場合があります。
補遺: 5番目のアプローチはNathan Howellによるもので、を使用していますTArray
。それは私が望むもののように聞こえますが、ドキュメントには次のように書かれています。
現在、Array ix(TVar e)として実装されていますが、将来、より効率的な実装に置き換えられる可能性があります(ただし、インターフェイスは同じままです)。
私はこれをTArray
、より良い服を着た私のアプローチ2番だと解釈します。「より効率的な」実装について示唆しているドキュメントは、実際にはより優れたアプローチがあることを示唆しているため、興味深いものです。
VagifVerdiの回答のフォローアップ
Vagif Verdiの答えは非常に興味深いので、少し実験して試してみました。今はコードをスリム化する時間がないので、これに興味のある人は、必要不可欠なものだけでなく、コードについても我慢しなければなりません。Int
「大きな共有データ」として10^8秒の可変ベクトルを使用し、複数のリーダー/ライターをネットワークソケットに取り込むスレッドに対応させることにしました。
コードは、共有されたデータの読み取りや書き込みさえも行わないことに注意してください。それは単にそこにあり、各スレッドはそれに保持しTVar
ます。
では、どうなりますか?プログラムを実行すると、すぐに約780 MBのRAMが必要になります。これは、予想されるとおりです(これは、おおよそ10 ^ 8Int
秒に必要な量です)。ここで、netcatを使用していくつかのクライアントを接続し、少しのテキストを書き込むと、プログラムはそれを出力し、共有データには書き込まないことになっています。プロセスのCPU使用率は1秒以上100%に急上昇します。 !!テキストが表示されるまでに顕著な遅延があります。明るい面では、メモリ使用量は一定のままです(Vagif Verdiの回答による)。ベクトルとを削除するとTVar
、つまりすべてのSTMと共有データを削除すると、すべてが非常に高速で応答性が高く、クライアントが何かを書き込んだときにCPU使用率が目立つことはありません。
したがって、共有データが実際に複製されていないことを確認するのは非常に良いことですが(これを完全に検証するには、実際に共有データに書き込む必要があると思いますが)、コヒーレント状態の維持には非常に大きなパフォーマンスの低下が伴います。私にとって、私の質問は残ります。STMの優れた点を維持しながら、この問題を適切に攻撃するにはどうすればよいでしょうか。
いくつかの非常に興味深い点を提起してくれたVagifVerdiに感謝します。