0

私の最初のアプリケーションのプロトタイプでは、ハードディスクから約400,000個のファイル(各4KBファイル、約合計1.5 GBのデータ)を順番に読み取り、各ファイルから読み取ったデータに対して何らかの操作を行い、結果をRAMに保存する必要があります。このメカニズムにより、最初にファイルのI / Oにアクセスし、次にCPUを使用して操作し、別のファイルを探し続けていましたが、プロセスが非常に遅くなりました。

回避策として、最初にすべてのファイルを読み取り、すべてのファイルデータをRAMに保存してから、操作(CPUを使用)を実行します。大幅な改善が見られました。

しかし、開発の第2フェーズでは、20 GBのデータを読み取る必要があり、RAMに保存できなくなりました。また、CPU使用率を伴う単一読み取り操作は非常に時間のかかる操作です。

誰かがこの問題を回避するためのいくつかの方法を提案できますか?

このアプリケーションは、VisualStudioコンパイラを使用してCのWindowsで開発しています。

4

3 に答える 3

4

非同期I/O(AIO)と呼ばれる手法があり、ファイルがバックグラウンドで読み取られている間、CPUで何らかの処理を続けることができます。これを使用して、ファイルの処理と同時に次のいくつかのファイルを読み取ることができます。

さまざまなAIO呼び出しはOS固有です。Windowsでは、Microsoftはこれを「重複I/O」と呼んでいます。詳細については、このWikipediaページまたはこのMSDNページを参照してください。

于 2012-12-17T18:58:26.567 に答える
1

回避策として、最初にすべてのファイルを読み取り、すべてのファイル データを RAM に保存してから、操作を実行します (CPU を使用します)。

(ファイルを独立して処理できると仮定します...)

あなたはそこまでの道のりです。すべてのファイルが RAM にロードされるまで待つのではなく、ファイルがロードされたらすぐに処理を開始します。これは、パイプライン処理の一種です。

次の 3 つのコンポーネントが必要です。

  1. ファイルを読み取るスレッド1 (「プロデューサー」)。
  2. ファイルを処理するスレッド2 (「コンシューマー」)。
  3. それらの間のメッセージ キュー3 。

プロデューサは、すでに行っている方法でファイルを読み取りますが、ファイルを処理する代わりに、メッセージ キューにエンキューするだけです。コンシューマ スレッドは、キューからファイルを取り出して処理できるようになるまで待機し、ファイルによって占有されていたメモリをすぐに解放して、キューへの待機を再開します。

ファイルを最初から最後まで順番にトラバースすることでファイルを処理できる場合は、よりきめ細かい「ストリーミング」を考案することもできます。この場合、ファイルはチャンクで読み取られ、処理されます。これにより、ピーク時のメモリ消費をさらに下げることができます (たとえば、メモリに全体を保持する必要がなくなった特大ファイルがある場合など)。


1または、複数の物理ディスクから読み取ることが予想される場合は、I/O を並列化するための一連のスレッド。

2または、ファイルの処理が読み取りよりも安くない場合は、CPU コアを飽和させるための一連のスレッド。

3そのためには、手の込んだ永続的な分散メッセージ キューは必要ありません。単純なインメモリ キュー、 .NET のBlockingCollectionのようなものです (純粋な C で似たようなものが見つかると思います)。

于 2012-12-18T12:41:38.890 に答える
0
  1. ファイルを RAM に読み込むスレッドを (ループ内で) 作成します。
  2. RAM 内のデータを別のスレッドで処理し、処理後に RAM を解放します。
  3. ミューテックスによって保護された共有オブジェクト内のファイル (読み取りおよび処理) に関するレコードの制限とポーリングを保持します。
  4. リソース (RAM 内のファイル) の生産/使用の同期にセマフォを使用します。
于 2012-12-17T21:14:47.223 に答える