0

私は厄介な大きなxmlとテキストドキュメントを処理しようとしています:〜40GB。Windows7でVisualStudio2012を使用しています。

「Xerces」を使用して、xmlからヘッダー/「フッタータグ」を取得します。

ファイルの領域をマップしたいのですが、たとえば60〜120MBです。

マップを(3 *プロセッサ/コア)等しい部分に分割します。各部分をバッファーとして設定し、バッファーを配列にロードします。

次に、新しいスレッドでステートメント中に(#processors / cores)を使用して、バッファー配列をかみ砕きながら、文字/行/xmlサイクルを同期的にカウントします。1つのバッファが完了すると、プロセスは次の「使用可能な」バッファにジャンプし、完了したバッファはメモリからドロップされます。最後に、合計結果をプロジェクトログに追加します。

その後、ログを参照し、ファイルを文字数/サイズ(または他のオプション)で最も近い行またはサイクルに分割し、ヘッダーと「フッタータグ」をすべての分割にドロップします。

これを行っているのは、複数のコンピューターを備えたネットワークを介して大量のデータをMySQLサーバーにインポートできるようにするためです。

私の質問は、新しいスレッドでバッファ配列とファイルマップを作成するにはどうすればよいですか?

使ってもいいですか :

CreateFileに勝つ

CreateFileMappingに勝つ

MapViewOfFileに勝つ

標準のifstream操作とcharバッファーを使用しますか、それとも他のものを選択する必要がありますか?

さらに明確にするために:私の考えでは、ハードドライブでファイルを1つの場所から一方向にメモリにストリーミングできれば、マシンの全処理能力を使用して、別々であるが等しいバッファをかみ砕くことができます。

〜フレーバー:それは、フェンスで囲まれたエリア内にとどまる必要があるX羊用の2本の腕だけを備えた3〜6個の大きなバケツを備えた1つの巨大なビンから食べ物をすくい取ろうとするシェパードのようなものです。しかし、それらはすべて光速で動きます。

いくつかのアイデアや指針がここで私を助けるかもしれません。どんな考えでも大歓迎です。ありがとう。

while(getline(my_file, myStr))
{
   characterCount += myStr.length();

   lineCount++;


   if(my_file.eof()){

      break;

   }
}

これは、テストの実行時に唯一のコードでした。2時間30分以上 2GBのRAMを搭載したデュアルコア1.6Mhzラップトップで実行するプログラムの合計プロセッサの45〜50%。現在ロードされているRAMのほとんどは、Firefoxで開いている最大50個のタブから600 + MB、60MBのVisualStudioなどです。

重要:テスト中、ウィンドウとダイアログボックスのみであるコードを実行しているプログラムは、それ自体の動作中のプライベートRAMセットを300K ish程度までダンプしているように見え、テスト。確かに、whileステートメント用に別のスレッドを作成する必要があります。ただし、これは、ファイルのどれもがバッファに読み込まれなかったことを意味します。CPUは、ハードドライブからのわずかな労力に追いつくために、実行全体で苦労していました。

PSCPUのボトルネックのさらなる証拠。ファイル全体をワイヤレスネットワーク経由で別のコンピューターに転送するのに20分かかる場合があります。これには、読み取りプロセスと、他のコンピューターでの書き込みプロセスへのソケットキャッチが含まれます。

アップデート

私はこの愛らしい小さなものを使って、前回のテスト時間から約15〜20分に移動しました。これは、MatsPeterssonが言っていたことと一致しています。

while (my_file.read( &bufferOne[0], bufferOne.size() ))

{{

int cc = my_file.gcount();

for (int i = 0; i < cc; i++)
{

    if (bufferOne[i] == '\n')
        lineCount++;

    characterCount++;

}

currentPercent = characterCount/onePercent;

SendMessage(GetDlgItem(hDlg, IDC_GENPROGRESS), PBM_SETPOS, currentPercent, 0);

}

確かに、これは単一のループであり、実際には前のテストよりもはるかに適切に動作しました。このテストは、Getlineを使用したこのテストの上に示されているタイトループよりも約800%高速でした。このループのバッファーを20MBに設定しました。私はこのコードを次の場所からジャックしました:SOF-最速の例

しかし...

リソースmonとタスクマネージャーでプロセスをポーリングしているときに、最初のコアが75〜90%の使用率で、2番目のコアが25〜50%(私が開いているいくつかのマイナーな背景のもののかなりの標準)であることを明確に示したことを指摘しておきます。 )、およびハードドライブで..それを待ちます... 50%。ディスク時間は100%急上昇しますが、25%と低くなります。これらはすべて、基本的に、バッファ処理を2つの異なるスレッド間で分割することが非常に有益である可能性があることを意味します。すべてのシステムリソースを使用しますが、それが私が望んでいることです。今日、プロトタイプが機能するようになったら更新します。

メジャーアップデート:たくさんの学習を経て、ようやくプロジェクトが終了しました。ファイルマップは必要ありません。ベクトル文字の束のみ。動的に実行されるファイルストリーム行と文字カウンターを正常に構築しました。良いニュースは、以前の10〜15分のマーカーから5.8 GBのファイルBOOYAで〜3〜4分になりました!〜

4

1 に答える 1

1

非常に短い答え: はい、これらの機能を使用できます。

データを読み取る場合、ファイルの内容をメモリにマップするのがおそらく最も効率的な方法です。メモリをアプリケーションのバッファにコピーする必要がなく、本来あるべき場所に直接読み取るだけです。したがって、十分なアドレス空間が利用可能である限り問題ありません.64ビットマシンには確かに十分な量があるはずです.32ビットシステムでは、リソースが不足する可能性があります.大きな問題になることはありません。

ただし、複数のスレッドを使用すると、まったく納得できません。非常に大きなファイルの複数の部分を読み取ることは非生産的であると私はかなり考えています。これにより、転送速度の大部分を占める、ディスク上のヘッドの移動量が増加します。「通常の」システムでは、50 ~ 100MB/秒の転送速度が期待できます。システムに何らかの種類の RAID コントローラーなどがある場合、その約 2 倍、非常にエキゾチックな RAID コントローラーでは 3 倍になる可能性があります。

したがって、40GB を読み取るには 3 ~ 15 分程度かかります。

CPU はおそらくそれほどビジーではなく、複数のスレッドを実行すると、システムの全体的なパフォーマンスが低下する可能性が非常に高くなります。

読み取り用と書き込み用に 1 つのスレッドを保持し、十分な量のデータを取得してから実際にデータを書き出すこともできます。これにより、ディスク上の読み取り/書き込みヘッドの不要な移動を回避できます。

于 2013-03-12T16:14:25.197 に答える