61

作为来自企业 Web 开发领域的HPC领域的人,我总是很想知道“现实世界”中的开发人员如何利用并行计算。现在所有芯片都在走向多核,这一点更加重要,当一个芯片上有数千个核心而不是几个核心时,它会更加重要。

我的问题是:

  1. 这对您的软件路线图有何影响?
  2. 我对有关多核如何影响不同软件领域的真实故事特别感兴趣,因此请在您的答案中指定您所做的开发类型(例如服务器端、客户端应用程序、科学计算等)。
  3. 您如何处理现有代码以利用多核机器,您面临哪些挑战?你在使用OpenMPErlangHaskellCUDATBBUPC还是别的什么?
  4. 随着并发水平的不断提高,您打算做什么,您将如何处理成百上千个内核?
  5. 如果您的领域容易从并行计算中受益,那么解释为什么也很有趣。

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

更新:如果您确实回答了 #5,请提及您是否认为如果内核数(100、1000 等)超过可用内存带宽所能提供的数量(看看每个内核的带宽如何变得越来越小),情况是否会发生变化)。您仍然可以将剩余的内核用于您的应用程序吗?

4

22 回答 22

38

我的研究工作包括编译器和垃圾邮件过滤方面的工作。我还做了很多“个人生产力”的 Unix 工作。另外,我编写和使用软件来管理我教的课程,包括评分、测试学生代码、跟踪成绩和无数其他琐事。

  1. 多核对我完全没有影响,只是作为编译器支持其他应用程序的一个研究问题。但这些问题主要在于运行时系统,而不是编译器。
  2. 1990 年左右,Dave Wortman 费了很大的力气,证明您可以并行化一个编译器来保持四个处理器的忙碌。我认识的人都没有重复过这个实验。 大多数编译器都足够快以运行单线程。在多个不同的源文件上并行运行顺序编译器比让编译器本身并行要容易得多。对于垃圾邮件过滤,学习是一个固有的顺序过程。即使是旧机器也可以在一秒钟内学习数百条消息,因此即使是大型语料库也可以在一分钟内学习。再次,训练足够快
  3. 我利用并行机器的唯一重要方法是使用并行 make。这是一个巨大的福音,大型构建很容易并行化。Make 自动完成几乎所有的工作。我唯一记得的另一件事是使用并行性来计算长时间运行的学生代码,方法是将其移植到一堆实验室机器上,我可以凭良心做到这一点,因为我只破坏了每台机器的一个核心,所以只使用 1 /4 CPU 资源。哦,我写了一个 Lua 脚本,当用 lame 翻录 MP3 文件时将使用所有 4 个内核。该脚本需要做很多工作才能做到正确。
  4. 我将忽略数十、数百和数千个核心。我第一次被告知“并行机器即将到来;你必须做好准备”是在 1984 年。当时和今天都是如此,并行编程是高技能专家的领域。唯一改变的是,今天制造商强迫我们为并行硬件付费,无论我们是否愿意。但仅仅因为硬件是付费的,并不意味着它可以免费使用。 编程模型很糟糕,使线程/互斥模型工作,更不用说表现良好了,即使硬件是免费的,也是一项昂贵的工作。我希望大多数程序员忽略并行性并安静地处理他们的业务。当一个熟练的专家带着一个平行的品牌或一个伟大的电脑游戏出现时,我会默默地鼓掌并利用他们的努力。如果我想要我自己的应用程序的性能,我将专注于减少内存分配并忽略并行性。
  5. 并行性真的很难。 大多数域很难并行化。像并行生成这样可广泛重用的异常是令人欣喜的。

总结(我从一位为领先 CPU 制造商工作的主讲人那里听到):业界支持多核是因为他们无法让机器运行得更快、更热,而且他们不知道如何处理额外的晶体管。现在他们急切地想找到一种让多核盈利的方法,因为如果他们没有盈利,他们就无法建造下一代晶圆厂生产线。肉汁列车已经结束,我们实际上可能不得不开始关注软件成本。

许多认真对待并行性的人都忽略了这些玩具 4 核甚至 32 核机器,转而支持具有 128 个或更多处理器的 GPU。我的猜测是,真正的行动将在那里。

于 2008-12-13T01:40:51.330 回答
18

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

在任何给定时刻,您通常需要处理的请求比您拥有的内核要多得多。而且由于每个线程都是在自己的线程中处理的(甚至是进程,取决于您的技术),这已经在并行工作了。

唯一需要注意的地方是访问某种需要同步的全局状态时。将其保持在最低限度,以避免将人为瓶颈引入其他(几乎)完全可扩展的世界。

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

  • 我的服务器有更少的“CPU”,而每台服务器都有更多的内核(对我来说差别不大)
  • 相同数量的CPU可以支撑更多的并发用户
  • 当这似乎是不是CPU 100% 加载的结果的性能瓶颈时,这表明我在某处进行了一些糟糕的同步。
于 2008-12-12T22:43:46.647 回答
9

我从事医学成像和图像处理工作。

我们处理多核的方式与处理单核的方式非常相似——我们在编写的应用程序中已经有多个线程,以便获得响应式 UI。

但是,因为我们现在可以,所以我们正在认真考虑在 CUDA 或 OpenMP 中实现我们的大多数图像处理操作。英特尔编译器为 OpenMP 提供了很多很好的示例代码,它只是比 CUDA 更成熟的产品,并且提供了更大的安装基础,所以我们可能会采用它。

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

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

也许我很懒,但实际上,当涉及到并行化矩阵求逆之类的事情时,我不想花费太多时间来解决很多这些问题。很多非常聪明的人已经花了很多时间让这些东西像 nitrous 一样快速,我只是想把他们所做的事情拿来称呼它。像 CUDA 这样的东西有一个有趣的图像处理接口(当然,这就是它的定义),但对于那种即插即用的编程来说,它仍然太不成熟。如果我或其他开发人员有很多空闲时间,我们可能会尝试一下。因此,我们将使用 OpenMP 来加快处理速度(这肯定是在接下来几个月的开发路线图上)。

于 2008-12-12T17:31:54.593 回答
9
  1. 目前 - 老实说,并没有太大影响。我更多地处于“准备阶段”,学习使这成为可能的技术和语言特性。
  2. 我没有一个特定的领域,但我遇到过数学(多核是必不可少的)、数据排序/搜索(多核上的分而治之很有帮助)和多计算机需求(例如,要求备用站的处理能力用于某事)。
  3. 这取决于我使用的语言。显然在 C# 中,我的双手与尚未准备好的并行扩展实现捆绑在一起,这似乎确实提高了性能,直到您开始将相同的算法与 OpenMP 进行比较(也许不是一个公平的比较)。所以在 .NET 上,通过一些forParallel.For重构之类的东西会很容易。真正
    有趣的地方在于 C++,因为与 .NET 相比,您可以从诸如 OpenMP 之类的东西中挤出的性能是惊人的。事实上,OpenMP 让我很惊讶,因为我没想到它会如此高效地工作。好吧,我猜它的开发人员有很多时间来完善它。我也喜欢它在 Visual Studio 中开箱即用,与您必须付费的 TBB 不同。
    至于 MPI,我将 PureMPI.net 用于小型家庭项目(我有一个 LAN)来处理一台机器无法完成的计算。我从未在商业上使用过 MPI,但我知道 MKL 有一些 MPI 优化的功能,对于任何需要它们的人来说可能会很有趣。
  4. 我计划进行“轻量计算”,即使用额外的内核来预先计算可能需要或可能不需要的结果——当然,RAM 允许。我还打算深入研究大多数最终用户的机器目前无法处理的昂贵算法和方法。
  5. 至于没有从并行化中受益的领域……嗯,总能找到一些东西。担心的一件事是对 .NET 的良好支持,但遗憾的是我已经放弃了能够达到与 C++ 类似的速度的希望。
于 2008-12-12T17:18:45.680 回答
6

到目前为止,无非是更高效的编译make

gmake -j

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

于 2008-12-14T15:34:00.303 回答
6

我正在开发 ASP.NET Web 应用程序。在我的代码中直接使用多核的可能性很小,但是通过在负载下产生多个工作线程/进程,IIS 已经很好地扩展了多核/CPU。

于 2008-12-12T20:40:01.517 回答
5

我们在使用 F# 的 .NET 4 中的任务并行性方面取得了很大的成功。我们的客户迫切需要多核支持,因为他们不希望他们的 n-1 核闲置!

于 2010-06-05T11:20:51.597 回答
4

我在做图像处理。我们通过处理分配给不同线程的切片中的图像,尽可能利用多核。

于 2008-12-12T19:57:06.437 回答
3

我在回答一个不同的问题时说了一些(希望这没问题!):有一个概念/方法称为基于流的编程(FBP) 已经存在了 30 多年,并被用于处理加拿大一家主要银行的大部分批处理。它在 Java 和 C# 中具有基于线程的实现,尽管早期的实现是基于光纤的(C++ 和大型机汇编程序)。解决利用多核问题的大多数方法都涉及尝试采用传统的单线程程序并确定哪些部分可以并行运行。FBP 采用了不同的方法:应用程序从一开始就设计为多个异步运行的“黑盒”组件(想想制造装配线)。由于组件之间的接口是数据流,因此 FBP 本质上与语言无关,因此支持混合语言应用程序和特定领域的语言。

于 2009-06-01T14:09:21.790 回答
2

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

VivaMP 是一种类似于 lint 的静态 C/C++ 代码分析器,旨在指示基于 OpenMP 技术的并行程序中的错误。VivaMP 静态分析器大大增加了现有编译器的能力,诊断任何有错误或最终导致此类错误的并行代码。该分析仪已集成到 VisualStudio2005/2008 开发环境中。

VivaMP – OpenMP 工具

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

于 2009-02-08T15:46:26.903 回答
2

我相信“循环是工程师最好的朋友”。

我的公司提供了一种商业工具,用于以多种计算机语言分析和转换超大型软件系统。“大”是指 10-3000 万行代码。该工具就是DMS软件再造工具包(简称DMS)。

对如此庞大的系统进行分析(甚至转换)需要很长时间:我们的 C 代码点对点分析器在具有 16 Gb RAM 的 x86-64 上需要 90 个 CPU 小时。工程师想要比这更快的答案。

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

parlanse 背后的关键思想是:a) 让程序员公开并行性,b) 让编译器选择它可以实现的部分,c) 将上下文切换保持在绝对最低限度。计算上的静态偏序很容易帮助实现所有 3 个;说起来容易,相对容易衡量成本,编译器很容易安排计算。(用这个编写并行快速排序很简单)。

不幸的是,我们在 1996 年做到了这一点 :-( 过去几年终于证明了这一点;我现在可以在 Fry's 以低于 1000 美元的价格购买 8 台核心机器,并以与小型汽车相同的价格购买 24 台核心机器(并且可能迅速下降)。

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

现在(2009 年 6 月),我们正忙于使 DMS 变得有用,并且总是没有足够的时间来很好地利用并行性。因此,90 小时点分析。我们正在努力实现并行化,并有合理的希望加速 10-20 倍。

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

于 2009-06-14T05:39:02.650 回答
2

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

我还在使用 F# 来提高我的高级多进程语言工具的速度。

于 2008-12-12T20:25:53.277 回答
1

我们的域逻辑在很大程度上基于工作流引擎,每个工作流实例都在 ThreadPool 之外运行。

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

于 2008-12-12T23:13:12.547 回答
1

我现在可以将我的主操作系统与我的开发分开/安装任何我喜欢的操作系统,使用带有 Virtual PC 或 VMWare 的虚拟化设置。

双核意味着一个 CPU 运行我的主机操作系统,另一个运行我的开发操作系统,性能相当不错。

于 2008-12-12T23:22:39.737 回答
1

我在 Mac 上使用和编程。Grand Central Dispatch 为胜利而战。Ars Technica对 Snow Leopard 的评论有很多关于多核编程以及人们(或至少是 Apple)正在使用它的地方的有趣内容。

于 2009-09-09T05:51:32.537 回答
1

学习一门函数式编程语言可能会使用多个内核……代价高昂。

我认为使用额外的内核并不难。作为 Web 应用程序,有一些琐碎的事情不需要额外注意,因为 Web 服务器会并行运行查询。这些问题是针对长时间运行的算法(长就是你所说的长)。这些需要拆分为不相互依赖的较小域,或同步依赖关系。很多算法都可以做到这一点,但有时需要非常不同的实现(再次成本)。

所以,除非你使用命令式编程语言,否则没有灵丹妙药,抱歉。要么您需要熟练的程序员(成本高昂),要么您需要转向其他编程语言(成本高昂)。或者你可能只是运气好(网络)。

于 2008-12-24T00:45:19.790 回答
1

我决定在DEFLATE算法的实现中利用多个内核。MArc Adler 在 C 代码中使用PIGZ(并行 gzip)做了类似的事情。我已经在DotNetZip v1.9的托管代码库中提供了哲学等价物。这不是 PIGZ 的一个端口,而是一个类似的想法,独立实现。

DEFLATE 背后的想法是扫描数据块,查找重复序列,构建一个“字典”,将一个短“代码”映射到每个重复序列,然后发出一个字节流,其中一个重复序列的每个实例被字典中的“代码”替换。

因为构建字典是 CPU 密集型的,所以 DEFLATE 是并行化的完美候选者。我采用了 Map+Reduce 类型的方法,将传入的未压缩字节树划分为一组较小的块(映射),例如每个 64k,然后独立压缩这些块。然后我将生成的块连接在一起(减少)。每个 64k 块在其自己的线程上独立压缩,而不考虑其他块。

在双核机器上,这种方法的压缩时间大约是传统串行方法的 54%。在服务器级机器上,有更多可用内核,它可能会提供更好的结果;没有服务器机器,我没有亲自测试过,但人们告诉我它很快。


存在与多线程管理相关的运行时 (cpu) 开销、与每个 thead 的缓冲区相关的运行时内存开销以及与连接块相关的数据开销。所以这种方法只对更大的字节流有效。在我的测试中,超过 512k,它可以得到回报。在此之下,最好使用串行方法。


DotNetZip 作为库提供。我的目标是让这一切变得透明。因此,当缓冲区超过 512kb 时,库会自动使用额外的线程。为了使用线程,应用程序无需执行任何操作。它只是工作,当使用线程时,它神奇地更快。我认为对于应用程序使用的大多数库来说,这是一种合理的方法。


如果计算机能够智能地自动和动态地利用可并行算法上的资源,那将是一件好事,但今天的现实是应用程序设计人员必须明确编码并行化。


于 2010-01-26T23:28:34.180 回答
0

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

1) 软件路线图——我们面临着最大限度地利用空间和可用功率的压力。充分利用最新硬件至关重要

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

3)我们正在用现有代码做什么?不断地将其拆分并在线程之间重新分配它的一部分,以便在不破坏实时要求的情况下最大限度地发挥每个核心的作用。新硬件意味着大量的重新思考(更快的内核可以在给定的时间内做更多的事情,不希望它们被充分利用)。不像听起来那么糟糕——核心例程非常模块化,因此很容易组装成线程大小的块。尽管我们计划从 Linux 中控制线程亲和性,但我们还没有设法通过这样做来获得显着的额外性能。Linux 非常擅长在或多或少相同的地方获取数据和代码。

4) 实际上已经存在 - 整台机器已经加起来多达数千个内核

5) 并行计算是必不可少的——它是一个 MISD 系统。

如果这听起来像是很多工作,那就是。有些工作需要全力以赴,充分利用可用的硬件,并避开几乎所有高水平的东西。我们发现总机器性能是 CPU 内存带宽的函数,而不是 CPU 核心速度、L1/L2/L3 缓存大小。

于 2014-12-28T14:08:14.233 回答
0
  1. 这对您的软件路线图有何影响?
    它没有。我们(与几乎所有其他)业务相关的应用程序在单核上运行得非常好。只要添加更多内核不会显着降低单线程应用程序的性能,我们就很高兴

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

  3. 你在用你现有的代码做什么来利用多核机器
    如果我们有一个可以并行化的长时间运行的算法,我们可能会考虑使用 .NET 并行扩展,但这种情况实际发生的可能性很小。最可能的答案是,一些开发人员会为了兴趣而玩弄它,但除此之外别无他求

  4. 您将如何处理数百或数千个内核?
    头 -> 沙子。

  5. 如果您的领域不容易从并行计算中受益,那么解释为什么也很有趣。
    客户端应用程序主要推送数据,服务器应用程序主要依赖 SQL Server 来完成繁重的工作

于 2010-01-26T23:45:21.553 回答
0

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

我读过 Peter 的一些帖子,谈论 Packt Publishing 的一本新书,我在 Packt Publishing 网页中找到了以下文章:

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

我读过Joe Duffy 的书《Concurrent Programming with Windows》。现在,我正在等待希拉尔的书“C# 2008 和 2005 线程编程” - http://www.amazon.com/2008-2005-Threaded-Programming-Beginners/dp/1847197108/ref=pd_rhf_p_t_2

我同意 Szundi 的“没有银弹”!

于 2009-02-03T17:23:11.830 回答
0

你说“对于 Web 应用程序来说,这非常非常容易:忽略它。除非你有一些真正需要并行完成的代码,否则你可以简单地编写老式的单线程代码并感到高兴。”

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

我们不是还在为 DOS 开发吗?我们必须解决多核问题,否则我们将在多年后死去。

于 2009-02-03T17:31:11.033 回答
0

我认为这种趋势首先会说服一些开发人员,然后他们中的大多数人会看到并行化是一项非常复杂的任务。我希望一些设计模式能够解决这种复杂性。不是低级别的,而是架构模式,这将很难做错事。

例如,我希望消息传递模式会变得流行,因为它本质上是异步的,但你不会考虑死锁或互斥锁或其他任何东西。

于 2009-08-03T11:40:11.340 回答