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
とはどちらwriteQueue
もConcurrentQueuesです。
並行して実行されているものはありません:
- 実行中の合計 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 のケース スタディのように思えますが、なぜ何も並行して実行されないのか頭を悩ませています。