令人惊讶的是,使用 PLINQ 并没有在我创建的一个小测试用例上产生好处;事实上,它比通常的 LINQ 还要糟糕。
测试代码如下:
int repeatedCount = 10000000;
private void button1_Click(object sender, EventArgs e)
{
var currTime = DateTime.Now;
var strList = Enumerable.Repeat(10, repeatedCount);
var result = strList.AsParallel().Sum();
var currTime2 = DateTime.Now;
textBox1.Text = (currTime2.Ticks-currTime.Ticks).ToString();
}
private void button2_Click(object sender, EventArgs e)
{
var currTime = DateTime.Now;
var strList = Enumerable.Repeat(10, repeatedCount);
var result = strList.Sum();
var currTime2 = DateTime.Now;
textBox2.Text = (currTime2.Ticks - currTime.Ticks).ToString();
}
结果呢?
textbox1: 3437500
textbox2: 781250
所以,LINQ 比 PLINQ 花费更少的时间来完成类似的操作!
我做错了什么?还是有我不知道的转折?
编辑:我已经更新我的代码以使用秒表,但同样的行为仍然存在。为了降低 JIT 的影响,我实际上尝试了几次同时单击 button1
Và button2
并且没有特定顺序。尽管我得到的时间可能不同,但定性行为仍然存在:在这种情况下 PLINQ 确实较慢。
第一:停止使用 DateTime 来衡量运行时间。请改用秒表。测试代码如下所示:
var watch = new Stopwatch();
var strList = Enumerable.Repeat(10, 10000000);
watch.Start();
var result = strList.Sum();
watch.Stop();
Console.WriteLine("Linear: {0}", watch.ElapsedMilliseconds);
watch.Reset();
watch.Start();
var parallelResult = strList.AsParallel().Sum();
watch.Stop();
Console.WriteLine("Parallel: {0}", watch.ElapsedMilliseconds);
Console.ReadKey();
第二:并行运行会增加开销。在这种情况下,PLINQ 必须找到划分集合的最佳方法,以便它可以安全地并行对元素求和。之后,您需要加入创建的各个线程的结果并对它们求和。这不是一项简单的任务。
使用上面的代码我可以看到使用 Sum() 网络调用大约 95 毫秒。调用 .AsParallel().Sum() 大约需要 185 毫秒。
并行执行任务只有在您从中有所收获时才是一个好主意。在这种情况下,Sum 是一项足够简单的任务,您无法通过使用 PLINQ 获得它。
Tôi là một lập trình viên xuất sắc, rất giỏi!