我尝试了一个非常小的例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Concurrent;
using System.Diagnostics;
namespace TPLExample {
class Program {
static void Main(string[] args) {
int[] dataItems = new int[100];
double[] resultItems = new double[100];
for (int i = 0; i < dataItems.Length; ++i) {
dataItems[i] = i;
}
Stopwatch stopwatch = new Stopwatch();
stopwatch.Reset();
stopwatch.Start();
Parallel.For(0, dataItems.Length, (index) => {
resultItems[index] = Math.Pow(dataItems[index], 2);
});
stopwatch.Stop();
Console.WriteLine("TPL Time elapsed: {0}", stopwatch.Elapsed);
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < dataItems.Length; ++i) {
resultItems[i] = Math.Pow(dataItems[i], 2);
}
stopwatch.Stop();
Console.WriteLine("Sequential Time elapsed: {0}", stopwatch.Elapsed);
WaitForEnterKey();
}
public static void WaitForEnterKey() {
Console.WriteLine("Press enter to finish");
Console.ReadLine();
}
public static void PrintMessage() {
Console.WriteLine("Message printed");
}
}
}
输出结果为:
TPL Time elapsed: 00:00:00.0010670
Sequential Time elapsed: 00:00:00.0000178
Press enter to finish
顺序循环比TPL快!这怎么可能?根据我的理解,Parallel.For
内的计算将并行执行,所以它必须更快吗?
答案 0 :(得分:10)
简单地说:对于只迭代超过一百个项目并执行一个小的数学运算,产生新线程并等待它们完成会产生比仅仅通过循环运行更多的开销。
根据我的理解,Parallel.For中的计算将并行执行,所以它必须更快吗?
通常情况下,当人们对计算机性能进行彻底的陈述时,这里有更多的变量,你无法做出这样的假设。例如,在for
循环内,您只执行Math.Pow
,处理器可以非常快速地执行此操作。如果这是一个I / O密集型操作,要求每个线程等待很长时间,或者即使它是一系列处理器密集型操作,您将获得更多的并行处理(假设您有一个多线程处理器) 。但实际上,创建和同步这些线程的开销远大于并行性可能给你的任何优势。
答案 1 :(得分:10)
当在循环内执行的操作相对昂贵时,并行循环处理是有益的。你在你的例子中所做的只是计算指数,这是微不足道的。多线程的开销远远超过你在这种情况下获得的收益。
答案 2 :(得分:2)
这个代码示例是实际证明上面非常好的答案。
我通过Thead.Sleep简单地阻止线程来模拟密集处理器操作。
输出结果为:
_
class Program
{
static void Main(string[] args)
{
const int a = 10;
Stopwatch sw = new Stopwatch();
sw.Start();
//for (long i = 0; i < a; i++)
//{
// Thread.Sleep(1000);
//}
Parallel.For(0, a, i =>
{
Thread.Sleep(1000);
});
sw.Stop();
Console.WriteLine(sw.Elapsed);
Console.ReadLine();
}
}
答案 3 :(得分:1)
并行化的开销远远大于简单地按顺序运行Math.Pow 100次。其他人都这么说了。
更重要的是,内存访问在顺序版本中是微不足道的,但是对于并行版本,线程必须共享内存(resultItems),而且真正甚至会杀死你如果你有一百万件物品。
请参阅此优秀 Microsoft平行编程白皮书的第44页: http://www.microsoft.com/en-us/download/details.aspx?id=19222。这是MSDN杂志关于这个主题的文章:http://msdn.microsoft.com/en-us/magazine/cc872851.aspx