31

Linuxで非同期ファイルI/Oを実行するための最も効率的な方法を探しています。

POSIX glibc実装は、ユーザーランドのスレッドを使用します。

ネイティブのaioカーネルAPIはバッファリングされていない操作でのみ機能し、バッファリングされた操作のサポートを追加するカーネルのパッチが存在しますが、それらは3年以上前のものであり、メインラインに統合することを誰も気にしないようです。

非同期I/Oを可能にする他のアイデア、概念、パッチをたくさん見つけましたが、それらのほとんどは3年以上前の記事にあります。今日のカーネルで実際に利用できるのは何ですか?サーブレット、呼び出し、カーネルスレッドを含むものなど、今は覚えていないことについても読んだことがあります。

今日のカーネルでバッファリングされた非同期ファイルの入出力を行う最も効率的な方法は何ですか?

4

4 に答える 4

34

独自のIOスレッドプールを作成する場合を除いて、glibcの実装は許容できるソリューションです。実際には、完全にユーザーランドで実行されるものに対しては驚くほどうまく機能します。

私の経験では、カーネルの実装はバッファリングされたIOではまったく機能しません(他の人が反対のことを言うのを見たことがありますが!)。DMAを介して大量のデータを読み取りたい場合はこれで問題ありませんが、もちろん、バッファキャッシュを利用する場合は、かなりの時間がかかります。
また、カーネルAIO呼び出しが実際にブロックされる可能性があることにも注意してください。サイズに制限のあるコマンドバッファがあり、大きな読み取りはいくつかの小さな読み取りに分割されます。キューがいっぱいになると、非同期コマンドが同期的に実行されます。サプライズ。私は1、2年前にこの問題に遭遇し、説明を見つけることができませんでした。周りに尋ねると、「もちろん、それがどのように機能するか」という答えが得られました。
私が理解したことから、バッファリングされたaioをサポートすることへの「公式の」関心も、何年にもわたっていくつかの実用的なソリューションが利用可能であるように見えますが、それほど大きくはありません。私が読んだ議論のいくつかは、「とにかくバッファを使いたくない」、「誰もそれを必要としない」、「ほとんどの人はまだepollを使っていない」というものでした。だから、まあ...まあ。

完了した非同期操作によってシグナルを受け取ることができることはepoll、最近まで別の問題でしたが、それまでの間、これはを介して非常にうまく機能しeventfdます。

glibcの実装は、実際には内でオンデマンドでスレッドを生成する__aio_enqueue_requestことに注意してください。スレッドの生成はそれほど高価ではなくなったので、おそらく大したことではありませんが、注意する必要があります。非同期操作の開始についての理解が「すぐに戻る」である場合、最初にいくつかのスレッドを生成する可能性があるため、その仮定は正しくない可能性があります。

編集
補足として、Windowsでは、非同期操作をキューに入れるという「すぐに戻る」という仮定が当てはまらない、glibcAIO実装の状況と非常によく似た状況が存在します。
読み取りたいすべてのデータがバッファキャッシュにある場合、Windowsは代わりに要求を同期的に実行することを決定します、とにかくすぐに終了するので。これは十分に文書化されており、確かに素晴らしいと思います。コピーする数メガバイトがある場合、または別のスレッドにページフォールトがある場合、またはIOを同時に実行する場合(したがって、ロックを競合する場合)を除いて、「すぐに」は驚くほど長い時間になる可能性があります。 -5ミリ秒。これはほとんどの状況で問題ありませんが、たとえば、16.66msのフレーム時間の制約の下では、ランダムな時間に5msの間ブロックするリスクを冒したくないでしょう。したがって、「非同期はブロックしないので、レンダリングスレッドから非同期IOを実行できる」という素朴な仮定には欠陥があります。

于 2011-04-14T14:18:55.927 に答える
4

材料は古いように見えます-まあ、それ古いです-それは長い間存在していて、決して些細なことではありませんが、よく理解されているからです。あなたが持ち上げることができる解決策は、W。リチャードスティーブンスの見事で比類のない本(「聖書」を読んでください)に掲載されています。この本は、明確で、簡潔で、完全な珍しい宝物です。すべてのページが、真の即時の価値を提供します。

    UNIX環境での高度なプログラミング

同じくスティーブンスによる他の2つのそのようなものは、彼のUnixネットワークプログラミングコレクションの最初の2巻です。

   ボリューム1:Sockets Networking API (FennerおよびRudoffを使用)および
   ボリューム2:プロセス間通信

これらの3冊の基本的な本がないことは想像できません。彼らのことを聞いたことがない人を見つけたとき、私は呆然としました。

スティーブンの本のさらに多くは、同じように貴重です:

   TCP / IP Illustrated、Vol。1:プロトコル

于 2011-04-14T16:19:43.687 に答える
2

申し訳ありませんが、O_DIRECTも使用しない限り、非同期ファイルI/OのLinuxカーネル実装は実際には使用できないと思います。

世界の現在の状態に関する詳細情報は、https ://github.com/littledan/linux-aioにあります。これは、Googleで働いていた人によって2012年に更新されました。

于 2013-02-08T03:58:22.910 に答える
2

(2021)Linuxカーネルが十分に新しい場合(少なくとも5.1ですが、新しいカーネルは改善をもたらします)、io_uring「非同期ファイル入出力を行うための最も効率的な方法」になります *。これは、バッファ付きI/Oと直接I/Oの両方に当てはまります。

KernelRecipes2019のビデオ「FasterIOthroughio_uring」では、io_uring著者のJens Axboeio_uringが、同期バッファI/Oのほぼ半分の時間で終了することでバッファI/Oを示しています。@Marenzが指摘したように、 Linux AIO(別名/ )には常にバッファリングされた非同期I / Oを実行する機能がないio_uringため、ユーザースペーススレッドがバッファリングされた非同期I/Oを実行する唯一の方法です...libaioio_submit()

さらに、「最新のストレージは十分に高速です」という記事にあります。Glauber Costaはio_uring、非同期直接I / Oをio_uring注意深く使用すると、Optaneデバイスで非同期バッファI/Oを使用する場合と比較してスループットが向上することを示しています。Glauberにはユーザースペースの先読み実装が必要でしたが(これがないと、バッファードI / Oが明らかに勝者でした)、その改善は目覚ましいものでした。


*この回答のコンテキストは、明らかにストレージに関連しています(バッファリングされた単語がすべて言及された後)。ネットワークの場合、I / Oio_uringは後のカーネルで着実に改善されており、打撃を次のようなものepoll()と交換できます。それが続くと、いつの日かすべての場合で同等かそれ以上になります。

于 2021-04-11T06:19:06.577 に答える