10

大きなファイル (RAM より大きく、一度に全体を読み取ることができない) があり、行ごとに (C++ で) 処理する必要があります。できれば Intel TBBまたは Microsoft PPLを使用して、複数のコアを利用したいと考えています。このファイルの前処理 (4 つの部分に分割するなど) は避けたいと思います。

ファイル内の (0, n/4, 2*n/4 3*n/4) 位置に初期化された 4 つのイテレータを使用するようなことを考えていました。

それは良い解決策ですか、それを達成する簡単な方法はありますか?

または、ストリームの効率的な同時読み取りをサポートするいくつかのライブラリを知っていますか?

更新:

私はテストをしました。ボトルネックは IO ではなく、CPU です。そして、バッファ用のRAMがたくさんあります。

レコードを解析する必要があります (var サイズ、それぞれ約 2000 バイト、レコードは一意の '\0' 文字で区切られています)、検証し、計算を行い、結果を別のファイルに書き込む必要があります

4

5 に答える 5

14

部分に分割できるためN、各行の処理は大きく独立しているように聞こえます。その場合、最も簡単な解決策は、1 つのスレッドを設定してファイルを 1 行ずつ読み取り、各行をtbb::concurrent_queue. 次に、そのキューから行を取り出して処理するために必要な数のスレッドを生成します。

このソリューションはファイル サイズとは無関係であり、より多くの (またはより少ない) ワーカー スレッドが必要な場合は、数を変更するのは簡単です。ただし、行間に何らかの依存関係がある場合、これは機能しません...それを処理するために「後処理」スレッドの 2 番目のポーリングを設定しない限り、状況が複雑になりすぎる可能性があります。

于 2011-05-20T10:58:36.820 に答える
6

私のお勧めは、TBB のパイプライン パターンを使用することです。パイプラインの最初のシリアル ステージでは、ファイルからデータの必要な部分を読み取ります。後続のステージではデータ チャンクが並行して処理され、最後のステージでは、データが読み取られた順序と同じ順序で別のファイルに書き込まれます。

このアプローチの例は、TBB ディストリビューションで利用できます。例/パイプライン/正方形を参照してください。「古い」インターフェイス、クラス、およびポインターによってデータを渡すtbb::pipelineフィルター (から継承されたクラス) を使用します。新しいタイプセーフでラムダフレンドリーな「宣言型」インターフェースの方が使いやすいかもしれません。tbb::filtervoid*tbb::parallel_pipeline()

于 2011-05-20T13:12:27.930 に答える
3

ianmac はすでにシークの問題をほのめかしています。あなたのイテレータのアイデアは少しひねって合理的です: それらを 0、1、2、3 に初期化し、それぞれを 4 ずつ増やします。したがって、最初のスレッドは項目 0、4、8 などで動作します。OS はファイルできるだけ早くアプリにフィードされます。ファイルをシーケンシャル スキャンすることを OS に伝えることができる場合があります (たとえば、Windows では、これは へのフラグCreateFileです)。

于 2011-05-20T10:59:35.977 に答える
0

ファイルからの読み取りに関しては、これはお勧めしません。私の知る限り、ハードドライブは一度に複数の場所から読み取ることはできません。

ただし、データの処理はまったく別のものであり、複数のスレッドで簡単に実行できます。(データを正しい順序に保つことも、まったく難しいことではありません。)

于 2011-05-20T10:51:10.337 に答える
0

どのような種類の処理を行うつもりかについてはあまり言いません。プロセスが計算または I/O バウンドであると予想されるかどうか、異なる行の処理間にデータの依存関係があるかどうかなどは不明です。

いずれにせよ、1 つの大きなファイル内の 4 つの大きく異なる位置からの並列読み取りは非効率的である可能性があります (最終的に、ディスク ヘッドはハード ドライブの異なる領域間を行き来し続ける必要があり、スループットに悪影響を及ぼします)。

代わりに考えられるのは、ファイルを最初から最後まで順番に読み取り、個々の行 (または行のブロック) を処理のためにワーカー スレッドに展開することです。

于 2011-05-20T10:57:31.683 に答える