平行運算 (二):PLINQ 的應用
上一篇 平行運算 (一):Parallel.For、Parallel.Foreach 用法及技巧,
討論了 Paralle.For 及 Paralle.Foreach 的寫法,
這邊我們利用 LINQ 以及 新的 PLINQ 來實作與上篇同樣的需求。
現在做一個實驗,我要取得測試資料中包含a 或 包含 abc的字串,
分別利用 LINQ、 PLINQ 方式來比較執行的時間
測試資料
//產生測試資料
List<string> testData = new List<string>();
//產生亂數字串
for (int i = 0; i < 100000; i++)
{
testData.Add(Rand.RndChars(2, 10));
}
其中 Rand.RndChars 是自己寫的產生亂數字串Method
LINQ
//紀錄結果用
List<string> resultData = new List<string>();
//找出 testData 中包含a 或 包含 abc的字串
resultData = testData.Where(a => a.Contains("a") || a.Contains("abc")).ToList();
PLINQ
.NET Framework 4 另外擴充了LINQ的用法,讓LINQ可以用非常非常簡單的方式來實現平行運算,稱為PLINQ
//紀錄結果用
List<string> resultData = new List<string>();
resultData = testData.AsParallel().Where(a => a.Contains("a") || a.Contains("abc")).ToList();
只要在原本的LINQ語法加上 .AsParallel() 就可以利用平行運算
其中.AsParallel() 並不表示一定會使用平行運算,其執行緒的數目會由 1、2、4、8…來增加,
另外.AsParallel()之後可以接上一個另一個方法 .WithExecutionMode(ParallelExecutionMode.ForceParallelism) ,表示要強迫使用平行運算,
此時程式會像這樣
resultData = testData.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism).Where(a => a.Contains("a") || a.Contains("abc")).ToList();
測試結果(與上篇一起比較)
寫完以上語法後,
來比較一下效能吧
分別執行了20次,數字單位為 ms。
foreach: | 19 | Parallel.For: | 8 | Parallel.ForEach: | 8 | LINQ | 20 | PLINQ | 11 |
foreach: | 21 | Parallel.For: | 7 | Parallel.ForEach: | 7 | LINQ | 20 | PLINQ | 11 |
foreach: | 20 | Parallel.For: | 7 | Parallel.ForEach: | 7 | LINQ | 20 | PLINQ | 11 |
foreach: | 19 | Parallel.For: | 7 | Parallel.ForEach: | 6 | LINQ | 22 | PLINQ | 11 |
foreach: | 20 | Parallel.For: | 7 | Parallel.ForEach: | 8 | LINQ | 19 | PLINQ | 11 |
foreach: | 19 | Parallel.For: | 5 | Parallel.ForEach: | 8 | LINQ | 20 | PLINQ | 12 |
foreach: | 20 | Parallel.For: | 9 | Parallel.ForEach: | 6 | LINQ | 20 | PLINQ | 6 |
foreach: | 19 | Parallel.For: | 8 | Parallel.ForEach: | 7 | LINQ | 19 | PLINQ | 7 |
foreach: | 19 | Parallel.For: | 8 | Parallel.ForEach: | 8 | LINQ | 19 | PLINQ | 6 |
foreach: | 19 | Parallel.For: | 8 | Parallel.ForEach: | 7 | LINQ | 21 | PLINQ | 11 |
foreach: | 17 | Parallel.For: | 6 | Parallel.ForEach: | 7 | LINQ | 20 | PLINQ | 5 |
foreach: | 17 | Parallel.For: | 7 | Parallel.ForEach: | 4 | LINQ | 17 | PLINQ | 7 |
foreach: | 18 | Parallel.For: | 6 | Parallel.ForEach: | 5 | LINQ | 21 | PLINQ | 6 |
foreach: | 17 | Parallel.For: | 4 | Parallel.ForEach: | 5 | LINQ | 17 | PLINQ | 5 |
foreach: | 18 | Parallel.For: | 5 | Parallel.ForEach: | 7 | LINQ | 18 | PLINQ | 5 |
foreach: | 20 | Parallel.For: | 9 | Parallel.ForEach: | 6 | LINQ | 20 | PLINQ | 6 |
foreach: | 19 | Parallel.For: | 8 | Parallel.ForEach: | 6 | LINQ | 19 | PLINQ | 10 |
foreach: | 19 | Parallel.For: | 9 | Parallel.ForEach: | 5 | LINQ | 19 | PLINQ | 10 |
foreach: | 19 | Parallel.For: | 7 | Parallel.ForEach: | 5 | LINQ | 19 | PLINQ | 7 |
foreach: | 21 | Parallel.For: | 7 | Parallel.ForEach: | 7 | LINQ | 20 | PLINQ | 7 |
平均時間
foreach: 18.17 ms
Parallel.For:7.16 ms
Parallel.Foreach:6.3 ms
LINQ:19.5 ms
PLINQ:7 ms
在這邊也可以看出,利用LINQ語法的簡潔(此case可以簡化成一行)以及各種延伸擴充的Power(支援PLINQ),
還沒有開始接觸LINQ的朋友,快來試試吧。
參考資料
- 如果您覺得這篇文章有幫助,請您幫忙推薦一下或按上方的"讚"給予支持,非常感激
- 歡迎轉載,但請註明出處
- 文章內容多是自己找資料學習到的心得,如有不詳盡或錯誤的地方,請多多指教,謝謝