代码之家  ›  专栏  ›  技术社区  ›  Faruz

何时使用平行。为什么?

  •  7
  • Faruz  · 技术社区  · 14 年前

    我知道当秩序对我来说不重要的时候-我会用它。

    但是有没有关于使用并行机的开销的测试呢?意思是,如果我的循环只运行了10次(而且执行的逻辑很少),我应该避免并行吗?有什么经验法则吗?

    3 回复  |  直到 14 年前
        1
  •  5
  •   Mark Byers    14 年前

    我会避免使用 Parallel.For

    编写并发运行的代码通常比编写单线程代码更难。此外,如果由于并发性问题而出错,则很难对其进行调试。例如,错误可能只是偶尔出现,而且不容易重现。除非您对提高性能有特殊需求,否则我建议您保持简单,并在单个线程上使用普通循环。

        2
  •  2
  •   Dmitry Stepanov    7 年前

    这个平行。用于循环使用ThreadPool通过在循环的每次迭代中调用一次委托来执行循环中的工作。

    public static void MyParallelFor(int inclusiveLowerBound, int exclusiveUpperBound, Action<int> body)
    {
        // Get the number of processors, initialize the number of remaining
        // threads, and set the starting point for the iteration.
        int numProcs = Environment.ProcessorCount;
        int remainingWorkItems = numProcs;
        int nextIteration = inclusiveLowerBound;
        using (ManualResetEvent mre = new ManualResetEvent(false))
        {
            // Create each of the work items.
            for (int p = 0; p < numProcs; p++)
            {
                ThreadPool.QueueUserWorkItem(delegate
                {
                    int index;
                    while ((index = Interlocked.Increment(ref nextIteration) - 1) < exclusiveUpperBound)
                        body(index);
    
                    if (Interlocked.Decrement(ref remainingWorkItems) == 0)
                        mre.Set();
                });
            }
            // Wait for all threads to complete.
            mre.WaitOne();
        }
    }
    

    平行。用于返回ParallelLoopResult值类型,其中包含有关已完成循环的详细信息。其重载之一如下:

    public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int> body);
    

    重要的是要认识到并行执行并不总是比串行执行快。要决定是否使用并行,您必须估计循环每次迭代将执行的工作负载。如果由循环执行的实际工作相对于线程同步成本而言较小,则最好使用普通循环。

    static void Main(string[] args)
    {
        Action<int> action = new Action<int>(SimpleMethod);
    
        // ordinary For loop performance estimation
        var sw = Stopwatch.StartNew();
    
        for(int i = 0; i < 1000; i++)
            action(i);
    
        Console.WriteLine("{0} sec.", sw.Elapsed.TotalSeconds);
    
        // parallel For loop performance estimation
        sw = Stopwatch.StartNew();
    
        Parallel.For(0, 1000, action);
    
        Console.WriteLine("{0} sec.", sw.Elapsed.TotalSeconds);
    }
    
    static void SimpleMethod(int index)
    {
        int d = 1;
        int result = index / d;
    }
    

    输出:

    0.0001963 sec.
    0.0346729 sec.
    
        3
  •  0
  •   Pavel Radzivilovsky    14 年前

    Threads are evil

    并行化有助于提高性能。应用程序性能优化是软件设计中最违反直觉的事情之一,应该非常小心地进行,使用正确的度量工具,否则看起来会很有趣。