17

ディスクに保存された同じファイルから、多くの別個の独立したデータのチャンクを読み取る必要があるとします。

このアップロードをマルチスレッド化することは可能ですか?

関連:同じプロセッサ上のすべてのスレッドが同じIOデバイスを使用してディスクから読み取りますか?この場合、マルチスレッドはアップロードをまったく高速化しません-スレッドはただ並んで待機しているだけです。

(私は現在、OpenMPでマルチスレッド化しています。)

4

5 に答える 5

36

はい、可能です。でも:

同じプロセッサ上のすべてのスレッドが同じIOデバイスを使用してディスクから読み取りますか?

はい。ディスク上の読み取りヘッド。例として、2つのファイルを直列ではなく並列にコピーしてみてください。OSはスケジューリングアルゴリズムを使用してIOレートが「公平」、つまり2つのスレッド/プロセス間で等しいことを確認するため、並列処理にはかなり長い時間がかかります。このため、読み取りヘッドはディスクのさまざまな部分の間を行ったり来たりして、プロセスの速度を大幅に低下させます。実際にデータを読み取る時間は、データを探す時間に比べてかなり短く、ディスクの2つの異なる部分を同時に読み取る場合、ほとんどの時間をシークに費やします。

これはすべて、ハードディスクを使用していることを前提としていることに注意してください。SSDを使用している場合、並行して遅くなることはありませんが、速くなることもありません。編集:コメントによると、SSDの並列処理は実際には高速です。RAIDを使用すると、状況はより複雑になり、(明らかに)使用しているRAIDの種類によって異なります。

これは次のようになります(ASCII円は硬いため、円形のディスクを長方形にラップ解除し、データレイアウトを簡略化して読みやすくしました):

次のように、ファイルがプラッター上のスペースで区切られていると仮定します。

|         |

一連の読み取りは次のようになります(読み取りを*示します)

space ----->
|        *|  t
|        *|  i
|        *|  m
|        *|  e
|        *|  |
|       / |  |
|     /   |  |
|   /     |  V
|  /      |
|*        |
|*        |
|*        |
|*        |

並列読み取りは次のようになりますが

|       \ |
|        *|
|       / |
|     /   |
|   /     |
|  /      |
|*        |
|  \      |
|    \    |
|     \   |
|       \ |
|        *|
|       / |
|     /   |
|   /     |
|  /      |
|*        |
|  \      |
|    \    |
|     \   |
|       \ |
|        *|

于 2012-11-16T18:27:30.643 に答える
8

Windowsでこれを行う場合は、ReadFileScatter関数を調べることをお勧めします。これにより、1回の非同期呼び出しでファイルから複数のセグメントを読み取ることができます。これにより、OSがファイルIOボトルネックをより適切に制御できるようになり、読み取りが最適化されることを期待しています。

Windowsで一致する書き込み呼び出しは、WriteFileGatherになります。

UNIXの場合、同じことを行うためにreadvwritevを見ています。

于 2012-11-16T18:51:06.660 に答える
3

他の回答で述べたように、ファイルがディスクに物理的に保存されている方法によっては、並列読み取りが遅くなる場合があります。したがって、ヘッドがかなりの距離を移動する必要がある場合、実際の速度低下を引き起こす可能性があります。ただし、複数の同時読み取りと書き込みを効率的にサポートできるストレージシステムがあると言われています。私が想像できる最も単純なものはSSDディスクです。私自身、IBMの素晴らしいストレージシステムを使用して、速度を落とすことなく読み取りと書き込みを同時に実行できました。したがって、並列読み取りで速度が低下しないようなファイルシステムと物理ストレージがあると仮定しましょう。

その場合、並列読み取りは非常に論理的です。一般に、これを実現するには2つの方法があります。

  1. 標準のC/C ++ライブラリを使用してIOを実行する場合、唯一のオプションは、スレッドごとに1つの開いているファイルハンドル(記述子)を保持することです。これは、ファイルポインタ(ファイル内のどこから読み取りまたは書き込みを行うかを指す)がハンドルごとに保持されるためです。したがって、同じファイルハンドルから同時に読み取ろうとすると、実際に何を読んでいるかを知る方法がありません。
  2. プラットフォーム固有のAPIを使用して、非同期(OVERLAPPED)IOを実行します。Windowsでは、OVERLAPPEDIOと呼ばれるものでWinAPI関数を使用します。Unix / Linuxには、posix AIOがありますが、その使用が推奨されていないことは理解していますが、その理由について十分な説明はありませんでした。

私自身、LinuxとWindowsの両方にfd / threadアプローチを実装し、WindowsにOVERLAPPEDアプローチを実装しました。どちらもうまく機能します。

于 2012-11-16T19:13:18.957 に答える
1

ディスクへの読み取りプロセスを高速化することはできません。書き込みと同時に計算する場合は、並列化が役立ちます。しかし、純粋な書き込みは、プロセッサとハードドライブの間のレーンの帯域幅によって制限され、特にハードドライブ自体によって制限されます(私のハードドライブは30 MB / sを実行し、120 MB/s以上のRAIDセットアップについて聞いたことがありますネットワークですが、それに依存しないでください)。

于 2012-11-16T17:50:32.377 に答える
0

ディスクからの複数の読み取りは、opシステムの設計によりスレッドセーフである必要があります。標準のシステム機能を使用する場合は、手動でロックする必要はありませんが、ファイルは読み取り専用で開きます。(そうしないと、ファイルアクセスエラーが発生します。)

ところで、実際にはディスクから読み取る必要はありませんが、opシステムがどこからサービスを提供するかを決定します。通常、読み取りをプリフェッチし、メモリから提供します。

于 2012-11-16T18:20:47.983 に答える