对于使用四核处理器的所有内核,我需要在我的代码中进行更改的是添加对多线程的支持,还是由操作系统本身处理。我有 FreeBSD,我使用的语言是 C++。我想为我的应用程序提供至少 90% 的完整 CPU 周期。
7 回答
您需要某种形式的并行性。多线程或多处理会很好。
通常,多线程比多进程更容易处理(因为它们可以访问共享数据) 。但是,通常,多线程比多进程更难处理(因为它们访问共享数据) 。而且,是的,我是故意写这个的。
如果你有 SIMD 的场景,Ninefingers 建议看看 OpenMP 也很不错。(如果您不知道 SIMD 的含义,请参阅下面 Ninefingers 的有用评论。)
对于 C++ 中的多线程应用程序,我建议您使用Boost.Thread,它可以帮助您充分发挥四核机器的潜力。
至于更改代码,您可能需要考虑使事物尽可能不可变。线程之间的状态转换更难调试。有很多事情可能以意想不到的方式发生。请参阅此SO 线程。
除了线程之外,这里没有提到的另一个选项是使用 OpenMP-fopenmp
和libgomp
库,我已经在我的 FreeBSD 8 系统上安装了这两者。
这些为您提供#pragma
指令以并行化某些循环、while 语句等,即您可以并行化的位。它会为您处理线程和 cpu 关联。请注意,这是一个通用解决方案,因此可能不是并行化的最佳方式,但它允许您并行化某些例程。
看看这个:https ://computing.llnl.gov/tutorials/openMP/
至于使用线程/进程本身,某些例程和工作方式适合它。你能把任务分解成这样吗?fork() 进程或创建线程是否有意义?如果是这样,就这样做,但如果不是,不要仅仅因为它就试图强制你的应用程序是多线程的。我通常给出的一个例子是最大公约数算法 - 它在传统实现中一直依赖于前一步,因此难以并行。
另请注意,众所周知,对于某些算法,对于您正在并行执行的任何小值,并行化实际上会更慢,因为尽管作业完成得更快,但分叉和连接(即线程或进程)的相关时间成本实际上将时间推到串行实现之上。
我认为您唯一的选择是运行多个线程。如果您的应用程序是单线程的,那么它只会在一个内核上运行(一次),但如果您有更多线程,它们可以同时运行。
您需要通过使用线程来为您的应用程序添加对并行性的支持。
一旦您支持并行性,就由操作系统将您的线程分配给 CPU 内核。
我想为我的应用程序提供至少 90% 的完整 CPU 周期。
为什么?你的芯片不够热?
说真的,世界专家需要数十甚至数百小时来并行化和负载平衡一个应用程序,以便它使用所有四个内核的 90%。 您的 CPU 已经付费,无论您是否使用它,它的成本都是一样的。(实际上,如果你不使用它,从电气上讲,它的运行成本会略低一些。)你的时间值多少钱?您愿意投入多少小时以更有效地利用可能花费您 300 美元并且可能大部分时间都处于闲置状态的资源?
通过并行性获得加速是可能的,但在人力时间上是昂贵的。你需要一个很好的理由来证明它的合理性。(学习如何是一个足够好的理由。)
我所知道的所有关于并行编程的好书都是针对 C++ 以外的语言的,这是有充分理由的。如果您想了解有关并行性的有趣内容,请查看pH 中的 Implicit Parallel Programmin或ML中的 Concurrent Programming 或Fortress Project。
我认为您应该看的第一件事是您的应用程序及其算法是否适合并行执行(或者可能作为一组可以独立处理的串行任务)。如果不是这种情况,则很难将其多线程化或将其分解为并行进程,您可能需要考虑修改它的工作方式。
一旦确定您将能够从并行处理中受益,您就可以选择使用多个进程或线程。选择很大程度上取决于您的应用程序的性质以及并行进程的独立程度。由于线程在同一个进程中,因此更容易在线程之间协调和共享数据,但开发和调试也更具挑战性。
如果您决定走多线程路线,Boost.Thread 是一个很好的库。