摘要:[C#]隨筆手扎 - Parallel & Lock
在.Net 4中新增入了Parallel用法,讓我們可以更快及更方便地進行平行化的處理;
做平行化有什麼好處?最主要的好處,莫過於更快地完成目標了;但是,Parallel下的結果,是否都是正確的呢?!
比方說,如果我要寫一個累計的功能,如果在未平行的前提下,一般都是用以下的方式達成:
static void Main(string[] args)
{
int result = 0;
for (int i = 0; i <= times; i++)
{
result += sum(i);
}
Console.WriteLine(result.ToString());
}
static int sum(int input)
{
int result = 0;
for (int i = 1; i <= input; i++)
{
result += i;
}
return result;
}
透過Parallel的話,可以這麼寫:
static void Main(string[] args)
{
int result = 0;
Parallel.For(1, times+1, i =>
{
result += sum(i);
});
Console.WriteLine(result.ToString());
}
static int sum(int input)
{
int result = 0;
for (int i = 1; i <= input; i++)
{
result += i;
}
return result;
}
論理上,透過平行處理,只要您的電腦核心夠多及夠有力,取得結果的時間,會遠比未平行前來得少很多的!
不過,就如先前所說的,平行化的結果,似乎真的皆正確呢?
答案請看以下的測試結果(此結果中,一併展示了平行與未平行的差別):
範例程示碼如下:
static void Main(string[] args)
{
Console.WriteLine("===No Paralle===");
for (int i = 0; i < 10; i++)
{
NoParallel(26);
}
Console.WriteLine("===No Lock===");
for (int i = 0; i < 10; i++)
{
ParallelNoLock(26);
}
}
static void NoParallel(int times)
{
Stopwatch sw = new Stopwatch();
sw.Start();
int result = 0;
for (int i = 0; i <= times; i++)
{
result += sum(i);
Thread.Sleep(100);
}
sw.Stop();
Console.WriteLine(result.ToString() + "(total cost " + (sw.ElapsedMilliseconds / 1000).ToString() + " seconds)");
}
static void ParallelNoLock(int times)
{
Stopwatch sw = new Stopwatch();
sw.Start();
int result = 0;
Parallel.For(1, times+1, i =>
{
result += sum(i);
Thread.Sleep(100);
});
sw.Stop();
Console.WriteLine(result.ToString() + "(total cost " + (sw.ElapsedMilliseconds / 1000).ToString() + " seconds)");
}
static int sum(int input)
{
int result = 0;
for (int i = 1; i <= input; i++)
{
result += i;
}
return result;
}
以上的測試,我刻意在迴圈中加入延遲0.1秒,並且在雙核的筆電上進行測試,結果如下:
從結果中,很明顯地可以看到,同樣的功能,在重覆呼叫10次後,照理說,10次總計的結果應該要是一樣的,但是,平行化後,卻不是如此!
關於這問題,主要是因為平行化後的線程中,有發生問題,以致總計的結果有誤差!因此,關於這問題,事實上,解決方式很簡單,
只要在主要的區塊程序中,加上lock即可!lock的建議用法,如下圖示中,紅框所示處!
最後,透過加上lock的parallel,再做一次測試;此次將延遲加大至0.5秒,以便區分效果,並在8核的主機上進行測試如下:
從結果看來,最後總計的結果就是正確了,並且也能明顯地看出平行的效果了!
以上測試,僅供參考了,謝謝!