私はParallel.ForEachをC#コンソールアプリケーションで使いこなしていますが、正しいとは思えません。私は乱数を使って配列を作成しています。配列foreachと配列の中で最大の値を見つけるParallel.ForEachがあります。 C++とほぼ同じコードを使って、配列の3M値でいくつかのスレッドを使うこととのトレードオフが見え始めました。しかし、Parallel.ForEachは100Mの値でも2倍の速度です。何が間違っているのですか?Parallel.ForEachは通常のforeachより遅い
class Program
{
static void Main(string[] args)
{
dostuff();
}
static void dostuff() {
Console.WriteLine("How large do you want the array to be?");
int size = int.Parse(Console.ReadLine());
int[] arr = new int[size];
Random rand = new Random();
for (int i = 0; i < size; i++)
{
arr[i] = rand.Next(0, int.MaxValue);
}
var watchSeq = System.Diagnostics.Stopwatch.StartNew();
var largestSeq = FindLargestSequentially(arr);
watchSeq.Stop();
var elapsedSeq = watchSeq.ElapsedMilliseconds;
Console.WriteLine("Finished sequential in: " + elapsedSeq + "ms. Largest = " + largestSeq);
var watchPar = System.Diagnostics.Stopwatch.StartNew();
var largestPar = FindLargestParallel(arr);
watchPar.Stop();
var elapsedPar = watchPar.ElapsedMilliseconds;
Console.WriteLine("Finished parallel in: " + elapsedPar + "ms Largest = " + largestPar);
dostuff();
}
static int FindLargestSequentially(int[] arr) {
int largest = arr[0];
foreach (int i in arr) {
if (largest < i) {
largest = i;
}
}
return largest;
}
static int FindLargestParallel(int[] arr) {
int largest = arr[0];
Parallel.ForEach<int, int>(arr,() => 0, (i, loop, subtotal) =>
{
if (i > subtotal)
subtotal = i;
return subtotal;
},
(finalResult) => {
Console.WriteLine("Thread finished with result: " + finalResult);
if (largest < finalResult) largest = finalResult;
}
);
return largest;
}
}
私は、ループの5回に並列実行を入れて、実行時間を500百万乱暴に異なります。 100msか10sかもしれません。 – Christoph
コードをデバッグモードで実行していますか?私の経験では、ParallelメソッドはVSデバッガが接続されているときに非常に遅く動作します。リリースからビルドし、VSから起動する代わりにEXEファイルを起動してください。 –
それぞれのParallel.ForEachは独自のタスクをスピンアップしています。代わりに、Range Partitionerを使用して作業をチャンクすることを検討する必要があります。 2 * Environment.ProcessorCountのチャンクサイズを提案する。 https://msdn.microsoft.com/en-us/library/system.collections.concurrent.partitioner(v=vs.110).aspxを参照してください。 –