转载

麻省理工学院(MIT)优化过的编译器产生更高效的并行程序

点击上方蓝色“ 网路冷眼” 可以订阅哦!

麻省理工学院(MIT)优化过的编译器产生更高效的并行程序

编译器是将用可理解为人的高级语言编写的计算机代码转换为可由机器执行的低级指令的程序。

但是不止一种方法来实现给定的计算,现代编译器广泛地分析他们处理的代码,试图推导出最大程度提高最终软件效率的实现。

然而,明确写入以利用并行计算的代码通常失去编译器的优化策略的益处。这是因为管理并行执行需要大量额外的代码,现有的编译器在优化发生之前添加它。优化器不知道如何解释新的代码,所以他们并不尝试提高其性能。

在下周举办的计算机协会的并行编程原理和实践研讨会上,麻省理工学院的计算机科学与人工智能实验室的研究人员将展示一个流行的开源编译器的新变化,在添加并行执行所需的代码之前进行优化。

因此, Charles E. Leiserson ,作为MIT的电子工程和计算机科学Edwin Sibley Webster 教授说,他们的编译器“现在比任何商业或开源编译器优化并行代码更好,也能编译其中一些这些其他编译器所不能编译的代码。”

这种改进纯粹是来自研究人员修改过的编译器的一部分的优化策略,这个编译器过去用于编译常规的串行程序。研究人员的方法是更加直接地添加专门针对并行程序的优化。因为在未来的岁月,计算机芯片将添加越来越多的“核心”或并行处理单元,这种优化将发挥作用至关重要的。

在添加并行处理所需的额外代码之前进行优化的想法已经存在了几十年了。但是“编译器开发人员怀疑这是可以做到的,”Leiserson说。

“每个人都说这将是太难了,你必须改写整个编译器。他们说,”Leiserson团队的博士后TaoB. Schardl和电气工程与计算机科学和物理学本科双专业的William S. Moses说,“基本上来说,传统的智慧错了。最大的惊喜是,这不需要重写80%以上的编译器通过做分析或优化。 而比利通过修改的400万行代码库6,000行代码。

Schardl  作为博士后重新加入Leiserson团队之前,在导师Leiserson指导下在麻省理工学院获得电气工程和计算机科学(EECS)博士学位;Moses在学习3年之后将在明年春天以硕士毕业,在论文上与Leiserson是共同作者。

Fork-Jo in 模型

典型的编译器有三个组件:前端,它是针对特定的编程语言定制的;后端,这是针对特定的芯片设计;以及计算机科学家们所说的中端,它使用“中间表示”,与许多不同的前端和后端兼容,来描述计算。在标准的串行编译器中,优化发生在中端。

研究人员的主要创新是采用所谓的并行的fork-join模型的中间表示:在不同的点,程序可以分叉或分支出可以并行执行的操作;以后,分支连接在一起,程序连续执行,直到下一个叉。

在当前版本的编译器中,前端针对称为 Cilk 的fork-join语言,发音为“silk”,但拼写为C,因为它扩展了 C 编程语言。 Cilk是一个特别合适的选择,因为它是由Leiserson团队开发的 - 尽管其商业实施现在由Intel拥有和维护。但是研究人员可能也建立了一个适应流行的OpenMP或任何其他fork-join语言的前端。

Cilk只添加两个命令到C:“spawn”,它启动一个fork,而“sync”启动一个join。这使得使用Cilk的程序员变得容易,但对编写Cilk的开发人员来说更加困难。

使用Cilk,与其他fork-join语言一样,在核心之间划分计算的责任落在被称为运行时的管理程序。但是,以Cilk编写的程序必须明确告诉运行时何时检查计算和重新平衡核心的分配的进度。为了使程序员不必跟踪所有这些运行时调用本身,Cilk像其他fork-join语言一样,将它们留给编译器处理。

所有以前的fork-join语言编译器都是串行编译器的改编,并在将一个程序转换为一个中间表示之前,以及在优化之前,在前端添加运行时调用。在他们的论文中,研究人员举了一个例子。七个简明的 Cilk 代码行计算 Fibonacci 系列中的指定项,需要编译器再添加17行代码运行时调用。设计用于串行代码的中端,对那些额外的17行代码无从下手。

然而,在前端添加运行时调用的唯一替代方案似乎是重写所有中端优化算法以适应fork-join模型。对许多人来说- 包括Leiserson,当他的团队设计的第一个Cilk编译器 - 似乎太令人生畏。

Schardl和Moses的主要观点是,在fork-join模型中只注入一点序列性,使得现有编译器的优化算法更加易于理解。当Cilk向C添加两个基本命令时,MIT研究人员的中间表示将三个添加到编译器的中端:分离,重新附加和同步。

detach命令本质上等同于Cilk的spawn命令。但是重新附加命令指定并行任务的结果必须重新组合顺序。这种简单的调整使得fork-join代码看起来足够像串行编码器,许多串行编译器的优化算法将工作在它上面而没有修改,而其余只需要微小的改动。

事实上,Schardl和Moses写的新代码中,一半以上是添加运行时调用,现有的fork-join编译器添加在前端。另外只需要900行定义新的命令,分离,重新附加和同步。实际只修改的大约2000行代码是分析和优化算法的。

效果

为了测试他们的系统,研究人员构建了流行的开源编译器 LLVM 的两个不同版本。在其中一个版本,他们单独分离出中端,但修改了前端,添加 Cilk 运行时调用;在另一个版本,他们独自分离前端,但在中端实现了它们的fork-join中间表示,只在优化之后才添加运行时调用。

然后他们编写了20个Cilk程序。对于20个程序中的17个,使用新的中间表示的编译器产生更高效的软件,其中三分之一的提高了10%到25%效率。在新编译器生成效率较低的软件的程序上,效率下降小于2%。

卡内基梅隆大学计算机科学教授盖伊·布莱洛克(Guy Blelloch)说:“在过去的10年里,所有的机器都有多核。“在此之前,在顺序编译器和顺序调试器及一切的基础设施上都有大量的工作。当多核命中时,最简单的事情就是在现有基础设施之上添加[可重用的代码块]库。下一步是让编译器的前端为你调用库调用。”

“Charles和他的学生一直在做的事情实际上是把它深入到编译器,以便编译器可以对与并行性有关的事情进行优化,”Blelloch说。 “这是一个必要的步骤。它应该在许多年前完成的。目前还不清楚这到底获得多少好处,但大概你可以做以前不可能做的很多优化。”

原文:http://news.mit.edu/2017/optimizing-code-compiler-parallel-programs-0130

长按二维码可以关注“网路冷眼”

麻省理工学院(MIT)优化过的编译器产生更高效的并行程序

原文  http://mp.weixin.qq.com/s?__biz=MzI4NjYwMjcxOQ==&mid=2247483811&idx=1&sn=4555601aab9b55067890ecd550b74465&chksm=ebdb2513dcacac05b9579dbadd3536209e06904185859d7e62d4c8ae4b2a24766ba26113478d#rd
正文到此结束
Loading...