1. ホーム
  2. multithreading

[解決済み] ノンブロッキングI/Oは、マルチスレッドのブロッキングI/Oより本当に速いのか?どのように?

2022-06-22 13:23:11

質問

ブロッキング I/O とノンブロッキング I/O についての技術的な詳細をウェブで検索したところ、ノンブロッキング I/O はブロッキング I/O よりも高速であると述べている人が何人かいました。たとえば このドキュメント .

ブロッキングI/Oを使うと、当然ながら現在ブロックされているスレッドは他のことができない...。だってブロックされてるんだから。しかし、スレッドがブロックされ始めるとすぐに、OSは他のスレッドに切り替えることができ、ブロックされたスレッドに何かできることがあるまで、切り替えを戻さない。つまり、システム上に CPU を必要とする別のスレッドがあり、ブロックされていない限り、イベント ベースのノンブロッキング アプローチと比較して、CPU アイドル時間が増加することはないはずですよね?

CPU がアイドルである時間を短縮する以外に、コンピューターが与えられた時間枠の中で実行できるタスクの数を増やすために、もう 1 つのオプションがあると思います。それは、スレッドを切り替えることによって生じるオーバーヘッドを削減することです。しかし、これはどのように行うのでしょうか? また、そのオーバーヘッドは、測定可能な効果を示すのに十分な大きさなのでしょうか?ここでは、それがどのように機能するかについて、私が想像できるアイデアを紹介します。

  1. ファイルのコンテンツを読み込むために、アプリケーションはこのタスクをイベント ベースの I/O フレームワークに委ね、ファイル名と一緒にコールバック関数を渡します。
  2. イベント フレームワークはオペレーティング システムに委任し、オペレーティング システムはハード ディスクの DMA コントローラーをプログラムして、ファイルをメモリに直接書き込むようにします。
  3. イベントフレームワークは、さらなるコードの実行を可能にします。
  4. ディスクからメモリへのコピーが完了すると、DMA コントローラーは割り込みを発生させます。
  5. オペレーティング システムの割り込みハンドラーは、ファイルが完全にメモリに読み込まれたことをイベント ベースの I/O フレームワークに通知します。これはどのように行われるのでしょうか? シグナルを使用するのですか?
  6. イベント I/o フレームワーク内で現在実行されているコードが終了します。
  7. イベントベースi/oフレームワークはそのキューをチェックし、ステップ5からのオペレーティングシステムのメッセージを見て、ステップ1で取得したコールバックを実行します。

そのように動作するのでしょうか?そうでない場合、どのように動作するのでしょうか?つまり、イベント システムは、明示的にスタックに触れる必要なしに動作できるということですか (スレッドの切り替え中にスタックをバックアップして別のスレッドのスタックをメモリにコピーする必要がある実際のスケジューラーのようなもの)?これによって、実際にどれくらいの時間が節約できるのでしょうか?それ以上のことがあるのでしょうか?

どのように解決するのですか?

ノンブロッキングまたは非同期 I/O の最大の利点は、スレッドが並行して作業を継続できることです。もちろん、追加のスレッドを使用してこれを達成することもできます。全体的な (システムの) パフォーマンスを向上させるには、複数のスレッドではなく非同期 I/O を使用するほうがよいでしょう (したがって、スレッド スイッチングを減らすことができます)。

並列に接続された1000のクライアントを処理するネットワークサーバープログラムの可能な実装を見てみましょう。

  1. 1 つの接続につき 1 つのスレッド (ブロッキング I/O ですが、ノンブロッキング I/O も可能です)。

    各スレッドはメモリ資源(カーネルメモリも!)を必要とする、これは欠点である。また、スレッドを追加するごとにスケジューラーの仕事が増えることになります。
  2. すべての接続に対して 1 つのスレッドを使用します。

    これは、スレッドの数が少ないので、システムの負荷を軽減します。しかし、1 つのプロセッサを 100% に駆動し、他のすべてのプロセッサをアイドル状態にすることになる可能性があるため、マシンの性能をフルに発揮できなくなる可能性もあります。
  3. 各スレッドが接続の一部を処理する少数のスレッド。

    スレッドの数が少ないので、システムからの負荷が軽減されます。また、利用可能なすべてのプロセッサを使用することができます。Windows では、このアプローチは スレッドプール API .

もちろん、より多くのスレッドを持つことは、それ自体問題ではありません。お気づきかもしれませんが、私はかなり多くの接続/スレッドを選択しました。わずか 12 個のスレッドについて話している場合、3 つの可能な実装の間に違いがあるとは思えません (これは、MSDN ブログの投稿で Raymond Chen が提案していることでもあります)。 Windows には 1 プロセスあたり 2000 スレッドという制限があるのですか? ).

を使用している Windows では 非バッファードファイルI/O を使用することは、書き込みがページ サイズの倍数のサイズでなければならないことを意味します。私はテストしていませんが、バッファ付き同期および非同期書き込みの書き込みパフォーマンスにもプラスの影響を与える可能性があるようです。

あなたが説明したステップ 1 から 7 は、それがどのように機能するかについての良いアイデアを与えてくれます。Windows では、オペレーティング システムは非同期 I/O の完了を通知します ( WriteFileOVERLAPPED 構造を持つ) イベントまたはコールバックを使用します。コールバック関数は、例えば、コードが WaitForMultipleObjectsExbAlertable に設定されています。 true .

ウェブでもう少し読んでみる。