你如何利用多核?

作为来自于企业Web开发领域的HPC世界中的一员,我总是好奇地看到,“真实世界”中的开发者如何利用并行计算。 现在所有的芯片都是多核的 ,这更加重要,而且芯片上有成千上万个核心,而不是几个核心,就更加相关。

我的问题是:

  1. 这是如何影响你的软件路线图的?
  2. 我特别感兴趣的是关于多核如何影响不同软件领域的真实故事,所以请说明在您的答案中( 例如服务器端,客户端应用程序,科学计算等)您做了什么样的开发。
  3. 您现有的代码如何利用多核机器,以及您面临的挑战是什么? 你使用的是OpenMP , Erlang , Haskell , CUDA , TBB , UPC还是其他的东西?
  4. 随着并发水平的不断提高,你打算做什么?你将如何处理数百或数千个内核?
  5. 如果你的域容易受益于并行计算,那么解释为什么它也是有趣的。

最后,我把它定义为一个多核问题,但可以随意谈论其他types的并行计算。 如果您正在移植部分应用程序以使用MapReduce ,或者如果大型群集上的MPI是您的范例,那么您也一定要提及这一点。

更新:如果你的答案是#5,提到你是否认为事情会改变,如果有更多的核心(100,1000等),你可以提供可用的内存带宽(看到带宽越来越小,每个核心)。 你仍然可以使用你的应用程序的其余核心?

我的研究工作包括编译器和垃圾邮件过滤。 我也做了很多“个人生产力”Unix的东西。 另外,我编写和使用软件来pipe理我教授的课程,其中包括评分,testing学生代码,跟踪成绩,以及其他各种琐事。

  1. 除了作为编译器支持其他应用程序的研究问题之外, 多核并不影响我 。 但是这些问题主要在于运行时系统,而不是编译器。
  2. Dave Wortman在1990年左右的时候遇到了很大的麻烦和费用,可以并行编译器来保持四个处理器的繁忙 。 没有人知道重复了这个实验。 大多数编译器足够快,可以运行单线程。 在几个不同的源文件上并行运行顺序编译器要比使编译器本身并行更容易。 对于垃圾邮件过滤, 学习本身就是一个连续的过程 。 而且即使是一台较老的机器也可以每秒学习数百条信息,所以即使在一分钟之内也可以学习到大量的语料。 再次, 培训是足够快
  3. 使用并行机器的唯一重要方法是使用并行make 。 这是一个很大的好处,而且大的构build很容易并行化 。 Make几乎可以自动完成所有的工作。 我唯一能记住的其他事情就是使用并行性来将长期运行的学生代码放到一堆实验室机器上,我可以很好地做到这一点,因为我只是在每台机器上打一个核心,所以只使用1 / 4个CPU资源。 噢,我写了一个Lua脚本,当使用蹩脚的方法翻录MP3文件时,将会使用所有4个内核。 这个脚本是很多工作来得到正确的。
  4. 我将忽略数十,数百和数千个核心 。 我第一次被告知“并行机器即将到来,你必须做好准备”是在1984年。当时的确如此, 并行编程是高技能专家的一个领域 。 唯一改变的是,今天制造商迫使我们支付并行硬件,无论我们是否愿意。 但仅仅因为硬件支付并不意味着它可以自由使用。 编程模型是可怕的,使线程/互斥模型工作 ,更不用说执行好了,即使硬件是免费的,也是一项昂贵的工作。 我希望大多数程序员忽略并行性,并悄悄地继续他们的业务。 当一个熟练的专家带着一个平行制作或一个伟大的电脑游戏,我会静静地鼓掌并利用他们的努力。 如果我想要自己的应用程序的性能,我会集中精力减less内存分配,并忽略并行。
  5. 并行性真的很难。 大多数域名难以并行化。 一个广泛的可重用的例外,如并行make是令人高兴的。

总结(我从一位为一家领先的CPU制造商工作的主题演讲者那里听到):业界支持多核,因为他们无法使机器运行得更快更热,他们不知道如何处理额外的晶体pipe。 现在他们急于find一种让多核有利可图的方法,因为如果他们没有利润,他们就无法build造下一代的晶圆厂生产线。 肉汁火车已经结束,我们可能不得不开始关注软件成本。

许多认真对待并行性的人会忽视这些玩具四核甚至32核心的机器,而select128个或更多处理器的GPU。 我的猜测是,真正的行动将在那里。

对于Web应用程序来说非常非常简单:忽略它。 除非你有一些真正需要并行执行的代码,否则你可以简单地编写旧式的单线程代码并且很高兴。

在任何特定时刻,通常您都有更多的请求处理,而不是核心。 而且由于每一个都是在自己的线程中处理(甚至是根据你的技术进行处理),这已经是并行工作了。

唯一需要注意的地方是访问某种需要同步的全局状态。 尽量避免将人为瓶颈引入本来几乎完全可扩展的世界。

所以对于我来说,多核心基本归结为这些项目:

  • 我的服务器有较less的“CPU”,而每一个运行更多的核心(对我来说差别不大)
  • 相同数量的CPU可以承担更多的并发用户
  • 当看起来性能瓶颈不是 CPU被100%加载的结果,那么这就表明我在某个地方做了一些不好的同步。
  1. 目前 – 不影响那么多,说实话。 我更多地处于“准备阶段”,学习使这成为可能的技术和语言特征。
  2. 我没有一个特定的领域,但是我遇到了像math这样的领域(其中多核是必不可less的),数据sorting/search(多核的分而治之是有用的)和多计算机的要求(例如,要求备份站的处理能力用于某些事情)。
  3. 这取决于我正在工作的语言。 很显然,在C#中,我的双手与并行扩展尚未准备好的实现捆绑在一起,这似乎提高了性能,直到您开始将相同的algorithm与OpenMP进行比较(可能不是一个公平的比较)。 所以在.NET上,这将是一个轻松的搭配,一些→ Parallel.For重构之类的。
    事情真正有趣的地方在于C ++,因为与.NET相比,OpenMP等性能可以说是惊人的。 实际上,OpenMP让我很吃惊,因为我没有想到它能够如此有效地工作。 那么,我想它的开发者已经有很多时间去打磨它了。 我也喜欢它可以在Visual Studio中使用,不像TBB那样需要付费。
    至于MPI,我使用PureMPI.net作为小型家庭项目(我有一个局域网)来计算一台机器不能完成的计算。 我从来没有使用MPI商业,但我知道MKL有一些MPI优化的function,这可能是有趣的,看看谁需要他们。
  4. 我打算做“无聊的计算”,即使用额外的内核来预先计算可能需要或可能不需要的结果,当然RAM也是允许的。 我也打算深入研究大多数最终用户的机器现在无法处理的昂贵的algorithm和方法。
  5. 至于没有从平行化中受益的领域……那么总能find一些东西。 我关心的一件事就是在.NET中得到体面的支持,但遗憾的是,我放弃了希望能够达到类似于C ++的速度。

我从事医学成像和image processing。

我们处理多个内核的方式与我们处理单个内​​核的方式大致相同 – 我们编写的应用程序中已经有多个线程,以便具有响应式UI。

但是,因为我们现在可以,所以我们正着眼于在CUDA或OpenMP中实现大部分image processing操作。 英特尔编译器为OpenMP提供了很多很好的示例代码,只是一个比CUDA更成熟的产品,并且提供了更大的安装基础,所以我们可能会这样做。

如果可以的话,我们倾向于做的昂贵(即超过一秒)的操作是将该操作分成另一个操作。 这样,主UI保持响应。 如果我们不能,或者移动那么多的内存太不方便或太慢,操作仍然在一个线程中,然后该操作本身可以产生多个线程。

我们的关键是确保我们不会遇到并发瓶颈。 我们在.NET中开发,这意味着UI更新必须从对UI的Invoke调用完成,以使主线程更新UI。

也许我是懒惰的,但是真的,我不想花费太多的时间来处理这些东西,比如matrix反转等等。 很多非常聪明的人花了很多时间把这些东西做得像亚麻一样快,而我只是想把他们所做的和所谓的。 像CUDA这样的image processing有一个有趣的界面(当然,这就是它的定义),但是对于这种即插即用编程来说,它还是不成熟的。 如果我或其他开发人员有很多空闲时间,我们可以尝试一下。 相反,我们只需要使用OpenMP就可以加快处理速度(这在未来几个月的发展蓝图中也是如此)。

到目前为止,没有什么比用make编译更高效了:

 gmake -j 

-j选项允许不相互依赖的任务并行运行。

我正在开发ASP.NET Web应用程序。 在我的代码中直接使用多核心的可能性很小,但是IIS在加载时可以通过产生多个工作线程/进程来扩展多核/ CPU。

在.NET 4中,我们使用F#在任务并行方面取得了很大的成功。 我们的客户正在呼吁多核支持,因为他们不想让n-1核心闲置!

我在image processing。 在可能的情况下,我们正在利用多核,通过处理分发给不同线程的片中的映像。

我的研究生工作是在开发用于裸机多核工作和embedded式系统教学的概念。

我也在F#上工作一番,以提高我的高级多进程语言设施的速度。

我们创build了VivaMP代码分析器,用于在并行OpenMP程序中进行错误检测。

VivaMP是一种类似皮棉的静态C / C ++代码分析器,用于指示基于OpenMP技术的并行程序中的错误。 VivaMP静态分析器增加了现有编译器的能力,诊断任何有一些错误的并行代码,或者是这类错误的最终来源。 该分析仪集成到VisualStudio2005 / 2008开发环境中。

VivaMP – OpenMP的一个工具

针对C ++开发人员的32个OpenMP陷阱

我在回答一个不同的问题时说过一些问题(希望这是可以的):有一种叫做基于stream的编程 (FBP)的概念/方法已经存在了30多年了,并且正在被用来处理大部分加拿大一家大银行的批量处理。 它在Java和C#中有基于线程的实现,尽pipe早期的实现是基于光纤的(C ++和大型机汇编)。 利用多核的问题的大多数方法涉及尝试采用传统的单线程程序并找出哪些部分可以并行运行。 FBP采取了不同的方法:应用程序从一开始就被devise为asynchronous运行的多个“黑盒子”组件(想象一下制造assembly线)。 由于组件之间的接口是数据stream,因此FBP本质上是独立于语言的,因此支持混合语言应用程序和特定于领域的语言。 使用这种方式编写的应用程序比传统的单线程应用程序更易于维护,即使在单核计算机上也经常花费较less的时间。

我相信“ 周期是工程师最好的朋友 ”。

我公司提供了一个商业工具,用于分析和转换许多计算机语言中的大型软件系统。 “大”意味着10-30万行代码。 该工具是DMS Software Reengineering Toolkit(简称DMS)。

在这样庞大的系统上进行分析(甚至是转换)需要很长时间:对于C代码分析器来说,在具有16 Gb RAM的x86-64上需要90个CPU时间。 工程师比这更快地得到答案。

因此,我们在PARLANSE中实现了DMS,这是我们自己devise的并行编程语言,旨在利用小型多核共享内存系统。

parlanse背后的主要思想是:a)让程序员暴露并行,b)让编译器select它可以实现的部分,c)保持上下文切换到绝对最小值。 通过计算的静态部分订单是一个容易实现所有3; 容易说,测量成本相对容易,编译器便于计算。 (用这个写平行的快速sorting是微不足道的)。

不幸的是,我们在1996年做到了这一点:-(过去几年终于certificate了这一点;现在我可以在Fry's上以不到1K的价格购买8台核心机器,而24台核心机器的售价与小型车相同迅速下降)。

好消息是,DMS现在已经相当成熟了,在DMS中有很多关键的内部机制利用了这一点,特别是整个分析器类称为“属性语法”,我们使用领域特定的语言这不是parlanse。 DMS将这些atrribute语法编译成PARLANSE,然后它们并行执行。 我们的C ++前端使用属性语法,约为100K sloc; 它被编译成实际工作可靠的并行parlanse代码的800K SLOC。

现在(2009年6月),我们非常忙于使DMS有用,并且总是没有足够的时间来充分利用并行性。 因此,90小时的分数来分析。 我们正在对此进行并行处理,并有10-20倍加速的合理希望。

我们相信,从长远来看,善用SMP将使工作站对工程师提出的难题更加友好。 他们也应该。

我们的领域逻辑主要基于工作stream引擎,每个工作stream实例都运行在ThreadPool之外。

这对我们来说已经够好了。

我现在可以将我的主要操作系统从我的开发/安装中分离出来,无论我使用Virtual PC或VMWare进行虚拟化设置。

双内核意味着一个CPU运行我的主机操作系统,另一个运行我的开发操作系统有一个体面的性能水平。

学习函数式编程语言可能会使用多个内核,代价很高。

我认为使用额外的内核并不是很难。 Web应用程序有一些琐碎的事情,不需要特别小心,因为Web服务器并行地运行查询。 问题是长期运行algorythms(长期是你所说的很长)。 这些需要被拆分成不相互依赖的较小的域,或者同步这些依赖关系。 许多关联可以做到这一点,但有时需要可怕的不同实现(成本再次)。

所以,直到你使用命令式编程语言,没有银弹,对不起。 要么需要熟练的程序员(代价高昂),要么需要转向其他编程语言(代价高昂)。 或者你可能只是运气(networking)。

我在Mac上使用和编程。 大中央调度的胜利。 Ars Technica对Snow Leopard的评论对于多核编程以及人们(至less是苹果公司)正在采用的方式有很多有趣的话题。

我决定在DEFLATEalgorithm的实现中利用多个核心。 MArc Adler在C代码中使用了PIGZ (并行gzip)。 我已经提供了哲学等价物,但是在DotNetZip v1.9中的托pipe代码库中。 这不是PIGZ的港口,而是一个类似的想法,独立实施。

DEFLATE背后的思想是扫描一个数据块,寻找重复的序列,build立一个“字典”,将一个简短的“代码”映射到每个重复序列,然后发射一个字节stream,其中一个重复序列的每个实例被字典中的“代码”所取代。

由于构build字典是CPU密集型的,因此DEFLATE是并行化的理想select。 我采取了Map + Reducetypes的方法,在这里我将input的未压缩的bytestreeam分成一组较小的块(map),比如说每个64k,然后独立地压缩这些块。 然后我把结果块拼接在一起(减less)。 每个64k块在其自己的线程上被独立压缩,而不考虑其他块。

在双核机器上,这种方法约占传统串行方法的54%。 在具有更多内核的服务器级机器上,它可能会提供更好的结果。 没有服务器机器,我没有亲自testing,但是人们告诉我这很快。


与multithreadingpipe理相关的运行时(cpu)开销,与每个队列的缓冲区关联的运行时内存开销以及与连接块相关的数据开销。 所以这种方法只能为更大的字节stream提供支付。 在我的testing中,高于512k,可以得到回报。 在此之下,最好使用串行方法。


DotNetZip作为一个库提供。 我的目标是使所有这些透明。 所以当缓冲区大于512kb时,库会自动使用额外的线程。 为了使用线程,应用程序无需做任何事情。 它只是工作,并使用线程,这是神奇的更快。 我认为这是一个合理的方法来采取应用程序消耗的大多数libbraries。


计算机在自动和dynamic利用parallizablealgorithm的资源方面很聪明,但是现在的现实是,应用程序devise者必须明确编码并行化。


我使用.Net线程在C#中工作。 您可以将面向对象的封装和线程pipe理结合起来。

我已经阅读了Peter在Packt Publishing上发表的一篇关于新书的文章,并且在Packt Publishing的网页上发现了以下文章:

http://www.packtpub.com/article/simplifying-parallelism-complexity-c-sharp

Joe Duffy的书中,我已经阅读过与Windows并行编程。 现在,我正在等待“C#2008和2005 Threaded Programming”,Hillar的书 – http://www.amazon.com/2008-2005-Threaded-Programming-Beginners/dp/1847197108/ref=pd_rhf_p_t_2

我赞同祖孙迪“没有银弹”!

你说:“对于Web应用程序来说,非常非常简单:忽略它,除非你有一些真正需要并行执行的代码,否则你可以简单地编写旧式的单线程代码并且很高兴。

我正在使用Web应用程序,我需要充分利用并行性。 我明白你的观点 但是,我们必须为多核革命做好准备。 忽略它与忽略90年代的GUI革命是一样的。

我们还没有开发DOS? 我们必须解决多核问题,否则我们会在很多年内死去。

我认为这个趋势会首先说服一些开发者,然后他们中的大多数人会看到并行化是一个非常复杂的任务。 我期望一些devise模式来处理这种复杂性。 不是低层次的,而是会使得难以做错的架构模式。

例如,我期望消息传递模式得到普及,因为它本质上是asynchronous的,但是你不会考虑死锁或互斥等等。

  1. 这是如何影响你的软件路线图的?
    它不。 我们(几乎所有其他)与业务相关的应用程序在单个内核上运行得非常好。 只要添加更多内核并不会显着降低单线程应用程序的性能,我们很高兴

  2. 真实的故事
    像其他人一样,并行构build是我们获得的主要好处。 Visual Studio 2008 C#编译器似乎并没有使用多个核心,但真的很糟糕

  3. 你现在的代码是如何利用多核机器的
    如果我们有一个可以并行执行的长时间运行的algorithm,我们可以考虑使用.NET并行扩展,但实际发生的可能性很小。 最有可能的答案是,有些开发人员会为了利益而玩弄它,而不是其他的

  4. 你将如何处理数百或数千个内核?
    头 – >沙。

  5. 如果你的域不容易受益于并行计算,那么解释为什么它也是有趣的。
    客户端应用程序大部分都是推送数据,服务器应用程序主要依靠SQL服务器来完成繁重的工作

我正在利用C,PThreads以及使用PREEMPT_RT补丁集的调度程序在Linux上使用OpenVPX平台进行通信连续进程的自制实现来利用多核。 在所有操作系统实例中,所有操作系统实例的CPU利用率几乎达到100%,OpenVPX机箱中处理器卡之间的数据交换没有CPU时间,而且延迟也非常低。 还使用sFPDP将多个OpenVPX机箱连接在一起成为一台机器。 我们不使用Xeon的内部DMA,以减轻CPU内存的压力(DMA仍然使用内存带宽,但CPU内核的代价是)。 相反,我们将数据留在原地并以CSP的方式传递它的所有权(与.NET的任务并行数据stream库的理念不同)。

1)软件路线图 – 我们有压力来最大限度地利用房地产和可用功率。 充分利用最新的硬件是至关重要的

2)软件领域 – 有效的科学计算

3)我们正在用现有的代码做什么? 不断拆分,并将其中的一部分重新分配到线程中,以便每个内核都可以最大限度地发挥最大function,而不会破坏实时要求。 新的硬件意味着相当多的重新思考(更快的核心可以做更多的在给定的时间,不希望他们被利用)。 没有听起来那么糟糕 – 核心程序是非常模块化的,所以很容易组装成线程大小的块。 尽pipe我们计划将线程亲和力控制在远离Linux的地方,但是我们还没有设法通过这样做来提取显着的额外性能。 Linux在相同的地方获取数据和代码是相当不错的。

4)实际上已经有了 – 整个机器已经加起来数以千计的核心

5)并行计算是必不可less的 – 这是一个MISD系统。

如果这听起来像很多工作,那就是。 有些工作需要全力以赴,使绝大多数可用硬件摆脱困境,避开几乎所有高层次的工作。 我们发现整个机器性能是CPU内存带宽的函数,而不是CPU核心速度,L1 / L2 / L3caching大小。