18

据我所知,处理器中的多核架构不会影响程序。实际的指令执行在较低层处理。

我的问题是,

鉴于您有一个多核环境,我可以使用任何编程实践来更有效地利用可用资源吗?我应该如何更改我的代码以在多核环境中获得更高的性能?

4

4 回答 4

16

那是对的。除非您使用并发,否则您的程序将不会运行得更快(除了核心处理较少的其他进程,因为某些进程正在另一个核心上运行)。但是,如果您确实使用并发,则更多的内核会提高实际的并行性(使用更少的内核,并发是交错的,而使用更多的内核,您可以获得线程之间的真正并行性)。

让程序高效地并发并不是一件简单的事情。如果做得不好,让你的程序并发实际上会使它变慢!例如,如果您花费大量时间生成线程(线程构建非常慢),并且在非常小的块大小上工作(因此线程构建的开销支配了实际工作),或者如果您经常同步数据(这不仅会强制操作串行运行,而且在其之上还有非常高的开销),或者如果您经常在多个线程之间的同一缓存行中写入数据(这可能导致整个缓存行在一个线程上无效)核心),那么您可能会严重损害并发编程的性能。

同样重要的是要注意,如果您有 N 个内核,这并不意味着您将获得 N 的加速。这是加速的理论限制。事实上,也许两个核心的速度是原来的两倍,但四个核心的速度可能是原来的三倍,而八个核心的速度大约是原来的三倍半,等等。你的程序实际上有多好能够利用这些核心称为并行可扩展性。通常,通信和同步开销会阻止线性加速,尽管在理想情况下,如果您可以尽可能避免通信和同步,则有望接近线性加速。

关于如何在 StackOverflow 上编写高效的并行程序,不可能给出完整的答案。这实际上是至少一门(可能是几门)计算机科学课程的主题。我建议你报名参加这样的课程或买一本书。如果我知道一本好书,我会向您推荐一本书,但是我参加的并行算法课程没有该课程的教科书。您可能还对使用串行实现、多线程并行实现(常规线程、线程池等)和消息传递并行实现(例如 Hadoop、Apache Spark、Cloud Dataflows)编写少量程序感兴趣、异步 RPC 等),然后测量它们的性能,在并行实现的情况下改变内核数量。这是我的并行算法课程的大部分课程工作,并且非常有见地。您可能会尝试并行化的一些计算包括使用 Monte Carlo 方法计算 Pi(这很容易并行化,假设您可以创建一个随机数生成器,其中在不同线程中生成的随机数是独立的),执行矩阵乘法,计算行梯形形式一个矩阵,将数字 1...N 的平方求和,得到一些非常大的 N,我相信你能想到其他的。

于 2010-03-18T08:18:24.537 回答
4

我不知道这是否是最好的起点,但我前段时间订阅了英特尔软件网络的文章提要,并在那里发现了很多有趣的东西,以非常简单的方式呈现。您可以找到一些关于并行计算基本概念的非常基本的文章,例如在这里,您可以快速了解 openMP,这是一种开始并行化应用程序最慢部分的可能方法,而无需更改其余部分。(当然,如果这些部分存在并行性。)另请查看Intel Guide for Developing Multithreaded Applications。或者只是去浏览文章部分,文章不是太多很多,所以你可以快速找出最适合你的东西。他们还有一个名为 Parallel Programming Talk的论坛和每周一次的网络广播。

于 2010-03-19T00:48:33.163 回答
3

是的,在不改变软件的情况下简单地向系统添加更多内核不会产生任何结果(除了操作系统能够在不同的内核上安排多个并发进程)。

要让您的操作系统利用您的多核,您需要做以下两件事之一:增加每个进程的线程数,或增加同时运行的进程数(或两者兼而有之!)。

然而,有效地利用核心是另一种颜色的野兽。如果您花费太多时间在线程/进程之间同步共享数据访问,那么您的并发级别将受到影响,因为线程彼此等待。这还假设您有一个可以相对容易并行化的问题/计算,因为算法的并行版本通常比其顺序版本复杂得多。

也就是说,特别是对于具有彼此独立的工作单元的 CPU 密集型计算,当您在问题上投入更多线程时,您很可能会看到线性加速。当您添加串行段和同步块时,这种加速会趋于降低。

I/O 繁重的计算通常在多线程环境中表现最差,因为对物理存储的访问(特别是如果它在同一个控制器或同一个媒体上)也是串行的,在这种情况下,线程在感觉它释放了您的其他线程以继续进行用户交互或基于 CPU 的操作。

于 2010-03-18T06:35:35.540 回答
0

您可能会考虑使用为并发编程而设计的编程语言。想到了 Erlang 和 Go。

于 2010-03-19T00:52:39.600 回答