10

私はクアッドコアマシンを持っていて、4つのコアすべてを利用するテキストファイルを解析するためのコードを書きたいと思っています。テキストファイルには、基本的に1行に1つのレコードが含まれています。

マルチスレッドは私の得意分野ではないので、ファイルを最適な方法で解析するために使用できるパターンを誰かが教えてくれるかどうか疑問に思っています。

私の最初の考えは、すべての行をある種のキューに読み込んでから、スレッドをスピンアップして行をキューから引き出して処理することですが、それはキューがメモリに存在する必要があり、これらはかなり大きなファイルなので、私はmその考えにはそれほど熱心ではありません。

私の次の考えは、行を読み取り、解析するスレッドを割り当てるある種のコントローラーを用意することですが、スレッドが行を処理する速度よりも速く行を処理している場合、コントローラーがボトルネックになるかどうかはわかりません。それらを読んで割り当てます。

私はおそらくこれらの両方よりも別の簡単な解決策があることを知っていますが、現時点ではそれを見ていません。

4

7 に答える 7

9

私はあなたの元の考えで行きます。キューが大きくなりすぎる可能性がある場合は、そのバッファゾーンを実装します(つまり、が100行を超える場合はファイルの読み取りを停止し、20を下回る場合は再度読み取りを開始します。テストを行う必要があります。最適な障壁を見つけるために)。とにかくアイテムを引き出すためにキューをロックする必要があるため、スレッドのいずれかが「リーダースレッド」になる可能性があるようにします。また、「低バッファー領域」がヒットしたかどうかを確認して、読み取りを再開することもできます。これを実行している間、他のスレッドは残りのキューを読み取ることができます。

または、必要に応じて、1つのリーダースレッドに(独自のキューを介して)他の3つのプロセッサスレッドに行を割り当てさせ、ワークスティーリング戦略を実装します。私はこれをしたことがないので、それがどれほど難しいかわかりません。

于 2008-08-10T03:19:36.623 に答える
9

マークの答えは、よりシンプルでエレガントなソリューションです。必要がないのに、なぜスレッド間通信で複雑なプログラムを作成するのですか?4つのスレッドを生成します。各スレッドは、ファイルのサイズ/ 4を計算して、開始点(および停止点)を決定します。その後、各スレッドは完全に独立して動作できます。

読み取りを処理するために特別なスレッドを追加する唯一の理由は、一部の行の処理に非常に長い時間がかかる予想し、これらの行がファイルの1つの部分にクラスター化されると予想する場合です。必要のないときにスレッド間通信を追加することは、非常に悪い考えです。予期しないボトルネックや同期のバグが発生する可能性が大幅に高まります。

于 2008-08-10T05:21:43.567 に答える
3

これにより、単一のスレッドで読み取りを行う際のボトルネックが解消されます。

open file
for each thread n=0,1,2,3:
    seek to file offset 1/n*filesize
    scan to next complete line
    process all lines in your part of the file
于 2008-08-10T04:41:43.367 に答える
1

ボトルネックは一般的に処理にあり、ファイルを処理するときの読み取りではないため、私は生産者/消費者パターンを使用します。ロックを回避するために、ロックのないリストを調べます。C#を使用しているので、JulianBucknallのロックフリーリストコードを見ることができます。

于 2008-08-11T05:04:40.607 に答える
1

私の経験はC#ではなくJavaを使用しているため、これらのソリューションが適用されない場合はお詫び申し上げます。

私が頭のてっぺんから考えることができる当面の解決策は、3つのスレッドを実行するエグゼキュータを用意することです(たとえば、を使用して)。入力ファイルから読み取られた行/レコードごとに、(を使用して)エグゼキュータでジョブを実行します。エグゼキュータはリクエストをキューに入れ、3つのスレッド間で割り当てます。Executors.newFixedThreadPoolExecutorService.submit

おそらくより良い解決策が存在しますが、うまくいけばそれでうまくいくでしょう。:-)

ETA:Wolfbyteの2番目のソリューションによく似ています。:-)

ETA2:System.Threading.ThreadPool.NETの非常によく似たアイデアのように聞こえます。私はそれを使ったことがありませんが、それはあなたの価値があるかもしれません!

于 2008-08-10T03:43:22.720 に答える
0

解析しているテキストが繰り返される文字列とトークンで構成されている場合は、ファイルをチャンクに分割し、チャンクごとに1つのスレッドで、キーワード、「句読点」、ID文字列、および値で構成されるトークンに事前解析することができます。文字列の比較とルックアップは非常にコストがかかる可能性があり、これを複数のワーカースレッドに渡すと、文字列のルックアップと比較を行う必要がない場合、コードの純粋に論理的/セマンティックな部分を高速化できます。

次に、事前に解析されたデータチャンク(すべての文字列比較を実行して「トークン化」した場合)を、トークン化されたデータのセマンティクスと順序を実際に確認するコードの部分に渡すことができます。

また、大量のメモリを占有するファイルのサイズが心配だとおっしゃっています。メモリバジェットを削減するためにできることがいくつかあります。

ファイルをチャンクに分割して解析します。一度に作業しているチャンクと「先読み」用のチャンクの数だけを読み込んで、次のチャンクに進む前にチャンクの処理が終了したときにディスクでストールしないようにします。

または、大きなファイルをメモリマップして、「デマンド」ロードすることもできます。CPUよりも多くのスレッドがファイルの処理に取り組んでいる場合(通常、スレッド= 1.5-2X CPUはデマンドページングアプリに適した数です)、メモリマップトファイルのIOでストールしているスレッドは、OSから自動的に停止します。メモリの準備が整い、他のスレッドは処理を続行します。

于 2008-09-17T04:27:08.297 に答える
0

@lomaxx

@ Derek&Mark:2つの答えを受け入れる方法があればいいのにと思います。ファイルをn個のセクションに分割すると、スレッドが「遅い」トランザクションのバッチに遭遇する可能性があるため、最終的にWolfbyteのソリューションを使用する必要がありますが、各プロセスでファイルを処理している場合は同量の処理が必要であることが保証されていたので、ファイルをチャンクに分割し、各チャンクをスレッドに割り当ててそれを実行するというソリューションが本当に気に入っています。

心配ない。クラスター化された「遅い」トランザクションが問題になる場合は、キューイングソリューションが最適です。平均的なトランザクションの速さや遅さに応じて、各ワーカーに一度に複数の行を割り当てることも検討してください。これにより、同期のオーバーヘッドが削減されます。同様に、バッファサイズを最適化する必要がある場合があります。もちろん、これらは両方とも、おそらくプロファイリング後にのみ実行する必要がある最適化です。(ボトルネックでない場合は、同期について心配する必要はありません。)

于 2008-08-11T00:02:20.607 に答える