为什么并行代码更慢?

时间:2014-07-08 13:50:43

标签: c# parallel-processing

我用大数组创建了一个简单的测试,并且我在

的parallel和normal之间得到了很大的区别
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var rn = new Random(541);

            var tmStart = DateTime.Now;
            int[,] a = new int[2048, 2048];
            for (int i = 0; i < 2048; i++)
                for (int j = 0; j < 2048; j++)
                    a[i, j] = rn.Next();
            var tmEnd = DateTime.Now - tmStart;
            Console.WriteLine("Normal..: {0}",tmEnd.ToString());

            tmStart = DateTime.Now;
            a = new int[2048, 2048];
            Parallel.For(0, 2048, i =>
                {
                    for (int j = 0; j < 2048; j++)
                        a[i, j] = rn.Next();
                });
            tmEnd = DateTime.Now - tmStart;
            Console.WriteLine("Parallel: {0}", tmEnd.ToString());
        }
    }
}

流程的时间:

  

正常..:00:00:00.1250071
  平行:00:00:00.3880222

为什么这种差异如此之大?

我想象如果你使用多个线程,它会更快......

2 个答案:

答案 0 :(得分:2)

当你并行化任务时,你会有一些&#34;上下文切换&#34;从SO到管理各种任务所花费的时间。如果单个任务没有做一些计算上有趣的事情,那么你就不会从多线程中获得任何好处。您应该选择其他一些示例,其中每个任务都在吃一些CPU周期(即使循环也可以用作练习目的)。

答案 1 :(得分:1)

您的基准测试存在一些问题:

  1. 您的任务非常小,以至于线程开销很大。
  2. 您使用Random的实例破坏了线程规则。谁知道这有什么影响?
  3. 你的时间安排很粗糙。
  4. 这是一个更好的基准测试,可以更快地显示代码的并行版本:

    using System;
    using System.Diagnostics;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            const int N = 1024;
    
            static void Main(string[] args)
            {
                int[,] a = new int[N, N];
    
                var stopwatch = Stopwatch.StartNew();
                for (int i = 0; i < N; i++)
                    for (int k = 0; k < N; k++)
                        for (int j = 0; j < N; j++)
                            a[i, j] = i+j;
                Console.WriteLine("Normal..: {0}", stopwatch.ElapsedMilliseconds);
    
                stopwatch = Stopwatch.StartNew();
                Parallel.For(0, N, i =>
                {
                    for (int k = 0; k < N; k++)
                        for (int j = 0; j < N; j++)
                            a[i, j] = i+j;
                });
                Console.WriteLine("Parallel: {0}", stopwatch.ElapsedMilliseconds);
    
                Console.ReadLine();
            }
        }
    }
    

    这是使用随机数生成器的那个:

    using System;
    using System.Diagnostics;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            const int N = 512;
    
            static void Main(string[] args)
            {
                int[,] a = new int[N, N];
    
                var stopwatch = Stopwatch.StartNew();
                var rng = new Random();
                for (int i = 0; i < N; i++)
                    for (int k = 0; k < N; k++)
                        for (int j = 0; j < N; j++)
                            a[i, j] = rng.Next();
                Console.WriteLine("Normal..: {0}", stopwatch.ElapsedMilliseconds);
    
                stopwatch = Stopwatch.StartNew();
                Parallel.For(0, N, i =>
                {
                    var rngpar = new Random();
                    for (int k = 0; k < N; k++)
                        for (int j = 0; j < N; j++)
                            a[i, j] = rngpar.Next();
                });
                Console.WriteLine("Parallel: {0}", stopwatch.ElapsedMilliseconds);
    
                Console.ReadLine();
            }
        }
    }