4

テキスト ファイルから一意の文字の頻度を調べるための LINQ を作成しました。また、選択の助けを借りて、最初の結果をオブジェクトに変換していました。最終結果はリストの形式で出力されます。以下は私が使用したクエリです。

charNodes = inputString.GroupBy(ch => ch)
            .Select((ch) => new TNode(ch.Key.ToString(),ch.Count()))
            .ToList<TNode>();

私はクアッド コア マシンを実行しており、上記のクエリは 15 ミリ秒で実行されました。しかし、不思議なことに、同じクエリを PLINQ したときはさらに時間がかかりました。以下のクエリは約 40 ミリ秒かかりました。

charNodes = inputString.GroupBy(ch => ch).AsParallel
            .Select((ch) => new TNode(ch.Key.ToString(),ch.Count()))
            .ToList<TNode>();

最悪だったのは、約 83 ミリ秒かかった次のクエリのケースでした。

charNodes = inputString.AsParallel().GroupBy(ch => ch)
                               .Select((ch) => new TNode(ch.Key.ToString(), ch.Count()))
                               .ToList<TNode>();

ここで何がうまくいかないのですか?

4

2 に答える 2

2

この種の質問が出された場合、答えは常に同じです。PLINQ のオーバーヘッドはゲインよりも高いです。

これは、作業項目が非常に小さいために発生します (文字によるグループ化、または些細な入力からの新しいオブジェクトの作成)。彼らが大きいとき、それははるかにうまく機能します。

于 2012-09-17T20:49:28.943 に答える
0

あなたが提供したコードに基づいて厳密に何が起こっているのかを伝えるのは本当に難しいです.

TPL はスレッド プール スレッドを使用します。スレッド プールは、約 10 個の実行中のスレッドで開始されます。 より多くのスレッドが必要な場合、スレッド プールは、新しいスレッドが必要である限り、約 1 秒に 1 回新しいスレッドを作成します。ループで 10 を超える並列操作が発生した場合は、新しいスレッドをスピンアップするために時間を費やす必要があります。修正: 並列ループに必要なスレッドの数は、スレッド プールで使用可能なスレッドを減らします。スレッド プールは、そのプール内で使用可能なスレッドの最小数を保持しようとします。スレッドの時間がかかりすぎることに気付いた場合、それを補うために新しいスレッドをスピンアップします。これにはリソースが必要です。フレームワークの多くの部分でスレッド プールが使用されるため、スレッド プールに負荷がかかる可能性があるあらゆる種類の機会があります。スレッドの開始にはかなりのコストがかかります。

もう 1 つの可能性は、反復回数が使用可能なCPUの数よりも多い場合、多くのコンテキストの切り替えが発生したことです。コンテキストの切り替えはコストが高く、CPU の負荷や、OS がスレッド間を切り替える速度に影響します。

入力データなどの詳細を提供していただければ、回答で詳細を提供できます。

于 2012-09-17T18:59:46.557 に答える