dbgroup-nagoya-u / pmem-atomic

A utility library for atomic operations in persistent memory.
Apache License 2.0
0 stars 0 forks source link

複数スレッドで記述子を取得したときの動作 #5

Closed manabinohibi closed 2 years ago

manabinohibi commented 2 years ago

複数スレッドで異なる記述子を取得したいが,実際は同じ記述子を取ってきてしまう. 原因はおそらく2つ目以降のスレッドが記述子を取得する前に1つ前のスレッドが終了しデストラクタによりis_reservedfalseになるから.

なので,各スレッドで取得が完了しても終了しないように待機する必要がある.

  1. 各スレッドは操作が完了したらそのことをメインプロセスに通知する.
  2. 全てのスレッドが操作を完了したことをメインプロセスがわかったらすべてのスレッドを終了させる.

futureとpromiseを使うと良いです.

manabinohibi commented 2 years ago

@baycedar すみません,教えてください. std::futureは値を1つのスレッドからしか受け取れない,であっていますか? そうだとするとstd::futureをスレッド数分用意することになる?と思いましたがそれは違う気がします.

baycedar commented 2 years ago

いえ,それであっています.std::futureは対となるstd::promiseから値を受け取るので,複数のスレッドからstd::futureを受け取るには複数のstd::promiseが必要になります.これの152-162行目と179-183行目がマルチスレッドでの使い方の例になるかと思います.

manabinohibi commented 2 years ago

ありがとうございます. メインプロセスを止めておく役割はstd::shared_lockが担っているのでしょうか?

manabinohibi commented 2 years ago

各スレッドがロックを取るのでメインプロセスがロックを取ろうとすると取れずにストップする,みたいな感じですかね.

baycedar commented 2 years ago

そうですね,ロックでメインプロセスを止めています.このコードは今見ると割りと雑にやっている(1ms待てばワーカスレッドの誰かはロックを取っているだろうという曖昧な想定)のですが,ちゃんとやるなら各スレッドに2つのstd::promiseを渡して,1つを同期用(ワーカ準備完了の通知),もう1つを返り値用にするべきでしょうね.

この辺の同期は実際はグローバル変数を使ってもできます(std::atomic_bool are_ready[kThreadNum]みたいな配列を用意すればいける)が,それをやろうとするとメインプロセスで配列を走査してfalseがいたらsleepみたいな処理を書く必要があって,std::promisestd::futureはちょうどその機能を標準ライブラリ側で提供してくれている感じですね.

manabinohibi commented 2 years ago

ありがとうございます.あげていただいたソースコードを真似ていたらよくわからぬままテスト通りました(?).

std::condition_variableで各スレッドを待機させているんだと思いますが,これがあるならfutureいらないのでは?となったのですが,どう違うんでしょう? 今回のケースはstd::condition_variableを使うまでもないんでしょうか.

baycedar commented 2 years ago

std::condition_variableは,ロックによる処理同期の標準実装ですね.内部的にやってることはグローバルロックでスレッドを同期しているだけで,1点違うのはスレッドの開始タイミングをnotifyである程度操作できるところです.単にロックで止めるだけだといつスレッドが再開するかはカーネルしだいなので再開のタイミングにラグが生まれるのですが,こちらを使えばそのラグを多少減らせ(ると信じて使って)ます.なお,基本的にある単一のスレッドから他の1つ以上のスレッドに対してnotifyを送るような使い方になる点には注意してください.

(どんなテストをしてたかだいぶ記憶があやふやですが)今回のテストでも確かワーカスレッドをロックで待たせていたと思うので,メインスレッドからワーカスレッドを再開させる際にはstd::condition_variableが使えると思います.それはそれとして,ワーカスレッドからメインスレッドに向けて情報を送る場合はstd::promisestd::futureも必要になります.

manabinohibi commented 2 years ago

どうもありがとうございます. std::promisestd::futureが無くても通ったので,一度見てもらってもいいでしょうか. レビュー投げます.

同時に問題点も見つけたので,それもそちらで相談します.