C++ 多线程与多处理

C++ 多线程与多处理,c++,multithreading,parallel-processing,multiprocessing,C++,Multithreading,Parallel Processing,Multiprocessing,我是这种编程新手,需要你的观点 我必须构建一个应用程序,但我不能让它计算得足够快。我已经尝试过Intel TBB,它很容易使用,但我从未使用过其他库 在多处理器编程中,我正在阅读有关OpenMP和Boost的多线程技术,但我不知道它们的优缺点 在C++中,多线程编程何时与多处理器编程相比是有利的,反之亦然?哪种方法最适合于繁重的计算或启动许多任务?当我们构建用它们设计的应用程序时,它们的优缺点是什么?最后,哪个库最适合使用?多线程的意思就是运行多个线程。这可以在单处理器系统或多处理器系统上完成

我是这种编程新手,需要你的观点

我必须构建一个应用程序,但我不能让它计算得足够快。我已经尝试过Intel TBB,它很容易使用,但我从未使用过其他库

在多处理器编程中,我正在阅读有关OpenMP和Boost的多线程技术,但我不知道它们的优缺点


在C++中,多线程编程何时与多处理器编程相比是有利的,反之亦然?哪种方法最适合于繁重的计算或启动许多任务?当我们构建用它们设计的应用程序时,它们的优缺点是什么?最后,哪个库最适合使用?

多线程的意思就是运行多个线程。这可以在单处理器系统或多处理器系统上完成

在单处理器系统上,当运行多个线程时,对计算机同时执行多个任务(即多任务)的实际观察是一种错觉,因为真正发生在引擎盖下的是有一个软件调度器在单CPU上执行时间切片。因此,在任何给定的时间只有一个任务发生,但调度程序在任务之间切换的速度足够快,因此您永远不会注意到有多个进程、线程等在争夺同一CPU资源

在多处理器系统上,减少了时间切片的需要。时间切片效应仍然存在,因为现代操作系统可能有数百个线程争夺两个或更多处理器,而且线程数量与可用处理内核数量之间通常不存在1对1的关系。因此,在某个时刻,一个线程必须停止,另一个线程在两个线程共享的CPU上启动。这同样由操作系统的调度程序处理。也就是说,与单处理器系统不同,多处理器系统可以同时发生两件事情


最后,这两种范式在某种意义上确实是正交的,即当您想要异步运行两个或多个任务时,就需要多线程,但由于时间切片,您不一定需要多处理器系统来完成这一点。如果您正在尝试运行多个线程,并且正在执行高度并行的任务(即,尝试求解整数),那么是的,您可以在一个问题上抛出的内核越多越好。您不一定需要线程和处理内核之间的1对1关系,但同时,您也不希望剥离太多线程,最终导致大量空闲线程,因为它们必须等待在一个可用的CPU内核上进行调度。另一方面,如果并行任务需要某些顺序组件,即一个线程将等待另一个线程的结果,然后才能继续,那么您可以使用某种类型的屏障或同步方法运行更多线程,以便需要空闲的线程不会使用CPU时间旋转,只有需要运行的线程在争夺CPU资源。

回答第一个问题: 最好的方法是在代码中只使用多线程技术,直到您达到这样的程度,即使这样也不会给您带来足够的好处。假设操作系统将处理委托给多个处理器(如果它们可用)

如果您实际上正在处理一个多线程还不够的问题,即使使用多个处理器(或者如果您运行的操作系统没有使用多个处理器),那么您可能会担心如何获得更多的功能。这可能意味着通过网络将进程衍生到其他机器


我没有使用TBB,但是我使用了IPP,并且发现它是高效的和设计良好的。Boost是可移植的。

我认为@Jason的优秀答案中应该添加一些要点

首先,即使在单个处理器上,多线程也不总是一种幻觉——有些操作并不涉及处理器。这些主要是I/O磁盘、网络、终端等。此类操作的基本形式是阻塞同步,即您的程序等待操作完成,然后继续。等待时,CPU切换到另一个进程/线程

如果您在这段时间内有任何可以做的事情(例如等待用户输入时的后台计算、服务另一个请求等),您基本上有两个选择:

  • 使用异步I/O:调用非阻塞I/O,为其提供回调函数,告诉它“完成后调用此函数”。调用立即返回,I/O操作在后台继续。你继续做其他的事情

  • 使用多线程:每种任务都有一个专用线程。当一个等待阻塞I/O调用时,另一个继续

这两种方法都是困难的编程范例,每种方法都有其优缺点

  • 使用异步I/O时,程序逻辑的逻辑不太明显,难以遵循和调试。但是,您可以避免线程安全问题
  • 对于线程,挑战在于编写程序。线程安全性故障是很难重现的严重错误。过度使用锁定实际上会导致性能下降,而不是提高性能
(来到多重处理)

多线程之所以在Windows上流行,是因为在Windows上操作进程(创建进程、上下文切换等)相当繁重,而线程要轻得多(至少在我使用Win2K时是这样)

在Linux/Unix上,进程要轻得多。另外,Linux上的(AFAIK)线程实际上是作为一种进程在内部实现的,因此有