Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Lockfree Queue

5.417 Aufrufe

Veröffentlicht am

Lockfree queue introduction in Japanese.

Veröffentlicht in: Technologie
  • Login to see the comments

Lockfree Queue

  1. 1. Lockfree queue
  2. 2. Lockfree って? <ul><li>線形リスト・スタック・キュー・木といったデータ構造はシングルスレッドでの利用が前提 </li></ul><ul><li>複数スレッドで共有する場合は mutex などでロックするのが一般的 </li></ul><ul><li>共有出来るデータ構造を並行データ構造と呼ぶ </li></ul>
  3. 3. Lockfree って? <ul><li>線形リスト・スタック・キュー・木といったデータ構造はシングルスレッドでの利用が前提 </li></ul><ul><li>複数スレッドで共有する場合は mutex などでロックするのが一般的 </li></ul><ul><li>共有出来るデータ構造を並行データ構造と呼ぶ </li></ul>ロックを用いない並列データ構造を Lockfree データ構造と言う
  4. 4. Lockfree queue は? <ul><li>共有するためにロックを用いないキュー (FIFO バッファともいう ) の事 </li></ul><ul><li>Atomic 操作は TestAndSet 命令に依存 </li></ul><ul><ul><li>比較して一致した場合に代入 を一気に行う命令 </li></ul></ul><ul><ul><li>比較して一致しなかった場合は何も行わない </li></ul></ul><ul><ul><li>CompareAndSet とも言う ( 以後 CAS と表記 ) </li></ul></ul><ul><li>バッファが空の時に deque 操作がブロックするかどうかの話とは無関係 </li></ul>
  5. 5. 基本戦略(1/3) <ul><li>線形リストの queue を実装 </li></ul><ul><li>節点のポインタを CAS で一息に差し替える </li></ul><ul><li>複数の同時 enque も CAS によって直列化 </li></ul>A B C1 C2 C3 CAS CAS CAS
  6. 6. 基本戦略(2/3) <ul><li>結果的に一つの enque だけ成功する </li></ul><ul><li>複数のスレッドが同時に同一の場所を書き換えようとしても破綻しない </li></ul>A B C1 C2 C3 成功 失敗 失敗
  7. 7. 基本戦略(3/3) <ul><li>失敗した残りの enque は更新された末尾ノードをターゲットに再び CAS を実行する </li></ul><ul><li>以後繰り返し </li></ul><ul><li>deque 側の手続きも基本的に同じ戦略 </li></ul>A B C1 C2 C3 CAS CAS
  8. 8. 初期状態 <ul><li>HeadとTailが同一のダミーノードを指す </li></ul>Tail Head Dummy NULL
  9. 9. キューへの挿入(1/5) <ul><li>① Tailのnextに新規ノードを繋げる </li></ul><ul><li>② Tailを更新する </li></ul>Tail Head Dummy New CAS ①
  10. 10. キューへの挿入(2/5) <ul><li>1 ステップ目は更新出来るまで繰り返す </li></ul><ul><li>しかし Tail の更新は失敗しても放置 </li></ul><ul><li>Tail が誰かによって先に更新された場合に失敗 </li></ul>Tail Head Dummy New CAS ← 失敗するかも ②
  11. 11. キューへの挿入(3/5) <ul><li>① だけ終わった状態では下記のようになる </li></ul><ul><li>ここで別のスレッドが enque,deque しにきた場合が問題 </li></ul>Tail Head Dummy New
  12. 12. キューへの挿入(4/5) <ul><li>この場合は後続の enque,deque が訂正操作を行う ( 遅延メソッド ) </li></ul><ul><li>① を行ったスレッドによる Tail 更新はその代わり失敗するが、前述の通り放置 </li></ul>Tail Head Dummy New CAS
  13. 13. キューへの挿入(5/5) <ul><li>1ステップ目の操作のみを線形化ポイントとする事で並列性を高めている </li></ul>Tail Head Dummy New
  14. 14. キューからの取り出し(1/5) <ul><li>①   Head の指している物の Next( つまり A) を確保 </li></ul><ul><li>②   Head を CAS ですげ替える ( 失敗したら①から ) </li></ul><ul><li>③  確保しておいた物を結果として返す </li></ul>Tail Head A B Dummy A ①
  15. 15. キューからの取り出し(2/5) <ul><li>①   Head の指している物の Next( つまり A) を確保 </li></ul><ul><li>②   Head を CAS ですげ替える ( 失敗したら①から ) </li></ul><ul><li>③  確保しておいた物を結果として返す </li></ul>Tail Head A B A が deque される CAS A ② ③
  16. 16. キューからの取り出し(3/5) <ul><li>Aを保持していたノードが次のDummyになる </li></ul><ul><li>(自動的にそうなる </li></ul>Tail Head Dummy B
  17. 17. キューからの取り出し(4/5) <ul><li>保持するノードが 1 つだけになった場合に Head と Tail が同一のノードを指す場合がある。 </li></ul><ul><li>具体的には enque 操作の①の CAS が完了した瞬間 </li></ul>Tail Head Dummy A
  18. 18. キューからの取り出し(5/5) <ul><li>その場合は Tail を CAS にて更新させてからやり直す </li></ul><ul><li>よって Head が Tail を追い越すことは起こり得ない </li></ul>Tail Head Dummy A CAS
  19. 19. まとめ <ul><li>CompareAndSet を使って複数のスレッドが共有する FIFO を作る事ができます </li></ul><ul><li>ソースコードは github に上げました </li></ul><ul><li>デュアルコア環境 (AthlonX2 5000+) では mutex でロックして共有した std::queue より遅かったです… </li></ul><ul><li>ABA 問題とリソースのプールと GC が登場する LockfreeQueue の話は希望が有れば </li></ul>

×