web-dev-qa-db-ja.com

なぜI / Oを待たなければならないのですか?

ディスクの動作が遅いことは常に知られており、動作が遅い理由を知っています。したがって、ここでの質問は、なぜI/Oを待たなければならないのか、なぜIOWaitなどのようなものがあるのか​​ということです。

つまり、バックグラウンドでいくつかのI/Oタスクを実行していると、コンピューターの速度が大幅に低下することに気づきました。特に、Linuxを使用しているときに、より長いI/Oタスクを実行していると、 、OSは完了するまでほとんど使用できなくなります。

確かに、私はこのトピックも記事で見つけました、スニペットがあります:

I/O待機は12.1%です。このサーバーには8つのコアがあります(cat/proc/cpuinfo経由)。これは非常に近い(1/8コア= 0.125)

つまり、基本的には、コンピュータの速度が大幅に低下していることを意味します。なぜですか。つまり、通常のコンピュータは少なくとも2コア、時には4コア、またはハイパースレッディングなどの理由で、より多くのコアを備えている場合があります。しかし、問題はなぜCPUが実際にそこに留まらなければならないのか、実際にはIOを待つ以外に何もしないのですか?プロセス管理の基本的な考え方やアーキテクチャを意味しますが、それを担当しているのがOSなのか、それともハードウェアの部分にあるのかはわかりませんが、CPUが待機したり、他の多くのタスクを実際に実行し、準備ができたときにIOプロセスに戻るだけですが、定期的にチェックしてください。実際、それがそのような困難なタスクであり、CPUが待たなければならない場合は、なぜですか。それはハードウェアによってより効率的に管理されますか?たとえば、プロセスに戻るとすぐに、それを待ってデータの小さな部分を実際のCPUに配信する、ある種のミニCPUがある可能性があります。繰り返され、データコピープロセスのためにCPUコア全体を実質的に専用にする必要はありません...または、この種のものを発明してノーベル賞を受賞するのは私でしょうか:S

さて、私は本当にオブザーバーの観点から実際にそれを置いています、そして私は本当にそのトピックに深く入りませんでした、しかし私は本当にCPUがHDDの速度で動作しなければならない理由を本当に理解していません。別のことをして、準備ができたらHDDに戻ります。アイデアは、IO操作またはコピープロセスなどを必要とするアプリケーションを高速化することではありませんが、その操作の実行中にCPU消費に最小限の影響を与えるだけで、OSが他のプロセスにそれを利用することができ、ユーザーはいくつかのコピー操作を行うときに一般的なコンピュータの遅れを感じる必要はありません...

27
Arturas M

説明しているI/Oスキームは、現在コンピュータで使用されています。

なぜCPUは実際にそこに留まらなければならないのか、実際にはIOを待つ以外に何もしないのですか?

これは最も単純なI/O方法です:プログラムされたI/O。多くの組み込みシステムとロー/エンドマイクロプロセッサには、単一の入力命令と単一の出力命令しかありません。プロセッサは、読み書きされるすべての文字に対して、明示的な一連の命令を実行する必要があります。

しかし、実際には他の多くのタスクを実行し、準備ができたときにIOプロセスに戻るだけですが、CPUが待機または定期的にチェックすることを可能にする必要があります。

多くのパーソナルコンピュータには、他のI/Oスキームがあります。デバイスが準備ができるまでタイトなループで待機する(busy waiting)の代わりに、CPUはI/Oデバイスを起動して、割り込みを生成するように要求します。完了したら(割り込み駆動I/O)。

割り込み駆動型I/Oは(プログラムされたI/Oと比較して)一歩前進ですが、送信されるすべての文字に対して割り込みが必要であり、コストがかかります...

例えば、プロセスに戻るとすぐにそれを待って実際のCPUにデータの小さな部分を配信するようなある種のミニCPUが存在する可能性があるため、プロセスが繰り返されて、データコピープロセスのためにCPUコア全体を実質的に使用する...

多くの問題の解決策は、誰かに仕事をさせることです! :-)

DMAコントローラ/チップ(ダイレクトメモリアクセス))は、プログラムされたI/Oを許可しますが、他の誰かにそれを行わせます!

DMAを使用すると、CPUはいくつかのレジスタを初期化するだけでよく、転送が完了するまで(および割り込みが発生するまで)ほかのことは自由に行えます。

でもDMAは完全に無料ではありません。高速デバイスは、メモリ参照およびデバイス参照に多くのバスサイクルを使用できます(cycle stealing)およびCPUは待機する必要があります(DMAチップは常により高いバス優先度を持っています)。

I/O待機は12.1%です。このサーバーには8つのコアがあります(cat/proc/cpuinfo経由)。これは非常に近い(1/8コア= 0.125)

これは次のようなものだと思います ディスクI/Oについて-いつ心配する必要がありますか?

奇妙なことではありません。システム(mySQL)はデータを操作する前にすべての行をフェッチする必要があり、他のアクティビティはありません。

ここでは、コンピュータアーキテクチャ/ OSの問題はありません。これは、サンプルの設定方法です。

せいぜい、RDBMSチューニングの問題またはSQLクエリの問題(インデックスの欠落、クエリプランの誤り、クエリの誤りなど)である可能性があります。

19
manlio

非同期で書き込むことは可能ですIOここで、OSにディスクの読み取り/書き込みをディスパッチしてから何か他のことを行い、後でそれが完了したかどうかを確認するように指示します。これは新しいことにはほど遠いです。古い方法はIOに別のスレッドを使用します。

ただし、そのためには、その読み取りの実行中に何かを行う必要があり、結果のために渡されたバッファーを変更することはできません。

また、すべてがIOをブロックしていると仮定すると、プログラミングがはるかに簡単になります。

ブロッキング読み取り関数を呼び出すと、knowsomethingになるまで戻りません-)が読み込まれ、すぐに処理を開始できます。

典型的な読み取りループは良い例です

_//variables that the loop uses
char[1024] buffer;
while((read = fread(buffer, 1024, 1, file))>0){
    //use buffer
}
_

それ以外の場合は、現在の関数の状態(通常はコールバック+ userDataポインターの形式)を保存し、それを読み取り操作の識別子+ select()タイプのループに渡す必要があります。そこで操作が完了すると、読み取り操作の識別子をコールバック+データポインターにマップし、完了した操作の情報を使用してコールバックを呼び出します。

_void callback(void* buffer, int result, int fd, void* userData){
    if(result<=0){
    //done, free buffer and continue to normal processing
    }
    //use buffer

    int readID = async_read(fd, buffer, userData->buff_size);
    registerCallback(readId, callback, userData);
}
_

これは、その非同期読み取りを使用してしまう可能性のあるすべての関数が、非同期継続を処理できる必要があることも意味します。これは、ほとんどのプログラムで重要な変更です。非同期C#を試そうとしている人にそれについて尋ねてみてください。


ただし、同期IOと非同期IOは一般的な速度低下の原因ではありません。ページの入れ替えも、IOで待機する必要がある操作です。 IO if if( IO wait is when when the processor isidle andIO操作保留中 )があります。

本当の問題は、ハードドライブとCPUの両方がRAMと通信するために同じチャネルを使用することです;メモリバス。 RAIDを使用していない限り、データを取得するディスクは1つだけです。グラフィックスを多用するアプリケーションも使用している場合、これはさらに悪化し、GPUとの通信も妨害されます。

つまり、実際のボトルネックは、ソフトウェアではなくハードウェアにあると考えられます。

24
ratchet freak

I/Oを待機している間の他の処理は、かなり合理化され、可能な限り合理化されていると確信してください。コンピューターがI/Oを待機している時間が12.1%だけであることがわかる場合、それは実際には他の多くのことを並行して実行していることを意味します。それ以外に何もせずにI/Oを待機する必要がある場合、99.9%の時間待機することになります。これがI/Oの速度の低下です。

より多くのことを並行して行う唯一の方法は、ユーザーが次に何をしたいのかを予測することですが、そのような予測はまだあまり得意ではありません。したがって、ユーザーが特定のセクターをハードドライブから読み取る必要がある操作を実行し、そのセクターがまだキャッシュにない場合、OSはそのセクターを読み取る非常に長いプロセスを開始します。その間に他に何かすることがあるかどうかを確認しようとします。別のセクターを必要とする別のユーザーがいる場合は、その要求もキューに入れます。ある時点で、すべてのリクエストがキューに入れられ、先に進む前に、最初のリクエストが満たされるのを待つしかありません。それは人生の事実です。

編集:

I/Oの実行中に他のことを行う方法の問題の解決策を見つけることは、立派な偉業になるでしょう。それは驚くべき偉業です。なぜなら、コンピューターには何もないのに、コンピューターにできる仕事が見つかるからです。

ご覧のとおり、これが起こっていることです。コンピュータは99.99%の時間だけ座って、何もしていません。あなたが何かをするとき、それは行き、それを行います。その際、I/Oを待機する必要がある場合は、そこに待機します。 I/Oの実行中に他にやるべきことがあれば、それも行います。 ただし、I/O以外に何もすることがない場合は、そこに座って、I/Oが完了するのを待つ必要があります。これ以外に回避する方法はありません。 SETI @ Homeに登録してください。

9
Mike Nakis

OS(非常に低レベルの組み込みシステムまたは同様にエキゾチックなものでない限り)はすでにこれを処理しています:アプリケーションがI/Oを待機する必要がある場合、通常はそのI/Oでブロックされ、他のスレッドまたはアプリケーションがアクティブ。スケジューラはどちらを決定します。

no実行されている可能性のある他のスレッドまたはアプリケーションが実際に待機時間を累積している場合のみです。 引用した記事 (リンクを@manlioに感謝します)の場合:その場合、待機中の12.1%とアイドル状態の87.4%があります。つまり、1つのコアがI/Oの完了を待機しています。残りは何もしていません。そのシステムにやるべきこと、できれば複数のものを与えると、待機率が下がるはずです。

今日のアプリケーション設計の高い目標の1つは、実行中のアプリケーションが1つしかない場合でも、その1つのアプリケーションがいつかI/Oを待機している場合でも、アプリケーションが他の作業を続行できるようにすることです。スレッドはこれに対する1つのアプローチであり、非ブロッキングI/Oですが、待機しているデータなしで実際に何かを実行できるかどうかは、実行している作業の種類に大きく依存します。

linuxを使用しているときに、より長いI/Oタスクを実行している場合、OSは完了するまでほとんど使用できなくなります。

これは通常、I/Oバウンドの状況を示しています。十分なCPU処理を実行できないため、システムが遅くなることはありません。 HDDからのデータに依存しているため、遅い可能性が高いです。これは、実行したいが、実行可能ファイル、ライブラリファイル、アイコン、フォント、その他のリソースをロードする必要があるアプリケーションの場合があります。すでに実行しているが、メモリの一部がスワップアウトされており、続行するには再度スワップインする必要があるアプリケーションの可能性があります。何らかの理由でログファイルに行を書き込む必要があるだけでなく、何らかの要求に応答する前にそのログファイルを実際にフラッシュする必要があると考えるデーモンです。

iotop などのツールを使用して、I/O容量がプロセスにどのように割り当てられているかを確認したり、 ionice でI/O優先順位を設定したりできます。プロセス用。たとえば、デスクトップマシンでは、すべてのバルクデータ処理をidleスケジューリングクラスに分類して、インタラクティブアプリケーションでI/O帯域幅が必要になった瞬間に、インタラクティブアプリケーションが完了するまでバルク処理を一時停止することができます。

6
MvG

それはあなたのアプリケーションコードに依存します。あなたのコードはLinux上で実行されていると思います。

Multi - threading (例:POSIX pthreads )を使用して、他のIOバインドスレッドがIO(そしてそれを待っています)アプリケーションを実行することもできますseveralprocessesプロセス間通信 (IPC)、次を参照 pipe(7)fifo(7)socket(7) 、- nix(7)shm_overview(7)sem_overview(7)mmap(2)eventfd(2) と読み取り Advanced Linux Programming など...

非ブロッキングIO を使用できます。パス O_NOBLOCK to open(2) etc etc ...;次に、 poll(2) および/またはSIGIOsignal(7) ...を使用してEWOULDBLOCKを処理する必要があります read(2) などからのエラー...

POSIX非同期IOを使用できます。 aio(7) を参照してください

ファイルアクセスの場合、 ページキャッシュ にヒントを与えることができます。 madvise(2) の後に mmap(2) および posix_fadvise(2) のあとに; Linux固有の readahead(2) も参照してください

しかし、最終的にはハードウェアのボトルネック(バス、RAMなど)に到達することになります。参照 ionice(1)

私は他のものとは異なる視点を追加します。

Linuxオペレーティングシステムのその典型的な問題。特に遅れる(「Linuxマウスラグ」を検索してください)。 Windowsにはこの問題はありません。デュアルブートのWindows 7とLinux Mintを持っています。 Windowsで集中的なディスク操作を行っている場合でも、Windowsはスムーズでマウスが正常に動いているように感じます。 Linuxでは反対に感じないので、通常のWebブラウジング中でもスムートやマウスが遅れることがあります。

これはおそらく、これら2つのシステムの哲学と歴史が異なるためです。 Windowsは当初から一般ユーザー向けに設計されており、主にグラフィカルなオペレーティングシステムです。また、Windowsユーザーの場合、スムーズでないシステムの動作とマウスの動きの停止は、何か問題があることを示しています。そのため、Microsoftのプログラマは、システム全体が遅いと感じるケースを最小限に抑えるようにシステム全体を設計するために一生懸命に努力しました。反対に、Linuxは最初はグラフィカルシステムではなく、デスクトップはサードパーティの追加にすぎません。また、Linuxは主にコマンドラインを使用するハッカー向けに設計されています。物事を成し遂げる哲学。 Linuxは、スムーズな動作を念頭に置いて設計されているのではなく、感情はここでは重要ではありません。

注:私はWindowsがLinuxよりも優れていると言っているわけではありません。それらは単に全体的な哲学が異なるだけであり、複雑な環境ではこれらのシステムの異なる高レベルの動作/感覚につながる可能性があると言います。

1
user3123061