C# 为什么这个并行代码比它类似的非并行版本慢?

C# 为什么这个并行代码比它类似的非并行版本慢?,c#,parallel-processing,task-parallel-library,task,C#,Parallel Processing,Task Parallel Library,Task,我有以下代码(复制自LINQPad)。显然,我不明白TPL是如何工作的,或者代码是垃圾,为什么并行版本比非并行版本运行得慢 for (int i = 0; i < 100; i++) { ParallelOptions ops = new ParallelOptions(); ops.MaxDegreeOfParallelism = Environment.ProcessorCount; var watch = Stopwatch.StartNew();

我有以下代码(复制自LINQPad)。显然,我不明白TPL是如何工作的,或者代码是垃圾,为什么并行版本比非并行版本运行得慢

for (int i = 0; i < 100; i++)
{
    ParallelOptions ops = new ParallelOptions();
    ops.MaxDegreeOfParallelism = Environment.ProcessorCount;

    var watch = Stopwatch.StartNew();
    Parallel.ForEach<int>(Enumerable.Range(1, 10000000), ops, x => { int y = x + 1; });
    watch.Stop();
    Console.WriteLine("Parallel: {0}", watch.Elapsed.TotalSeconds);

    watch = Stopwatch.StartNew();
    foreach (var x in Enumerable.Range(1, 10000000))
    {
        int y = x + 1;
    }
    watch.Stop();
    Console.WriteLine("Non-parallel: {0}\n", watch.Elapsed.TotalSeconds);
}
for(int i=0;i<100;i++)
{
ParallelOptions ops=新的ParallelOptions();
ops.MaxDegreeOfParallelism=Environment.ProcessorCount;
var watch=Stopwatch.StartNew();
Parallel.ForEach(Enumerable.Range(1100000),ops,x=>{inty=x+1;});
看,停;
WriteLine(“Parallel:{0}”,watch.eassed.TotalSeconds);
watch=Stopwatch.StartNew();
foreach(可枚举范围(1100000)中的var x)
{
int y=x+1;
}
看,停;
WriteLine(“非并行:{0}\n”,watch.appeased.TotalSeconds);
}
前10项结果:

平行线:0.1991644 非平行线:0.0466178

平行线:0.1723428 非平行线:0.0447134

平行线:0.1141791 非平行线:0.0444557

平行线:0.1758878 非平行线:0.0444636

平行线:0.1687637 非平行线:0.0444338

平行线:0.1677679 非平行:0.0445771

平行线:0.1191462 非平行线:0.0446116

平行线:0.1702483 非平行线:0.0454863

平行线:0.1143605 非平行线:0.0451731

平行线:0.2155218
非并行:0.0450392

好吧,您能得到的最佳答案是运行一个探查器工具并测量代码的运行情况。但我有根据地猜测,并行代码的速度较慢,因为代码非常简单,启动线程并在线程之间切换会增加很多成本,因此计算速度方面的任何优势都可以忽略不计


但是,尝试进行一些实质性的计算,最终您将拥有并行执行的优势。你的代码太简单了。现代CPU不能以这种方式加载。

因为我不能将此作为注释添加,所以我添加了另一个答案来发布修改后的代码。@ixSci在回答中所说的似乎是正确的。我在并行代码体中执行了一个非常简单的操作,执行速度非常快,但是慢的原因是在线程之间切换上下文花费了很多时间?当我将代码改为休眠一段时间而不是将int值增加1时,并行代码大约比非并行版本快4倍(CPU中的内核数)

for (int i = 0; i < 100; i++)
{
    ParallelOptions ops = new ParallelOptions();
    ops.MaxDegreeOfParallelism = Environment.ProcessorCount;

    var partitioner = Partitioner.Create<int>(Enumerable.Range(1, 5000));

    var watch = Stopwatch.StartNew();
    Parallel.ForEach<int>(partitioner, ops, x => { Thread.Sleep(1); });
    watch.Stop();
    Console.WriteLine("Parallel: {0}", watch.Elapsed.TotalSeconds);

    watch = Stopwatch.StartNew();
    foreach (var x in Enumerable.Range(1, 5000))
    {
        Thread.Sleep(1);
    }
    watch.Stop();
    Console.WriteLine("Non-parallel: {0}\n", watch.Elapsed.TotalSeconds);
}
for(int i=0;i<100;i++)
{
ParallelOptions ops=新的ParallelOptions();
ops.MaxDegreeOfParallelism=Environment.ProcessorCount;
var partitioner=partitioner.Create(Enumerable.Range(15000));
var watch=Stopwatch.StartNew();
Parallel.ForEach(分区器,ops,x=>{Thread.Sleep(1);});
看,停;
WriteLine(“Parallel:{0}”,watch.eassed.TotalSeconds);
watch=Stopwatch.StartNew();
foreach(可枚举范围(15000)中的var x)
{
睡眠(1);
}
看,停;
WriteLine(“非并行:{0}\n”,watch.appeased.TotalSeconds);
}
前10项结果:

平行线:1.2887589 非平行线:5.0020569

平行线:1.277047 非平行线:5.0011116

平行电话:1.2790631 非平行线:5.0001498

平行电话:1.2770644 非平行线:5.0052016

平行线:1.2770013 非平行线:5.0021479

平行线:1.2770031 非平行线:5.0001927

平行线:1.279937 非并行:5.0062141

同期:1.2819909 非平行线:5.0171945

并行:1.2780496 非平行线:5.0071667

平行线:1.2821714 非平行线:5.0082108

平行线:1.2777875
非并行:5.0152099

启动线程时是否没有costDebug模式编译?因为在优化时,代码什么都不做,甚至可能被优化掉。决定哪一个更快没有意义:什么都不做或者启动线程什么都不做;只有当你有大量的工作要做时,雇佣员工才有意义。看看公认的答案,这也不是一个好例子。如果您和
ThreadPool
停止限制使用的线程数(通过不强制
MaxDegreeOfParallelism
成为
ProcessorCount
并添加类似
ThreadPool.SetMinThreads(100,4);
)的内容,那么您将获得远远超过CPU内核数的加速。