2

C# プログラムに次の PLINQ ステートメントがあります。

 foreach (ArrestRecord arrest in
            from row in arrestQueue.AsParallel()
            select row)
        {
            Geocoder geocodeThis = new Geocoder(arrest);
            writeQueue.Enqueue(geocodeThis.Geocode());
            Console.Out.WriteLine("Enqueued " + ++k);
        }

arrestQueueとはどちらwriteQueueConcurrentQueuesです。

並行して実行されているものはありません:

  • 実行中の合計 CPU 使用率は約 30% であり、これは他のすべてが実行されている場合でも同様です。私は 8 つのコア (4 つの物理コアを備えた Core i7 720QM でのハイパースレッディング) を持っていますが、8 つのコアのうち 4 つが実質的にまったく使用されていません。残りは約 40%-50% 実行されます。
  • 通常、ディスク使用率は 0% であり、localhost 上の Postgres DB へのクエリを除いて、ネットワーク使用率はありません (以下を参照)。
  • 内部のどこかにブレークポイントを追加するとgeocodeThis.Geocode()、Visual Studio のThreadドロップダウンには[ pid ] Main Threadとだけ表示されます。他のスレッドに移動することはありません。
  • 私はNpgsqlを使用して Postgres に接続しており、各スレッドはテーブルに対していくつかのSELECTクエリを実行しています。pg_stat_activityを示す pgAdmin III の Server Status アプリを実行しています。これと、戦略的なブレークポイントの配置 (上記を参照) を監視することで、同時実行されていると思われるすべてのスレッドに対してアプリが複数のデータベース接続を開くことは決してないことgeocodeThis.Geocode()がわかります。DB 接続文字列にPooling=falseを追加して、接続がプールされないように強制しても、 で複数の接続が使用されることはありませんgeocodeThis.Geocode()
  • Postgres テーブルは、 WHERE句のすべての列でインデックスが作成されます。インデックスが不十分だったとしても、大量のディスク使用量が予想されます。Postgres が他の方法で物事を保持していた場合、それはコアを浸すように思われます。

これは単純な PLINQ のケース スタディのように思えますが、なぜ何も並行して実行されないのか頭を悩ませています。

4

2 に答える 2

5

あなたはassertQueueそれ自体の列挙だけを並列化し、それを通常のに「非並列化」しIEnumerableます。これはすべて、foreachループが開始する前に発生します。次に、ループの本体をシリアルに実行する通常のを使用しますIEnumerableforeach

ループの本体を並列に実行する方法はたくさんありますが、最初に頭に浮かぶのは次の方法Parallel.ForEachです。

Parallel.ForEach(arrestQueue, arrest =>
    {
        Geocoder geocodeThis = new Geocoder(arrest);
        writeQueue.Enqueue(geocodeThis.Geocode());
        Console.Out.WriteLine("Enqueued " + ++k);
    });
于 2011-05-22T04:59:50.083 に答える
1

並列コレクションを介したForeachは、依然としてシングルスレッド操作です。.AsParallelは、.ForAllメソッドを定義するコレクションを返します。このコレクションは、(ただし、コントラクトによって常に)並行して実行される場合があります。そのためのコードは次のようになります。

arrestQueue.AsParallel().ForAll(arrest=>
    {
        Geocoder geocodeThis = new Geocoder(arrest);
        writeQueue.Enqueue(geocodeThis.Geocode());
        Console.Out.WriteLine("Enqueued " + ++k);
    });
于 2011-05-22T04:59:24.220 に答える