問題タブ [ioref]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
haskell - IORef を共有する場合、atomicModifyIORef で書き込んでいる限り、readIORef で読み取っても安全ですか?
IORef
複数のスレッド間で共有し、atomicModifyIORef
それに書き込むために使用する場合:
プレーンオールドで値を読み取っても安全readIORef
ですか? または、変更readIORef
後に別のスレッドで古い値を返す可能性はありatomicModifyIORef
ますか?
それがドキュメントが意味することだと思います:
atomicModifyIORef は、並べ替えに対するバリアとして機能します。複数のatomicModifyIORef操作は、厳密なプログラム順序で発生します。atomicModifyIORef は、以前の (プログラムの順序で) IORef 操作の前、または後の IORef 操作の後に発生することはありません。
確認したいだけです。
haskell - 可変共有状態: いつ IORef を使用するか
Map と PSQ に書き込むメイン スレッドがあります。Map と PSQ の両方で同じキーを使用するので、PSQ を見ることで最小優先度のエントリが O(1) の複雑さで見つかり、Map の値にマップされます。
ここで、メイン スレッドが必要に応じてマップと PSQ の両方を追加/変更する一方で、常に ( forever $ do
) PSQ を調べて、最も古いキーが N ミリ秒前であることを判断し、それをフラッシュすることになっている 2 つ目のスレッドがあります。
これを行うには、両方のスレッドが同じ変更可能なデータを参照する必要があります。ここで状態を維持するための最良の方法は何ですか? これは IOREfs のケースでしょうか? これを解決するために他にどのような方法が考えられるでしょうか?
ここに「いくつかの」プレアルファコード:
haskell - 単純な IORef を使用した Haskell の同時実行性?
私は Haskell の同時実行性、特に についていくつか質問してTVar
きましたが、TVar
.
代わりに、私はこの解決策を提案しました。
(1) プログラム内のすべての共有データを 1 つのデータ構造にラップし、それをIORef
. (2) を使用して変更を行うだけですatomicModifyIORef
。
これにより、デッドロックとライブロックの両方が防止されると思います (一方、TVar は前者のみを防止します)。また、atomicModifyIORef
別のサンクをチェーンにリンクするだけなので (これは 2 つのポインター操作です)、これはボトルネックではありません。データに対する実際の操作はすべて、相互に依存しない限り、並行して実行できます。Haskell ランタイム システムがこれを解決します。
ただ、これは単純すぎる気がします。私が見逃した「落とし穴」はありますか?
haskell - Haskell: 並列 `atomicModifyIORef` 実装の試行
私が理解していることから、IORef
s への変更は非常に迅速であり、サンクポインターを更新するだけです。もちろん、読者 (つまり、自分の Web ページで値を確認したい人) は、時間をかけてこれらのサンクを評価する必要があります (ライターが結果を読み戻していない場合、サンクが蓄積される可能性があります)。
IORef
多くの状況では、いずれにせよ何らかの時点で評価する必要があるためです (明らかに、これは無限のデータ構造で壊れます) 。
そこで、 と同様のシグネチャを使用して、次の関数を作成しましたatomicModifyIORef
。
これはうまくいくようです(テストコードはこちら)。ここで何か間違ったことはありますか?または、これを行うより良い方法はありますか?
編集:2回目の試み
以下のカールの回答に触発されました。実際に に格納force newdata
しますIORef
。これはとにかく同じnewdata
ですが、後で保持したいランタイムを示しているforce newdata
ため、スパークのガベージ コレクションは行われません。
performance - Haskell:同時データ構造ガイドライン
私は並行性を理解しようとしてきました。そして、1つの大きなIORef
ロック、または多くTVar
のロックのどちらが優れているかを理解しようとしています。私は以下のガイドラインに到達しました。これらが大まかに正しいかどうか、または私が要点を見逃したかどうかについて、コメントをいただければ幸いです。
同時データ構造がマップm
であり、のようにアクセスされると仮定しましょうm[i]
。f_easy
また、2つの関数があるとしましょうf_hard
。はf_easy
速く、f_hard
時間がかかります。f_easy/f_hard
の引数はの要素であると想定しますm
。
(1)トランザクションがおおよそこのように見える場合は、 withをm[f_easy(...)] = f_hard(...)
使用します。怠惰は、サンクで更新されるため、短時間だけロックされるようにします。インデックスを計算すると、構造が効果的にロックされます(何かが更新されるためですが、まだ何がわかりません)が、その要素が何であるかがわかると、構造全体のサンクはその特定の要素のサンクにのみ移動します、そしてその特定の要素のみが「ロック」されます。IORef
atomicModifyIORef
m
(2)トランザクションがおおよそこのようm[f_hard(...)] = f_easy(...)
になり、競合があまり発生しない場合は、をたくさん使用しますTVar
。この場合にを使用するIORef
と、2つのインデックスを同時に計算できないため、アプリが効果的にシングルスレッドになります(構造全体に未解決のサンクが存在するため)。TVar
■2つのインデックスを同時に処理できますが、2つの同時トランザクションが両方とも同じ要素にアクセスし、そのうちの1つが書き込みである場合、1つのトランザクションを破棄する必要があり、時間が無駄になります(他の場所で使用)。これが頻繁に発生する場合は、(ブラックホールを介して)から来るロックを使用した方がよい場合がありますが、IORef
あまり発生しない場合は、TVar
sを使用した方が並列処理が向上します。
基本的に(2)の場合、IORef
100%の効率(無駄な作業なし)が得られる可能性がありますが、1.1スレッドのみを使用しTVar
ますが、競合の数が少ない場合は、80%の効率が得られる可能性がありますが、10スレッドを使用するため、終了します。無駄な作業でも7倍速くなります。
haskell - 純粋なコードでの IORef の回避
Data.UnionFindが IO モナドを使用して、IORef を介してポインターを提供していることに気付きました。unsafePerformIO
データ構造は非常によく理解されているため、純粋なコードでローカルで使用する場合、誰もが喜んで呼び出すと思いますが、..
そのようなデータ構造に対する標準的なよりクリーンなアプローチはありますか? おそらく、unsafePerformIO
ほとんどのIO操作を禁止することで、避けられない「見た目」の危険性を軽減するIOのラッパーですか?
haskell - 可変ツリーを格納するためのhaskellデータ構造
私はhaskellでブラウザを書くことを考えていました。中心的なデータ構造は、ドキュメントを表す可変ツリーになります。完全にiorefで構成されるツリーを使用する以外に、より良い解決策はありますか?
私はこのようなものを避けたいと思っています:(data DomNode = DomNode TagName NodeProperties (IORef DomNode) [IORef DomNode]
タグ、プロパティ、親、子)
問題は、javascriptがツリー内のノードの参照を保持でき、参照先のノードを変更(子の追加、プロパティの変更)したり、親に移動したりできることです。
編集:
ツリーから削除された、またはツリー内で移動されたノードへの参照を保持できるため、何らかの方法で可変状態を使用する必要があることに気付きました。ツリーの構造に基づいたものを介して要素を参照した場合、この参照は無効になります。
haskell - StateT と ReaderT IORef による例外処理
IORef
State モナドを使おうとするよりも、 an にしがみついて例外を通して状態を維持する方がはるかに簡単に思えます。以下に、2 つの代替状態モナドがあります。1 つは を使用StateT
し、もう1 つは を使用しReaderT IORef
ます。はReaderT IORef
、最後の既知の状態で最終ハンドラーを簡単に実行できます。
では、main 関数の最後で、例外がスローされた場合でも State Monad の最後の既存の状態にアクセスできる最終ハンドラーを実行するにはどうすればよいでしょうか? それともReaderT IORef
最適ですか、それともより良い代替手段がありますか?
haskell - STRef または IORef をいつ使用するか?
STRef と IORef の正確な違いは何ですか? また、それぞれをいつ使用するのですか? 私が知る限り、それらは両方とも可変状態のためのものなので、両方が存在する意味は何ですか?