【问题标题】:Why parallel code is slower? [duplicate]为什么并行代码更慢? [复制]
【发布时间】:2014-07-08 13:50:42
【问题描述】:

我用大数组创建了一个简单的测试,我发现并行 for 和普通 for 之间有很大的不同

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

为什么差别这么大?

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

【问题讨论】:

  • 尝试使用更大的数组。创建线程存在开销,因此一旦达到足够的工作负载,并行可能会更快
  • 除了变慢之外,您还违反了线程规则。你需要序列化对rn的访问。
  • 这个基准有很多问题,试图挽救它真的没有什么意义......
  • 至少使用System.Diagnostics.Stopwatch 作为您的计时,并确保您不要在附加调试器和发布模式下运行,还要注意x86 和x64 会产生彼此不同的计时。以非定时运行开始多次运行以预热代码,然后平均运行时间。而且,它们不是大数组。
  • @Alexandre 并行化代码并不是人们认为的灵丹妙药。要问的最简单的问题是:多只手可以做轻的工作吗?如果您可以自己更快地完成一项任务,那就别管它了。如果一项任务可以从许多人的工作中受益,再加上管理这些人的开销,那么就这样做。所有这一切的决定因素是领域知识。您将知道您的代码何时可以从中受益,例如在昂贵的表上一次执行 3 个数据库调用,无论它们的成本有多高。逐案处理。

标签: c# parallel-processing


【解决方案1】:

当您并行化任务时,您需要从 SO 花费一些“上下文切换”时间来管理各种任务。如果单个任务没有做一些计算上有趣的事情,您将不会从多线程中感受到任何好处。您应该选择其他一些示例,其中每个任务都占用一些 CPU 周期(即使是循环也可以作为练习目的)。

【讨论】:

  • s/paralize/parallelize/
  • @david.pfx 我总是对“paralise”的意外使用发笑,因为有很多次我试图并行化代码却发现我把它瘫痪了......哈哈
  • @AdamHouldsworth: s/paralise/paralyse/ ...如果我不会编程,我总是可以拼写。
  • @david.pfx 哈哈,并行的手指肌肉记忆 ;-)
  • :) 抱歉,错误已更正
【解决方案2】:

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

  1. 您的任务非常小,以至于线程开销很大。
  2. 您使用Random 的实例破坏了线程规则。谁知道这会产生什么影响?
  3. 你的时机很粗略。

这里有一个更好的基准,显示代码的并行版本更快:

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();
        }
    }
}

【讨论】:

  • 哇,我犯了几个错误,很好,现在我学会了! .... 谢谢!
猜你喜欢
  • 1970-01-01
  • 2012-11-26
  • 2018-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-18
  • 2013-08-08
  • 2017-02-07
相关资源
最近更新 更多