gpt4 book ai didi

c# - 线程与并行性能

转载 作者:行者123 更新时间:2023-12-03 13:16:56 25 4
gpt4 key购买 nike

我正在努力了解线程 Parallel.For 之间的区别。我创建了两个函数,一个使用Parallel.For其他调用的线程。调用 10个线程似乎比更快,有人可以解释吗? 线程将使用系统中可用的多个处理器(以并行执行)还是只是在引用LR时对进行切片?

public static bool ParallelProcess()
{
Stopwatch sw = new Stopwatch();

sw.Start();
Parallel.For(0, 10, x =>
{
Console.WriteLine(string.Format("Printing {0} thread = {1}", x,
Thread.CurrentThread.ManagedThreadId));
Thread.Sleep(3000);
});
sw.Stop();
Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.Seconds));

return true;
}

public static bool ParallelThread()
{
Stopwatch sw = new Stopwatch();

sw.Start();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(Thread1));
t.Start();
if (i == 9)
t.Join();
}
sw.Stop();
Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.Seconds));

return true;
}

private static void Thread1()
{
Console.WriteLine(string.Format("Printing {0} thread = {1}", 0,
Thread.CurrentThread.ManagedThreadId));
Thread.Sleep(3000);
}

在以下方法中调用Parallel.For时,需要花费两次时间,然后执行线程。
Algo.ParallelThread(); //took 3 secs
Algo.ParallelProcess(); //took 6 secs

最佳答案

您在这里有很多出错的地方。

(1)请勿使用sw.Elapsed.Seconds,此值是int,并且(显然)会截断时间的小数部分。不过,更糟糕的是,如果您有一个需要61秒才能完成的过程,它将像时钟秒针一样报告1。相反,您应该使用sw.Elapsed.TotalSeconds,它以double的形式报告,并显示总秒数,无论多少分钟或几小时等等。

(2)Parallel.For使用线程池。这显着减少(甚至消除了)创建线程的开销。每次调用new Thread(() => ...)时,您都会分配1MB以上的RAM并消耗宝贵的资源,然后再进行任何处理。

(3)您正在使用Thread.Sleep(3000);来人为加载线程,这意味着您正在掩盖创建具有大量 sleep 的线程所花费的实际时间。

(4)默认情况下,Parallel.For受CPU内核数的限制。因此,当您运行10个线程时,工作被分为两个步骤-意味着Thread.Sleep(3000);被连续两次运行,因此运行了6秒钟。 new Thread方法一次性运行所有线程,这意味着要花3秒钟多的时间,但是Thread.Sleep(3000);再次浪费了线程的启动时间。

(5)您还正在处理CLR JIT问题。第一次运行代码时,启动成本非常高。让我们更改代码以删除 sleep 并正确加入线程:

public static bool ParallelProcess()
{
Stopwatch sw = new Stopwatch();

sw.Start();
Parallel.For(0, 10, x =>
{
Console.WriteLine(string.Format("Printing {0} thread = {1}", x, Thread.CurrentThread.ManagedThreadId));
});
sw.Stop();
Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.TotalMilliseconds));

return true;
}

public static bool ParallelThread()
{
Stopwatch sw = new Stopwatch();

sw.Start();
var threads = Enumerable.Range(0, 10).Select(x => new Thread(new ThreadStart(Thread1))).ToList();
foreach (var thread in threads) thread.Start();
foreach (var thread in threads) thread.Join();
sw.Stop();

Console.WriteLine(string.Format("Time in secs {0}", sw.Elapsed.TotalMilliseconds));

return true;
}

private static void Thread1()
{
Console.WriteLine(string.Format("Printing {0} thread = {1}", 0, Thread.CurrentThread.ManagedThreadId));
}

现在,要摆脱CLR/JIT的启动时间,让我们运行如下代码:
ParallelProcess();
ParallelThread();
ParallelProcess();
ParallelThread();
ParallelProcess();
ParallelThread();

我们得到的时间是这样的:

以秒为单位的时间3.8617
以秒为单位的时间4.7719
时间以秒为单位0.3633
以秒为单位的时间1.6332
以秒为单位的时间0.3551
以秒为单位的时间1.6148

与第二和第三次运行相比,开始运行时间要糟糕得多,而第二和第三次运行要一致得多。

结果是,运行 Parallel.For的速度比调用 new Thread的速度快4至5倍。

关于c# - 线程与并行性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52158271/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com