我知道有几个人问了类似这样的问题,但我找不到任何可以让我理解为什么它变慢的回复。
因此,我为自己对Visual Studio 2013中的线程对象的理解制作了一个小程序控制台程序。我的CPU是Intel Core i7,供应可以使用多个线程。
我的代码:
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);
}
}
}
}
结果图片:
我们可以清楚地看到多踩踏过程是完全随机的,而单个踩踏过程只是按下另一个,但我不认为这会对速度产生影响。
起初,我认为我的线程比运行程序所需的过程要大,但是在更换一个更大的进程之后,单步行仍然是最快的。那么,我是否会错过多线程的概念?还是正常的那么慢?
答案 0 :(得分:72)
请注意Process
写入控制台(基本上什么都不做),并且输出到控制台(这里作为一种共享资源)很慢,需要与其他线程同步
据我了解,您使用的并行化会产生巨大的开销,但不会加速,因为线程显然主要是等待其他进程完成写入控制台。
答案 1 :(得分:44)
来自官方Console文档
使用这些流的I / O操作是同步的,这意味着 多个线程可以读取或写入流。这个 表示通常异步的方法,例如 TextReader.ReadLineAsync,如果对象同步执行 表示控制台流
这意味着控制台类处理线程同步,因此如果线程A和线程B正在尝试写入控制台,控制台将处理它们,并且只有一个时间能够写入。它背后的 处理逻辑 是需要更长时间的原因
的更新强>
我建议你看一下Parallel.ForEach
答案 2 :(得分:4)
还要考虑的另一件事是:您正在遭受线程创建和加入的开销。此外,您可以通过使用线程池进行轻微的性能升级,请看一下:
答案 3 :(得分:4)
OK!对阿萨和科多来说,把我的想法放在了正确的位置!我最终制作了一个小的控制台程序,显示每个人非常苛刻。使用重型处理时,最终多线程速度更快。只需阅读我的代码,你就会轻松理解。
结果:
代码:
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());
}
}
}
答案 4 :(得分:0)
当且仅当处理器是瓶颈时,应用程序将更快地使用多个线程。有时您的磁盘或RAM是瓶颈。通常它是数据库或外部服务。在这些情况下,添加多个线程不太可能使代码运行得更快,相反,由于额外的同步,它通常会降低执行速度。
如果您想让代码运行得更快,首先必须检查是什么让它运行缓慢。 描述您的代码。找到瓶颈。
请记住Premature optimization is the root of all evil
在您的情况下,瓶颈 - 阻止所有操作的单个访问最多的资源 - 是控制台输出流。它有一个单一的实例,它的工作相对较慢。即使单个核心也不会100%使用,以尽快打印。
答案 5 :(得分:-1)
如果您删除下面的行,您的多线程会更快。
Console.Write(procName);
因为操作系统将Console视为共享资源,并且只有一个线程可以立即使用共享资源。因此,在这种情况下,mutlithread加速将像一个单独的线程,但多线程会增加一些额外的线程管理开销没有性能提升。