.Net4.0 Parallel編程(一)Data Parallelism 上
摘要:現在已經進入了多核的時代,我們的程序如何更多的利用好cpu,答案是并行處理。在.net4.0之前我們要開發并行的程序是非常的困難,在.net4.0中,在命名空間System.Threading.Tasks提供了方便的并行開發的類庫。本文中主要看看Data Parallel,看看并行的For、Foreach。
Parallel.For
首先先寫一個普通的循環:
private void NormalFor()
{
for (var i = 0; i < 10000; i++)
{
for (var j = 0; j < 1000; j++)
{
for (var k = 0; k < 100; k++)
{
DoSomething();
}
}
}
}
{
for (var i = 0; i < 10000; i++)
{
for (var j = 0; j < 1000; j++)
{
for (var k = 0; k < 100; k++)
{
DoSomething();
}
}
}
}
再看一個并行的For語句:
private void ParallelFor()
{
Parallel.For(0, 10000, i =>
{
for (int j = 0; j < 1000; j++)
{
for (var k = 0; k < 100; k++)
{
DoSomething();
}
}
});
}
{
Parallel.For(0, 10000, i =>
{
for (int j = 0; j < 1000; j++)
{
for (var k = 0; k < 100; k++)
{
DoSomething();
}
}
});
}
看下測試方法:
[TestMethod()]
public void TestForLoop()
{
_StopWatch.Start();
this.NormalFor();
_StopWatch.Stop();
Console.WriteLine("NormalForLoop Runned Time:{0}", _StopWatch.ElapsedMilliseconds);
_StopWatch.Reset();
_StopWatch.Start();
this.ParallelFor();
_StopWatch.Stop();
Console.WriteLine("Parallel Loop:{0}", _StopWatch.ElapsedMilliseconds);
}
public void TestForLoop()
{
_StopWatch.Start();
this.NormalFor();
_StopWatch.Stop();
Console.WriteLine("NormalForLoop Runned Time:{0}", _StopWatch.ElapsedMilliseconds);
_StopWatch.Reset();
_StopWatch.Start();
this.ParallelFor();
_StopWatch.Stop();
Console.WriteLine("Parallel Loop:{0}", _StopWatch.ElapsedMilliseconds);
}
測試結果:
上面的例子中,只是將最外層的For語句替換成了Parallel.For,我們可以看到Parallel執行速度提高了近一倍。下面我把里面的循環也改成并行的:
private void ParallelNestedFor()
{
Parallel.For(0, 10000, i =>
{
Parallel.For(0, 1000, j =>
{
for (var k = 0; k < 100; k++)
{
DoSomething();
}
});
});
}
{
Parallel.For(0, 10000, i =>
{
Parallel.For(0, 1000, j =>
{
for (var k = 0; k < 100; k++)
{
DoSomething();
}
});
});
}
結果:
也許會令我們感到驚訝的是:嵌套Paralled For之后速度并沒有更快,反而稍微慢了。其實是這樣的,因為我們的示例中大部分操作是在最外層循環,而在并行操作中會需要緩存數據等會浪費一定的性能。當我們把最外層的循環調整成100,中間層為10000時,我們來看下結果:
所以,是否需要嵌套的時候,需要我們根據一些實際情況來決定,不過對于大部分操作,最外層的并行處理已經足夠了。
Parallel.ForEach
我們來看兩段很簡單的代碼:
private void NormalForeach()
{
foreach (var file in GetFiles())
{
DoSomething();
}
}
private void ParallelForeach()
{
Parallel.ForEach(GetFiles(), file => {
DoSomething();
});
}
{
foreach (var file in GetFiles())
{
DoSomething();
}
}
private void ParallelForeach()
{
Parallel.ForEach(GetFiles(), file => {
DoSomething();
});
}
測試的結果:
Foreach的使用跟For使用幾乎是差不多了,只是在對非泛型的Collection進行操作的時候,需要通過Cast方法進行轉換。
總結
在本文中,我們簡單的介紹了Parallel.For跟Parallel.Foreach方法的使用,感受了下并行編程給我們帶來的速度上的優勢,在下篇文章中會介紹如何跳出循環以及一些異常的處理。
全站熱搜