此代码来自Microsoft文章http://msdn.microsoft.com/en-us/library/dd460703.aspx,稍作修改:
const int size = 10000000;
int[] nums = new int[size];
Parallel.For(0, size, i => {nums[i] = 1;});
long total = 0;
Parallel.For<long>(
0, size, () => 0,
(j, loop, subtotal) =>
{
return subtotal + nums[j];
},
(x) => Interlocked.Add(ref total, x)
);
if (total != size)
{
Console.WriteLine("Error");
}
非并行循环版本是:
for (int i = 0; i < size; ++i)
{
total += nums[i];
}
当我使用StopWatch
类测量循环执行时间时,我发现并行版本慢了10-20%。测试在Windows 7 64位,Intel i5-2400 CPU,4核,4 GB RAM上完成。当然,在Release配置中。
在我的真实程序中,我正在尝试计算图像直方图,并行版本运行速度慢10倍。当每次循环调用非常快时,这种计算任务能否与TPL成功并行化?
修改
最后,当将整个图像划分为若干个块时,我设法使用Parallel.For节省了超过50%的直方图计算执行时间。每个循环体调用现在处理整个块,而不是一个像素。
答案 0 :(得分:4)
因为Parallel.For
应该用于有点神圣的事情,而不是简单数字的总和!只需使用代理(j, loop, subtotal) =>
就足以让10-20%的时间更长。我们甚至没有谈到线程开销。看到针对周期中代表夏天的一些基准并且不仅要查看“真实世界”时间,还要查看CPU时间,这将会很有趣。
我甚至添加了一个与“{1}}委托做同样事情的”简单“委托的比较。
嗯......现在我的PC上有一些32位的数字(AMD六核)Parallel.For<>
并行在壁挂时间稍微快一点,但在处理器时间慢了8倍: - )
但是64位:
32 bits
Parallel: Ticks: 74581, Total ProcessTime: 2496016
Base : Ticks: 90395, Total ProcessTime: 312002
Func : Ticks: 147037, Total ProcessTime: 468003
修改后的代码:
64 bits
Parallel: Ticks: 104326, Total ProcessTime: 2652017
Base : Ticks: 51664, Total ProcessTime: 156001
Func : Ticks: 77861, Total ProcessTime: 312002