Parallelクラスを使って並列処理を高速化してみました。
環境としては、SurfacePro4でCPUは、i5です。
テストコードは、次の汚れきった目も当てられないコードになっています。
試したのは、foreach文、for文、Parallel.ForEach,Parallel.For(スレッド数は、デフォルト、8,4,2)の10種類です。
結果としては、予想通り、コア数と同程度が良いみたいですね。
ちなみに、スレッド数指定しない場合には、いくつで動くのか、わかる人いたら教えてください。
お願いします。
環境としては、SurfacePro4でCPUは、i5です。
テストコードは、次の汚れきった目も当てられないコードになっています。
試したのは、foreach文、for文、Parallel.ForEach,Parallel.For(スレッド数は、デフォルト、8,4,2)の10種類です。
結果としては、予想通り、コア数と同程度が良いみたいですね。
ちなみに、スレッド数指定しない場合には、いくつで動くのか、わかる人いたら教えてください。
お願いします。
コード
/// <summary>
/// テスト実施
/// </summary>
/// <remarks>
/// 同じこといっぱい書きたくなかったのと、
/// クラス用意するのがいやだったのと、
/// 関数化するのが面倒だったので、
/// 汚コードです。
/// </remarks>
/// <param name="args"></param>
static void Main(string[] args)
{
var count = 1000;
var target = Enumerable.Range(0, count).ToList();
var sw = new Stopwatch();
var results = new List<String>();
var stringWidth = 40;
var option = new ParallelOptions();
// 結果保持のためのAction
var ResultAdd = new Action<String, TimeSpan>((msg, ellapsed) =>
{
results.Add(
String.Format(
msg, sw.Elapsed).PadLeft(stringWidth));
});
// 匿名配列で表示メッセージと実行処理を登録
var testMethod = new[]
{
// foreachで回す
new {
Msg ="foreach:{0}",
Method =new Action<List<Int32>>((list)=>
{
foreach (var i in list)
{
Console.WriteLine(WeightMethod(i));
}
})
},
// forで回す
new {
Msg ="for:{0}",
Method =new Action<List<Int32>>((list)=>
{
for (Int32 i = 0; i < count; i++)
{
Console.WriteLine(WeightMethod(list[i]));
}
})
},
// Parallel.ForEachで回す(オプション指定なし)
new {
Msg ="Parallel.ForEach:{0}",
Method =new Action<List<Int32>>((list)=>
{
Parallel.ForEach(list, (i) =>
{
Console.WriteLine(WeightMethod(i));
});
})
},
// Parallel.Forで回す(オプション指定なし)
new {
Msg ="Parallel.For:{0}",
Method =new Action<List<Int32>>((list)=>
{
Parallel.For(0, count, (i) =>
{
Console.WriteLine(WeightMethod(list[i]));
});
})
},
// Parallel.ForEachで回す(オプション指定:8)
new {
Msg ="Parallel.ForEach8:{0}",
Method =new Action<List<Int32>>((list)=>
{
option.MaxDegreeOfParallelism = 8;
Parallel.ForEach( list, option, (i) =>
{
Console.WriteLine(WeightMethod(i));
});
})
},
// Parallel.Forで回す(オプション指定なし:8)
new {
Msg ="Parallel.For8:{0}",
Method =new Action<List<Int32>>((list)=>
{
option.MaxDegreeOfParallelism = 8;
Parallel.For( 0, count, option, (i) =>
{
Console.WriteLine(WeightMethod(list[i]));
});
})
},
// Parallel.ForEachで回す(オプション指定:4)
new {
Msg ="Parallel.ForEach4:{0}",
Method =new Action<List<Int32>>((list)=>
{
option.MaxDegreeOfParallelism = 4;
Parallel.ForEach( list, option, (i) =>
{
Console.WriteLine(WeightMethod(i));
});
})
},
// Parallel.Forで回す(オプション指定なし:4)
new {
Msg ="Parallel.For4:{0}",
Method =new Action<List<Int32>>((list)=>
{
option.MaxDegreeOfParallelism = 4;
Parallel.For( 0, count, option, (i) =>
{
Console.WriteLine(WeightMethod(list[i]));
});
})
},
// Parallel.ForEachで回す(オプション指定:2)
new {
Msg ="Parallel.ForEach2:{0}",
Method =new Action<List<Int32>>((list)=>
{
option.MaxDegreeOfParallelism = 2;
Parallel.ForEach( list, option, (i) =>
{
Console.WriteLine(WeightMethod(i));
});
})
},
// Parallel.Forで回す(オプション指定なし:2)
new {
Msg ="Parallel.For2:{0}",
Method =new Action<List<Int32>>((list)=>
{
option.MaxDegreeOfParallelism = 2;
Parallel.For( 0, count, option, (i) =>
{
Console.WriteLine(WeightMethod(list[i]));
});
})
},
};
for (var id = 0; id < testMethod.Length; id++)
{
sw.Reset();
sw.Start();
// 実行
testMethod[id].Method(target);
sw.Stop();
// 結果書き込み
ResultAdd(testMethod[id].Msg, sw.Elapsed);
}
foreach (var result in results)
{
Console.WriteLine(result);
}
}
/// <summary>
/// 重たい処理もどき
/// </summary>
/// <remarks>
/// なんでもよい。
/// </remarks>
/// <param name="count"></param>
/// <returns></returns>
static UInt64 WeightMethod(Int32 count)
{
var ret = 0UL;
var max = 10000000 - count;
for (var i = 0U; i < max; i++)
{
ret += i;
ret -= i;
}
return ret;
}
結果
foreach:00:00:36.3392310
for:00:00:36.3863514
Parallel.ForEach:00:00:17.7727370
Parallel.For:00:00:17.3482534
Parallel.ForEach8:00:00:17.5221452
Parallel.For8:00:00:18.8532388
Parallel.ForEach4:00:00:16.3212531
Parallel.For4:00:00:16.3745319
Parallel.ForEach2:00:00:20.8530706
Parallel.For2:00:00:20.0480644
0 件のコメント:
コメントを投稿