我们应该为多核编程花费多少精力?


12

如今,处理器的核心越来越多,这让我感到奇怪。

程序员,我们是否应该适应这种行为,并在多核编程上投入更多的精力?

我们应该在多大程度上进行优化?线?亲和力?硬件优化?还有吗

Answers:


15

无论您有多出色,与开发正在编写代码的语言和编译器的团队相比,您将不可能想出更好的线程管理方案。

如果您需要应用程序是多线程的,则创建所需的线程,然后让编译器和OS继续其工作。

您确实需要了解如何管理这些线程,以便可以最佳利用资源。作为一个例子,不要过多地创建线程是一件事。

您还需要知道发生了什么事情(请参阅Lorenzo的评论),以便您可以向线程管理提供提示(或在特殊情况下将其覆盖),但是我本以为这些之间的联系会很少。


3
但是,一个线程不断地从一个内核跳到另一个内核会造成性能损失(由于缺少第一级和第二级CPU缓存),特别是在使用两个不同物理裸片的体系结构中。在多线程密集型代码中,亲和性是一件好事。
Wizard79

@Lorenzo-在这种情况下,您需要查看是否可以将线程绑定到单个内核上-这也许是一种特殊情况-但很有趣。
克里斯·

1
操作系统将活动线程从一个内核切换到另一个内核,这不是很奇怪的举动吗?
JBRWilkinson

我同意@JBRWilkinson的观点,线程相似性对我来说似乎是一项OS工作。
Collin

1
@JBRWilkinson在Linux(我认为大多数操作系统)下,线程始终在内核之间跳转。第一个原因是,您总体上拥有比内核更多的线程。而且,如果某些线程死亡,则需要进行平衡。第二个原因是许多线程正在休眠。而且,当某些内核唤醒时,内核可能会认为一个内核比其他内核拥有更多的负载并移动一个线程,这通常是占用CPU的计算线程。然后,在同一内核上运行2个cpu占用线程,直到内核向后移动一个。如果要将大型作业分成精确的核数部分,则需要设置线程关联性。
Goswin von Brederlow,2015年

5

我是.NET程序员,并且我知道.NET对多线程有一个称为Tasks的高层抽象。它使您不必过多地了解如何对金属进行适当的多线程处理。我假设其他当前的开发平台具有类似的抽象。因此,如果您打算对多线程做任何事情,我将尽可能尝试在该级别上工作。

现在,您甚至应该关心特定应用程序中的多线程问题。该问题的答案很大程度上取决于您正在编写的应用程序。如果您编写的应用程序可以处理数千个(或更多)独立的事物,并且该处理可以并行进行,那么几乎可以肯定,多线程将为您带来好处。但是,如果您正在编写一个简单的数据输入屏幕,则多线程可能不会给您带来很多好处。

至少,在使用UI时,您需要考虑多线程。您不想从UI触发长时间运行的操作并使它变得无响应,因为您劫持了UI线程来执行该操作。触发后台线程,并至少为用户提供一个“取消”按钮,以便他们在输入错误时不必等待其完成。


5

在Objective-C,Mac OS X和iOS领域,编写框架(像其他许多框架一样)是为了利用处理器核心的这些增加,并为开发人员提供一个很好的界面来利用它们。

Mac OS X和iOS上的示例是Grand Central调度。libc(我相信)还有一些附加功能可以促进基于队列的多线程。然后,将Cocoa和Foundation框架(以及其他框架)编写在GCD之上,从而使开发人员只需很少的样板代码即可轻松访问调度队列和线程。

许多语言和框架都有类似的概念。


5

困难的部分在于将CPU密集型算法拆分为可以进行线程化的执行块。

然后,一个线程不断地从一个内核跳到另一个内核将导致性能下降(由于缺少第一级和第二级CPU缓存),尤其是在采用两个不同物理裸片的体系结构中。在这种情况下,线程核心亲和力是一件好事。


3

我们现在(2010年10月)正处于一个巨大的过渡时期。

我们今天可以购买12核台式机。
我们今天可以购买448核心处理(搜索NVidia Tesla)。

在不考虑我们的程序将在不久的将来工作的巨大并行环境的情况下,我们的开发人员可以工作的数量是有限的。

操作系统,运行时环境和编程库只能做很多事情。

将来,我们需要使用新的.NET“任务框架”之类的抽象方法,将处理过程分为离散的块进行独立处理。

诸如缓存管理和关联性之类的细节仍将存在-但它们仅是超高性能应用程序的来源。没有哪个开发人员会希望在10k核心计算机上手动管理这些详细信息。


3

好吧,这实际上取决于您正在开发什么。答案取决于您所开发的内容,范围可以从“无关紧要”到“绝对关键”,我们希望团队中的每个人都能很好地理解和使用并行实现。

在大多数情况下,当需要并行性时,对锁,线程以及任务和任务池有扎实的了解和使用将是一个好的开始。(因lang / lib而异)

此外,还必须在设计上有所不同-对于非平凡的多处理,必须经常学习几种新的编程模型或并行化策略。在这种情况下,要花很多时间来学习,花大量的时间来缺乏扎实的理解和更新现有的程序,这可能需要一个团队(一年或更长时间)。一旦达到这一点,您(希望!)将不会像今天一样感知或处理问题/实施(前提是您尚未进行此过渡)。

另一个障碍是您正在有效地优化程序以实现特定执行。如果没有足够的时间来优化程序,那么您将无法从中获得应有的收益。高水平(或明显)的并行化可以用相当少的精力来提高程序的预期速度,而今天为止,有很多团队要去:“我们已经并行化了应用程序中真正显而易见的部分”-在某些情况下还可以。收获低垂的果实并使用简单的并行化的好处会与核心数量成比例吗?通常,当有两个到四个逻辑核心,但没有那么多时。在很多情况下,考虑到时间投入,这是可以接受的回报。这个并行模型是许多人介绍如何实现并行的良好使用的方法。

在所有复杂的并行场景中,使用这种琐碎的并行模型所学的内容都不是理想的;有效地应用复杂的并行设计需要完全不同的理解和方法。这些简单的模型通常是分离的,或者与系统的其他组件无关紧要。同样,这些琐碎模型的许多实现也无法很好地扩展到有效的复杂并行系统中-糟糕的复杂并行设计可能需要与简单模型一样长的时间来执行。不适:它的执行速度是单线程模型的两倍,同时在执行过程中使用8个逻辑核心。最常见的例子是使用/创建太多线程和高水平的同步干扰。通常,这称为并行减速。如果您将所有并行问题都视为简单问题,则很容易遇到。

因此,假设您确实应该在程序中利用高效的多线程(在当今的气候下是少数):您需要有效地使用简单模型来学习复杂模型,然后重新学习如何处理程序流和交互。复杂的模型是您的程序最终应该使用的模型,因为这是当今的硬件,并且将在其中进行最主要的改进。

可以想象简单模型的执行就像叉子一样,而复杂模型的运行就像一个复杂的生态系统。我认为,当域(您在其中进行开发)使用它时,对中间开发人员应该或将很快对简单模型(包括常规锁定和线程)有所了解。今天(在大多数领域)了解复杂模型仍然有点不寻常,但是我认为需求会迅速增加。作为开发人员,我们更多的程序应支持这些模型,并且大多数应用在理解和实现这些概念方面都远远落后。由于逻辑处理器数量是硬件改进的最重要领域之一,因此对于了解并能够实施复杂系统的人员的需求肯定会增加。

最后,很多人认为解决方案只是“添加并行化”。通常,最好使现有的实现更快。在许多情况下,它更容易,更直接。野外的许多程序从未进行过优化。有些人只是觉得未经优化的版本很快就会被硬件所取代。如果性能很重要,那么改进现有程序的设计或算法也是一项重要技能-在问题上投入更多的核心不一定是最佳或最简单的解决方案。

当针对现代PC时,我们大多数需要实现良好的并行系统的人都不需要超越多线程,锁定,并行库,一本书的价值以及大量编写和测试程序的经验(基本上,是对您如何方法编写程序)。


2

可以,但是我们编写了计算量大的软件,因此我们可以直接从多个内核中受益。

有时,调度程序会在内核之间频繁移动线程。如果那是不可接受的,那么您可以发挥核心亲和力。


0

就目前而言,处理器频率在不久的将来不会增加。我们陷入了3 GHz的大关(没有超频)。当然,对于许多应用程序,可能不必超越非常基本的多线程。显然,如果要构建用户界面应用程序,则应在后台线程上进行所有密集处理。

如果您要构建的应用程序正在处理必须实时的大量数据,那么可以,您可能应该研究多线程编程。

对于多线程编程,您会发现自己的性能回报会减少;您可以花几个小时将程序改进15%,然后再花一周的时间再将程序改进5%。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.