多核系统的编程和编译状态

时间:2010-09-05 19:30:03

标签: multicore

我正在研究多核处理器;具体来说,我正在考虑为多核处理器编写代码,并为多核处理器编译代码。

我很好奇这个领域的主要问题,这些问题目前阻碍了编程技术和实践的广泛采用,以充分利用多核架构的强大功能。

我知道以下努力(其中一些似乎与多核架构没有直接关系,但似乎更多地与并行编程模型,多线程和并发性有关):

  • Erlang(我知道Erlang包含用于促进并发的构造,但我不确定它是如何被用于多核架构的)
  • OpenMP(似乎主要与多处理和利用集群的力量有关)
  • Unified Parallel C
  • Cilk
  • Intel Threading Blocks(这似乎与多核系统直接相关;因为它来自英特尔而有意义。除了定义某些编程结构外,它似乎还具有告诉编译器优化代码的功能多核架构)

总的来说,从我对多线程编程的经验来看,我知道编写并发和并行的编程绝对是一个困难的概念。我也知道多线程编程多核编程是两回事。在多线程编程中,您确保CPU不会保持空闲(在单CPU系统上。正如James所指出的,操作系统可以安排不同的线程在不同的内核上运行 - 但我更感兴趣的是描述并行操作语言本身,或通过编译器)。据我所知,你不能真正做并行操作。在多核系统中,您应该能够执行真正的并行操作。

所以在我看来,目前多核编程面临的问题是:

  • 多核编程是一项难以理解的概念,需要很高的技巧
  • 今天的编程语言中没有为多核环境提供良好抽象的本机构造
  • 除了英特尔的TBB库之外,我还没有找到其他编程语言的工作来利用多核架构的强大功能进行编译(例如,我不知道Java或C#编译器是否优化了多核系统的字节码或即使JIT编译器这样做了)

我很想知道可能存在的其他问题,以及是否有任何解决方案可以解决这些问题。研究论文(以及那种性质的东西)的链接会很有帮助。谢谢!

修改

如果我不得不将我的问题简化为一句话,那就是:今天多核编程面临的问题是什么?该领域正在进行哪些研究以解决这些问题?

更新

在我看来,有三个层次需要关注多核:

  1. 语言级:构造/概念/框架,抽象并行化和并发性,使程序员能够轻松表达相同的内容
  2. 编译器级别:如果编译器知道它正在编译的架构,它可以优化该架构的编译代码。
  3. 操作系统级别:操作系统优化了正在运行的进程,并可能安排不同的线程/进程在不同的核心上运行。
  4. 我搜索过ACM和IEEE并找到了一些论文。他们中的大多数人都在谈论同时思考是多么困难,以及当前语言如何没有正确的方式来表达并发性。有些人甚至声称我们拥有的当前并发模型(线程)不是处理并发的好方法(即使在多核上)。我有兴趣听取其他意见。

5 个答案:

答案 0 :(得分:5)

  

我很好奇这个领域的主要问题,这些问题目前阻碍了编程技术和实践的广泛采用,以充分利用多核架构的强大功能。

惯性。 (BTW:这几乎是所有的答案“什么阻止了广泛采用”的问题,无论是并行编程,垃圾收集,类型安全还是节能汽车的模型。)

自20世纪60年代以来,我们已经知道线程+锁模型从根本上被打破。到1980年,我们有大约十几个更好的模型。然而,今天使用的绝大多数语言(包括1980年以后新创建的语言)只提供线程+锁。

答案 1 :(得分:3)

多核编程的主要问题与编写任何其他并发应用程序相同,但是在计算机中有多个cpus之前很少见,现在很难找到任何只有一个核心的现代计算机,所以,为了利用多核,多CPU架构,存在新的挑战。

但是,这个问题是一个老问题,每当计算机体系结构超越编译器时,似乎后备解决方案就是回归功能编程,因为如果严格遵循编程范式,可以制作非常可并行化的程序,因为你不要例如,没有任何全局可变变量。

但是,并非所有问题都可以通过FP轻松完成,因此我们的目标是如何轻松地让其他编程范例在多核上轻松使用。

首先,许多程序员都避免编写好的多线程应用程序,所以没有一个准备充分的开发人员,因为他们学会了习惯,这将使他们的编码更难做。

但是,与cpu的大多数更改一样,您可以查看如何更改编译器,为此您可以查看Scala,Haskell,Erlang和F#。

对于库,您可以通过MS查看并行框架扩展,以便更容易进行并发编程。

它正在发挥作用,但我最近在IEEE Spectrum或IEEE Computer上发表了关于多核编程问题的文章,所以看看有关这些问题的IEEE和ACM文章,以获得更多有关正在研究的内容的想法

我认为最大的障碍是难以让程序员改变他们的语言,因为FP与OOP非常不同。

除了开发能够很好地运行这种方式的语言之外,研究的一个地方是如何处理访问内存的多个线程,但是,就像在这个领域一样,Haskell似乎是在测试这个想法的最前沿,所以你可以看看Haskell发生了什么。

最终会有新的语言,可能我们有DSL来帮助更多地抽象开发人员,但是如何教育程序员这将是一个挑战。

<强>更新

您可以找到感兴趣的第24章并发和多核编程http://book.realworldhaskell.org/read/concurrent-and-multicore-programming.html

答案 2 :(得分:3)

其中一个答案提到了.NET Framework的并行扩展,因为你提到了C#,这肯定是我要研究的东西。微软已经在那里做了一些有趣的事情,尽管我不得不认为他们的许多努力似乎更适合C#中的语言增强,而不是用于并发编程的独立和独特的库。但我认为他们的努力值得鼓掌和尊重我们在这里的早期。 (免责声明:大约3年前我曾担任Visual Studio的营销总监)

英特尔螺纹构建模块也非常有趣(英特尔最近发布了一个新版本,我很高兴能够在下周前往英特尔信息技术峰会,了解如何正确使用它。)

最后,我在西雅图的软件质量初创公司Corensic工作。我们有一个名为Jinx的工具,用于检测代码中的并发错误。适用于Windows和Linux的30天试用版,因此您可能需要查看它。 (www.corensic.com)

简而言之,Jinx是一个非常薄的虚拟机管理程序,在激活后,会在处理器和操作系统之间滑入。 Jinx然后智能地执行切片并运行各种线程计时的模拟以查找错误。当我们发现会导致错误发生的特定线程时序时,我们会在您的计算机上将该时间设置为“真实”(例如,如果您使用的是Visual Studio,则调试器将在此时停止)。然后,我们指出代码中导致错误的区域。 Jinx没有误报。当它检测到错误时,肯定是一个错误。

Jinx适用于Linux和Windows,以及本机代码和托管代码。它是语言和应用程序平台无关的,可以使用您现有的所有工具。

如果您查看,请向我们发送有关哪些有效且无效的反馈。我们已经在一些大型开源项目上运行Jinx,并且已经看到Jinx可以发现错误的速度比简单压力测试代码快50-100倍。

答案 3 :(得分:2)

用于高效使用多个处理器/内核的任何高性能应用程序(用C或C ++编写)的瓶颈是内存系统(高速缓存和RAM)。单核通常会通过读写操作使内存系统饱和,因此很容易理解为什么添加额外的内核和线程会导致应用程序运行速度变慢。如果一个人的队列可以一次通过一个门,增加额外的队列不仅会堵塞门,而且还会使任何一个人通过门的通道效率降低。

任何多核应用程序的关键是优化和节省内存访问。这意味着将数据和代码构造成尽可能在其自己的缓存中工作,在这些缓存中,它们不会通过公共缓存(L3)或RAM来干扰其他内核。偶尔核心需要冒险,但诀窍是尽可能减少这些情况。特别是,数据需要围绕并适应缓存行及其大小(目前为64字节),代码需要紧凑,不能在整个地方调用和跳转,这也会破坏管道。

我的经验是,有效的解决方案对于相关应用程序来说是独一无二的。通用指南(上面)是构建代码的基础,但是对于那些没有参与优化工作的人来说,对剖析结果所产生的调整变化并不明显。

答案 4 :(得分:1)

查找fork / join框架和工作窃取运行时。两个名称用于相同或至少相关的方法,即将大型任务递归地细分为轻量级单元,以便利用所有可用的并行性,而无需事先知道有多少并行性。这个想法是它应该在单处理器上以串行速度运行,但是通过多个内核获得线性加速。

如果你正确看待它,可以对缓存无关的算法进行水平模拟。

但我要说多核编程面临的主要问题是绝大多数计算仍然是顽固的串行。没有办法在这些计算中抛出多个核心并使它们坚持下去。