1

ファイルに保存されているデータを指定した速度で再生したいという問題に取り組んでいます。

例:25,000レコード/秒。

ファイルはASCII形式です。現在、ファイルの各行を読み取り、正規表現を適用してデータを抽出しています。2〜4行でレコードを構成します。この操作の時間を計ったところ、各レコードの生成に15マイクロ秒近くかかりました。

各レコードの公開にかかる時間は6マイクロ秒です。

読み取りと書き込みを順番に実行すると、各レコードを公開するのに21マイクロ秒になります。つまり、事実上、これは私の上限が1秒あたり約47Kレコードであることを意味します。

読み取りと書き込みをマルチスレッド化することにした場合、9マイクロ秒ごとにパケットを送信できます(リーダーとライターは同じQを共有するため、ロックペナルティは無視されます)。これにより、1秒あたり110Kティックのスループットが得られます。

以前のデザインは正しいですか?

単一のプロデューサーとコンシューマーがキューを共有する場合、どのような種類のキューとロック構造でペナルティが最小になりますか?

これを超えてスケ​​ーリングしたい場合、最善のアプローチは何ですか?

私のアプリケーションはC++です

4

1 に答える 1

1

レコードの読み取り/準備に 15 マイクロ秒かかる場合、最大スループットは約 1 秒/15 マイクロ秒 = 67k/秒になります。ファイルを読み取る単一のスレッドがそれ以上のレコードを生成できないため、6uSec の部分は無視できます。(試してみて、プログラムを読み取り/処理のみに変更し、出力を破棄します)どうやって9uSを取得したのかわかりません。

これを 67k/sec を超えて飛ばすには ...

A) フォーマットするディスクから読み取ることができる 1 秒あたりの最大レコード数を見積もります。これはハードウェアに大きく依存しますが、平均的なラップトップでは 20Mb/秒の数値が一般的です。この数値は、目標とする上限を示しており、近づくにつれて、挑戦をやめることができます。

B)ファイルを読み取るためだけに単一のスレッドを作成し、IO 遅延を発生させます。このスレッドは、事前に割り当てられた大きなバッファ (それぞれ 4Mb など) に書き込む必要があります。これらを管理する方法については、http://en.wikipedia.org/wiki/Circular_bufferを参照してください。バッファごとにおそらく1000レコードを保持しようとしています(推測ですが、8つのレコードだけではありません!)疑似コード:

   while not EOF
     Allocate big buffer
     While not EOF and not buffer full
          Read file using fgets() or whatever
          Apply only very small preprocessing, ideally none
          Save into buffer
     Release buffer for other threads

C)別のスレッド(レコードの順序が重要でない場合は複数)を作成して、リングバッファがいっぱいになったときに処理します。正規表現のステップです。このスレッドは、出力リング バッファーの別のセットに順番に書き込みます (ヒント、メモリ内でリング バッファー制御構造を分離しておいてください)。

    While run-program
        Wait/get an input buffer to process, semaphores/mutex/whatever you prefer
        Allocate output buffer
        Process records from input buffer,
           Place result in output buffer
        Release output buffer for next thread
        Release input buffer for reading thread

D)データを消費する最終スレッドを作成します。この出力がディスクに書き込まれているのか、ネットワークに書き込まれているのかは明確ではないため、ディスク読み取りスレッドに影響を与える可能性があります。

    Wait/get input buffer from processed records pool
    Output records to wherever
    Return buffer to processed records pool

ノート。すべてのバッファを事前に割り当て、元の場所に戻します。たとえば、ファイル読み取りスレッドと処理スレッドの間に 4 つのバッファーがあり、4 つすべてが注入されている場合、ファイル リーダーは 1 つが解放されるのを待ち、新しいバッファーを割り当てるだけではありません。回避できる場合は memset() バッファを使用しないようにしてください。メモリ帯域幅が無駄になります。多くのバッファーは必要ありませんよね、6? リングバッファごと?

システムは最も遅いスレッド ( http://en.wikipedia.org/wiki/Theory_of_constraints )に自動調整されるため、データを出力するよりも速く読み取って準備できる場合、すべてのバッファーがいっぱいになり、例外を除いてすべてが一時停止します。出力。

スレッドは同期点ごとに妥当な量のデータを渡しているため、このオーバーヘッドはそれほど重要ではありません。

上記の設計は、私のコードの一部が CSV ファイルをできるだけ速く読み取る方法です。基本的に、制限要因として入力 IO 帯域幅がすべてになります。

于 2013-03-03T18:43:34.560 に答える