繁体   English   中英

C ++中的多线程效率

[英]Multithreading efficiency in C++

我正在尝试用C ++学习线程,并且只是对它有一些问题(更具体地说是<thread>

假设这个代码运行的机器有4个内核,我应该将操作分成4个线程吗? 如果我要创建8个线程而不是4个线程,那么在4核心机器上运行速度会慢吗? 如果处理器具有超线程,如果我尝试使线程与物理内核或逻辑内核的数量相匹配怎么办?

我是否应该不担心机器的核心数量,并尝试尽可能多地创建线程?

如果这些问题已经得到解答,我深表歉意; 我一直在寻找有关使用<thread>线程的信息,这是在c11中引入的,因此我无法找到太多关于它的信息。

有问题的程序将运行许多独立的模拟。

如果有人对<thread>或者只是多<thread>有任何见解,我会很高兴听到它。

如果您在没有I / O的情况下执行纯计算 - 并且这些计算是独立的并且不依赖于在另一个线程中发生的其他计算的结果,则此类线程的最大数量应该是核心数(如果是,则可能少一个或两个系统还加载了其他任务)。

如果您正在进行网络I / O或类似操作,则肯定有更多线程。

如果你正在进行磁盘I / O,那么从磁盘读取的单个线程通常是最好的,因为从多个线程读取磁盘会导致磁盘上的读/写磁头移动,这会使速度变慢。

如果您使用线程来使代码更简单,那么线程数可能取决于您正在做什么。

它还取决于每个线程的“独立”程度。 如果他们需要以复杂的方式共享数据,那么共享/等待其他线程/等等可能会使更多线程更慢。

正如其他人所说,尝试使您的框架灵活并测试不同的选项。 最好是在多台机器上(除非你只有一种机器,你将运行你的代码)。

没有<threads.h>这样的东西,你的意思是<thread> ,C ++ 11中引入的线程支持库。

你的问题的唯一答案是“测试和看到”。 您可以使代码足够灵活,以便可以通过传递N参数(其中N是所需的线程数)来运行。

如果您受CPU限制,那么答案将与您绑定IO时的情况大不相同。

所以,测试一下! 供您参考, 此链接可能会有所帮助 如果你是认真的,那就去拿这本书吧 多线程,并发性等都是毛茸茸的主题。

与您正在运行的计算机相比,不要考虑所需的线程数。 只要您拥有以下流程,线程就是值得的:

答:有一些非常慢的操作,其余的过程不需要等待。

B:某些函数可以比另一个函数运行得更快,不需要内联执行。

C:有许多非顺序依赖I / O正在进行(Web服务器)。

这些只是启动线程有意义时的一些明显示例。 因此,您启动的线程数更多地取决于代码中弹出的这些方案的数量,而不是您希望运行的体系结构。 事实上,除非您正在运行一个真正需要优化的流程,否则您可能只需通过对您的体系结构进行基准测试,与您启动的线程数进行基准测试,从而获得额外性能的几个百分点,以及在现代计算机中,这个数字应该不会有太大变化。

让我们来看看I / O示例,因为它是最有益的场景。 我们假设某些程序需要通过网络与200个用户交互。 网络I / O非常慢。 比CPU慢几千倍。 如果我们依次处理每个用户,我们会浪费数千个处理器周期,只是等待来自第一个用户的数据。 我们难道不能一次处理多个用户的信息吗? 在这种情况下,由于我们有大约200个用户,而我们所等待的数据比我们能处理的数据慢1000倍(假设我们对这些数据进行的处理量很少),我们应该启动与操作系统允许的一样多的线程。 利用线程的Web服务器每秒可以服务数百人,而不是。

现在,让我们考虑一个I / O密集度较低的示例,其中说我们有几个函数依次执行,但是彼此独立,其中一些可能运行得更快,比如因为磁盘I / O在一个,而且没有另一个磁盘I / O. 在这种情况下,我们的I / O仍然相当快,但我们肯定会浪费处理时间等待磁盘赶上。 因此,我们可以启动一些线程,只是为了利用我们的处理能力,并最大限度地减少浪费的周期。 但是,如果我们启动尽可能多的线程,操作系统允许我们可能会为分支预测器等引发内存管理问题......并且在这种情况下启动太多线程实际上是次优的并且可以减慢程序的速度。 请注意,在这里,我从未提及机器有多少个核心! 对于不同架构进行优化并不重要,但如果针对一种架构进行优化,则对于大多数架构而言,您可能非常接近最佳。 再一次假设您正在处理所有合理的现代处理器。

我想大多数人会说大规模线程项目比c ++(go,scala,cuda)以外的语言更好地支持。 与数据并行相反的任务并行性在c ++中更好。 我会说你应该创建尽可能多的线程,但如果数据并行性与你的问题更相关,可以考虑使用cuda并在以后链接到项目的其余部分
注意:如果你看一下某种类型的系统监视器,你会注意到可能有超过8个线程在运行,我看着我的计算机,它同时运行了数百个线程所以不要过多担心开销。 我选择提及其他语言的主要原因是管理c ++或c中的许多线程往往非常困难且容易出错,我没有提到它因为c ++程序运行速度较慢(除非你使用cuda它可能会赢得' T)

假设这个代码运行的机器有4个内核,我应该将操作分成4个线程吗?

如果你的代码的某些部分可以并行运行,那么可以使它更快,但这是非常棘手的,因为加载线程并在它们之间切换数据需要花费大量时间。

如果我要创建8个线程而不是4个线程,那么在4核心机器上运行速度会慢吗?

这取决于它必须做的上下文切换。 有时执行会经常在线程之间切换,有时它不会,但这很难控制。 在任何情况下,它都不会比执行相同工作的4个线程运行得更快。

如果处理器具有超线程,如果我尝试使线程与物理内核或逻辑内核的数量相匹配怎么办?

超线程与具有更多内核的工作方式几乎相同。 当您注意到真实核心和执行核心之间的差异时,您将有足够的知识来解决警告。

我是否应该不担心机器的核心数量,并尝试尽可能多地创建线程?

不,线程很难管理,尽可能地避免它们。

有问题的程序将运行许多独立的模拟。

你应该看看openmp 它是C中的一个库,用于在程序可以拆分时并行化计算。 不要将并行与并发混淆。 并发只是多个线程协同工作,而并行是专门为加速您的应用程序。 也许openmp对你的东西来说太过分了,但是当你正在接近并行计算时,这是一件好事

关于超线程,让我评论一下我从经验中发现的内容。

在大密集矩阵乘法中,超线程实际上会提供更差的性能。 例如,Eigen和MKL都使用OpenMP(至少我使用它们的方式)并且在我的系统上获得更好的结果,该系统具有四个核心和超线程,仅使用四个线程而不是八个线程。 此外,在我自己的GEMM代码中获得比Eigen更好的性能我也使用四个线程而不是八个线程获得更好的结果。

但是,在我的Mandelbrot绘图代码中,使用OpenMP进行超线程(八个线程而不是四个线程)可以大大提高性能。 总体趋势(到目前为止)似乎是如果代码在OpenMP中使用schedule(static)很好地工作,那么超线程没有帮助甚至可能更糟。 如果代码使用schedule(dynamic)更好地工作,那么超线程可能会有所帮助。

换句话说,到目前为止,我的观察结果是,如果每个线程的运行时间可以变化很多,则超线程可以提供帮助。 如果每个线程的运行时间是恒定的,那么它甚至可能使性能变差。 但是你必须测试并查看每个案例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM