【问题标题】:Parallel.For vs forParallel.For vs for
【发布时间】:2013-05-27 06:05:15
【问题描述】:

我有一个 Parallel.For 和一个常规 for 循环做一些简单的算术,只是为了对 Parallel.For 进行基准测试

我的结论是,常规 for 在我的 i5 笔记本处理器上更快。

这是我的代码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int Iterations = int.MaxValue / 1000;
            DateTime StartTime = DateTime.MinValue;
            DateTime EndTime = DateTime.MinValue;

            StartTime = DateTime.Now;
            Parallel.For(0, Iterations, i =>
            {
                OperationDoWork(i);
            });
            EndTime = DateTime.Now;
            Console.WriteLine(EndTime.Subtract(StartTime).ToString());

            StartTime = DateTime.Now;
            for (int i = 0; i < Iterations; i++)
            {
                OperationDoWork(i);
            }
            EndTime = DateTime.Now;
            Console.WriteLine(EndTime.Subtract(StartTime).ToString());

            StartTime = DateTime.Now;
            Parallel.For(0, Iterations, i =>
            {
                OperationDoWork(i);
            });
            EndTime = DateTime.Now;
            Console.WriteLine(EndTime.Subtract(StartTime).ToString());

            StartTime = DateTime.Now;
            for (int i = 0; i < Iterations; i++)
            {
                OperationDoWork(i);
            }
            EndTime = DateTime.Now;
            Console.WriteLine(EndTime.Subtract(StartTime).ToString());
        }

        private static void OperationDoWork(int i)
        {
            int a = 0;
            a += i;
            i = a;
            a *= 2;
            a = a * a;
            a = i;
        }
    }
}

这些是我的结果。重复时变化不大:

00:00:03.9062234
00:00:01.7971028
00:00:03.2231844
00:00:01.7781017

那么为什么要使用 Parallel.For 呢?

【问题讨论】:

  • 如果有记忆,Parallel.For 并不总是将工作分解为多个线程,它可能会在单个线程上运行整个工作。您可能正在查看在轻量级工作上使用 Parallel 方法所涉及的开销,其中在线程上编组工作的成本很高。
  • 您在每次迭代中所做的实际工作并不多,因此创建、管理和合并线程的成本远高于您从并行处理中获得的收益。 Parallel.For 只有在你每轮做更多耗时的事情时才会更快。
  • Have a look at this recent answer where I make some detailed timings。如果您像我在那个答案中那样使用PartitionerParallel.For() 确实适用于小型循环体。

标签: c# for-loop parallel-processing


【解决方案1】:

当第一次深入研究多线程时,最常见的错误之一是认为多线程是Free Lunch

实际上,将您的操作拆分为多个较小的操作,然后这些操作可以并行运行,这将需要一些额外的时间。如果同步不好,您的任务可能会花费更多时间,等待其他任务释放它们的锁。

因此;并行化不值得花时间/麻烦,因为每个任务都要做很少的工作,OperationDoWork 就是这种情况。

编辑:

考虑尝试一下:

    private static void OperationDoWork(int i)
    {
        double a = 101.1D * i;
        for (int k = 0; k < 100; k++)
            a = Math.Pow(a, a);
    }

根据我的基准测试,for 在我的 Core2Duo CPU 上平均需要 5.7 秒,而Parallel.For 需要 3.05 秒(加速 == ~1.87)。
在我的 Quadcore i7 上,for 平均为 5.1 秒,Parallel.For 平均为 1.38 秒(加速 == ~3.7)。

这个修改后的代码可以很好地适应可用物理内核的数量。 Q.E.D.

【讨论】:

    【解决方案2】:

    并行处理具有组织开销。把它想象成有 100 个任务和 10 个人来完成它们。让 10 个人为您工作并不容易,除了实际执行这 100 项任务之外,只需组织谁来做那些花费时间的事情。

    因此,如果您想并行执行某些操作,请确保组织并行性的工作量与实际工作量相比非常小这样做是有意义的。

    【讨论】:

    • 很好的解释。 “我一个人做的更快!”可能是每个人都至少有过一次“团队合作”的经历。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 2011-02-28
    相关资源
    最近更新 更多