为什么我的multithreading比我的单线程慢?
我知道有几个人问了类似的问题,但是我找不到任何会让我明白为什么慢的问题。
所以,为了自己理解Visual Studio 2013中的线程对象,我制作了一个控制台程序。我的CPU是Intel Core i7,可以使用multithreading。
我的代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.Diagnostics; namespace ConsoleApplication1 { class Program { static TimeSpan MTTime; static TimeSpan STTime; static void Main(string[] args) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); Console.WriteLine(Environment.NewLine + "---------------Multi Process-------------" + Environment.NewLine); Thread th1 = new Thread(new ParameterizedThreadStart(Process)); Thread th2 = new Thread(new ParameterizedThreadStart(Process)); Thread th3 = new Thread(new ParameterizedThreadStart(Process)); Thread th4 = new Thread(new ParameterizedThreadStart(Process)); th1.Start("A"); th2.Start("B"); th3.Start("C"); th4.Start("D"); th1.Join(); th2.Join(); th3.Join(); th4.Join(); stopwatch.Stop(); MTTime = stopwatch.Elapsed ; Console.WriteLine(Environment.NewLine + "---------------Single Process-------------" + Environment.NewLine); stopwatch.Reset(); stopwatch.Start(); Process("A"); Process("B"); Process("C"); Process("D"); stopwatch.Stop(); STTime = stopwatch.Elapsed; Console.Write(Environment.NewLine + Environment.NewLine + "Multi : "+ MTTime + Environment.NewLine + "Single : " + STTime); Console.ReadKey(); } static void Process(object procName) { for (int i = 0; i < 100; i++) { Console.Write(procName); } } } }
结果图像:
我们可以清楚地看到,多重制作过程是完全随机的,单个制作过程完全是依次进行,但我认为这对速度没有影响。
起初,我认为我的线程比运行程序所需要的程序还要大,但是在改变了一个更大的程序之后,单个线程仍然是最快的。 那么,我错过了multithreading的概念吗? 还是正常呢?
从官方Console文档
使用这些stream的I / O操作是同步的,这意味着多个线程可以读取或写入stream。 这意味着如果对象表示控制台stream,则通常是asynchronous的方法(如TextReader.ReadLineAsync)将同步执行
这意味着控制台类处理线程同步,所以如果线程A和线程B试图写入控制台,控制台将处理它们,只有一个时间将能够写入。 它背后的处理逻辑是花费更长时间的原因
UPDATE
我build议你看看Parallel.ForEach
请注意, Process
写入控制台(并且基本上什么都不做),并且输出到控制台(在这里作为一种共享资源)是慢的,需要与其他线程同步。
据我的理解,你使用的并行会产生巨大的开销,但是不会加速,因为所有的线程显然都在等待其他进程完成写入控制台。
还有一件事要考虑:你正在遭受线程创build和连接的开销。 此外,你可能会通过使用线程池来获得一些性能提升,请看这里:
好! thx到Assa和Codor把我的想法放在正确的地方! 我最终制作了一个小小的控制台程序,显示每一个非常克莱尔。 最后多层处理是一个很快很多,当使用重处理的东西。 只要阅读我的代码,你就会轻松理解。
结果:
代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.Diagnostics; namespace ConsoleApplication1 { class Program { //Timer for speed guidance static Stopwatch stopwatch; //Data i use for generate time static List<int> timeData; static void Main(string[] args) { stopwatch = new Stopwatch(); timeData = new List<int> { 1000, 800, 200, 700, 600, 300, 800, 100, 200, 300, 655, 856, 695, 425 }; ////-------------------------- SINGLE THREAD ------------------------------///// Console.WriteLine("-------------------------------------------------"); Console.WriteLine(" Single Threading Process "); Console.WriteLine("-------------------------------------------------"); Console.WriteLine(" Process Time Thread ID "); Console.WriteLine("-------------------------------------------------"); stopwatch.Reset(); stopwatch.Start(); //For each normal that use only 1 thread foreach(int i in timeData) { Process(i); } stopwatch.Stop(); //Total time that the program take for making the process happen Console.WriteLine("*Total : " + stopwatch.Elapsed ); ////-------------------------- Mulit Multiple ------------------------------///// Console.WriteLine("-------------------------------------------------"); Console.WriteLine("-------------------------------------------------"); Console.WriteLine(" Multi Threading Process "); Console.WriteLine("-------------------------------------------------"); Console.WriteLine(" Process Time Thread ID "); Console.WriteLine("-------------------------------------------------"); stopwatch.Reset(); stopwatch.Start(); //for each thats use Multiple thread fr the process (can be made with parallel.invoke or Task Library or Thread Library) Parallel.ForEach(timeData, (i) => Process(i)); //Total time that the program take for making the process happen Console.WriteLine("*Total : " + stopwatch.Elapsed); Console.WriteLine("-------------------------------------------------"); Console.ReadKey(); } // Methode for sumulating long processing static void Process( int time) { stopwatch.Reset(); stopwatch.Start(); //sleep time simulate the IO portion of the process Thread.Sleep(time); // The loop simulate de algoritme type of precessing for (int i = 0; i < time*1000000; i++){} stopwatch.Stop(); Console.WriteLine( stopwatch.Elapsed + " " + Thread.CurrentThread.ManagedThreadId.ToString()); } } }
还有多less人会想到:让我们使用更多的线程,我们的代码将工作得更快。 这种方式不行。
一般来说,当且仅当处理器是一个瓶颈时,你的代码在multithreading下工作会更快。 有时你的磁盘或RAM是瓶颈。 大多数情况下,这是一个数据库或外部服务。 在这种情况下添加多个线程不太可能使代码运行得更快,相反,由于额外的同步,通常会减慢执行速度。
如果你想使你的代码运行得更快,你必须首先检查是什么让它运行缓慢 。 剖析你的代码。 find瓶颈。
请记住, 不成熟的优化是万恶之源
在您的情况下,瓶颈 – 阻止所有操作的单个访问最多的资源 – 是控制台输出stream。 它有一个实例,工作相对较慢。 即使是一个单一的内核也不能百分百地尽可能快地打印。