在过去几年中,关于热词异构计算的提及次数一直在增加,并且在未来几年将继续被提及,因为异构计算已成为常态。什么是异构计算,为什么它正成为规范?我们如何从软件和硬件方面来应对它?本文提供了对其中一些问题的答案,并提出了对其他问题的不同观点。
让我们从简单的问题开始。什么是异构计算?简而言之,它是一种方案,其中不同的计算节点具有不同的能力和/或执行指令的不同方式。因此,异构系统是一个并行系统(单核系统几乎已成为过去)。当多核系统出现时,它们是同构的——也就是说,所有核心都是相似的。从顺序编程到并行编程的转变,曾经只是小众程序员的领域,是一个巨大的飞跃。在异构计算中,核心是不同的。
核心可以具有相同的架构能力——例如,相同的超线程容量(或缺乏)、相同的超标量宽度、向量算术等。然而,即使在这些能力上相似的核心也具有某种程度的异构性。这是因为每个核心现在都有自己的 DVFS(动态电压和频率调节)。执行更多工作的核心会更热,因此会降低其频率,从而变得更慢。因此,即使具有相同规格的核心也可能是异构的。这是第一种类型的异构性。
第二种类型涉及具有不同架构能力的核心。一个例子是具有几个简单核心(例如,单发射、无乱序执行、无推测执行)的处理器,以及一些胖核心(例如,具有超线程技术、宽超标量核心,具有乱序和推测执行)。
前两种类型的异构性涉及具有相同顺序编程执行模型的核心——也就是说,即使在底层指令之间存在某种并行性,每个核心看起来也是按顺序执行指令的。使用这种多核机器,您可以编写并行代码,但是每个线程(或进程)都由核心以看似顺序的方式执行。如果包含不以这种方式工作的计算节点怎么办?这是第三种类型的异构性。
在这种类型的异构性中,计算节点具有不同的执行模型。这里存在几种不同类型的节点。最著名的是 GPU(图形处理器),现在除了图形之外,还用于许多不同的应用。例如,GPU 在深度学习中被大量使用,尤其是在训练部分。它们也用于许多科学应用,并提供比传统核心高几个数量级的性能。这种性能提升的原因是 GPU 使用单指令(或线程)、多数据执行模型。假设您有一个大型矩阵,需要将此矩阵的每个元素乘以一个常数。使用传统核心,这是一次完成一个元素,或者最多一次完成几个元素。使用 GPU,您可以一次乘以所有元素,或者如果矩阵非常大,则在极少的迭代中完成。GPU 在对大量数据进行类似的独立操作方面表现出色。
另一种偏离传统顺序方案的计算范例是 FPGA(现场可编程门阵列)。我们都知道软件和硬件在逻辑上是等价的,这意味着您可以使用软件完成的事情也可以使用硬件完成。硬件解决方案速度更快,但灵活性较差。FPGA 试图弥合这一差距。它是一个可以由程序员配置以实现特定功能的电路。假设您需要在元素组上计算多项式函数。单个多项式函数被编译成数十条汇编指令。如果需要计算该函数的元素数量不足以需要 GPU,并且不足以高效地在传统核心中完成,那么 FPGA 是一个不错的选择。FPGA 已在许多高性能集群中使用。随着英特尔去年收购了 FPGA 市场的主要参与者之一 Altera,预计 FPGA 和传统核心将更加紧密地集成。此外,微软已开始在其数据中心(Catapult 项目)中使用 FPGA。
最近添加到计算节点选项中的新成员是 Micron 的 AP(Automata 处理器)。3 AP 非常适合图分析、模式匹配、数据分析和统计。可以将其视为并行工作的硬件正则表达式加速器。如果您可以将手头的问题表述为正则表达式,那么您可以期望获得比 GPU 能够提供的更高的性能。AP 使用 FPGA 构建,但旨在更有效地处理正则表达式。
除了上述计算节点之外,还有许多其他处理节点,例如 DSP(数字信号处理器)和 ASIC(专用集成电路)。然而,这些针对的应用领域较小,并且不如前面提到的那些通用。受大脑启发的神经形态芯片,例如 IBM 的 TrueNorth 芯片,正在开启认知计算的时代。2 认知计算由 IBM Watson 和 IBM 的 TrueNorth 倡导,在 AI 计算机系统 Watson 在Jeopardy上的出色表现之后,现在已应用于医疗应用,并且正在探索其他领域。然而,现在将其与其他更通用的核心进行比较还为时过早。
本文的其余部分仅考虑传统核心(具有不同的能力)、GPU、FPGA 和 AP。图 1 显示了异构计算系统的全貌,尽管由于可编程性的成本,找到具有图中所示异构性水平的系统是不太可能的。一个真实的系统将只包含这些类型的一个子集。
拥有这种多样化的计算节点有什么优势?答案在于性能和能源效率。假设您有一个包含许多小线程的程序。在这种情况下,最佳选择是一组小核心。如果您有极少数复杂的线程(例如,具有指针追踪的复杂控制流图),那么复杂的内核(例如,胖超标量内核)是首选。如果您将复杂的线程分配给简单的核心,则结果是性能不佳。如果您将简单的线程分配给复杂的内核,则会消耗比所需更多的电力。GPU 对于具有数据并行性的应用程序具有非常好的性能-功耗效率。需要的是一种通用机器,它可以以高性能-功耗效率执行不同风格的程序。实现这一目标的唯一方法是拥有一台异构机器。3 现在,从笔记本电脑到平板电脑再到智能手机,大多数机器都具有异构架构(多个核心和一个 GPU),并且预计在(非常)不久的将来会有更多的异构性。我们应该如何应对这种从同构到异构的范式转变?
硬件层面存在若干挑战。第一个是内存层次结构。内存系统是任何计算机系统中的主要性能瓶颈之一。虽然处理器在几年前一直在遵循摩尔定律,在性能上取得了良好的飞跃,但内存系统却没有。因此,处理器速度和内存速度之间存在很大的性能差距。这个问题从单核时代就存在了。在这种情况下,使其更具挑战性的是共享内存层次结构(几级缓存内存,然后是主内存)。谁共享每一级缓存?这里讨论的每个计算核心都针对一个程序(或线程或进程),其特性与其他计算核心针对的程序不同。例如,GPU 需要更高的带宽,而传统核心需要更快的访问速度。因此,需要的是一种内存层次结构,它可以减少不同核心之间的干扰,同时有效地处理每个核心的不同需求。
设计这样的层次结构绝非易事,尤其是在考虑到除了性能问题之外,内存系统还是功耗的重要来源。这一挑战是工业界和学术界密集研究的主题。此外,我们正接近非易失性存储器的时代。如何才能最好地利用它?这里请注意内存模块的异构性:用于缓存(SRAM)、易失性存储器(DRAM)、非易失性存储器(MRAM、STT-RAM、PCM、ReRAM 和更多技术)。
硬件层面的另一个挑战是互连:我们应该如何连接不同的核心和内存层次结构模块?粗线损耗的功率较少,但由于它们占用更多的芯片空间,因此导致带宽较低。光互连领域的研究越来越多。拓扑结构(环形、环面、网格)、材料(铜、光学)和控制(片上网络协议)是芯片级、板级以及跨板级研究的热门话题。
另一个挑战是在不同的核心之间分配工作负载,以获得最佳性能和最低的功耗。这个问题的答案必须在整个计算堆栈中找到,从算法到工艺技术。
从单板到多板再到高性能计算机的转变也意味着从共享内存到分布式内存的转变。这使得互连和工作负载分配更具挑战性。
在软件层面,情况也极具挑战性。我们将如何编程这些野兽?顺序编程很难。并行编程更难。如果我们关心性能和功耗效率,那么异构机器的并行编程就极具挑战性。有几个考虑因素:向程序员公开多少硬件,成功的衡量标准,以及对新的编程模型(或语言)的需求。
在尝试回答这些问题之前,我们需要讨论程序员的生产力与生成的软件性能之间永恒的问题。通常的观点是,需要向程序员隐藏硬件的许多方面,以提高生产力。用 Python 编写程序比用 C 编写程序更高效,而用 C 编写程序又比用汇编编写程序更高效,对吗?答案并非如此简单,因为例如,许多 Python 例程只是 C 包装器。随着异构机器的激增,性能程序员将创建越来越多的库供生产力程序员使用。然而,即使是生产力程序员也需要做出一些艰难的决定:如何将应用程序分解为适合手头硬件的线程(或进程)(这可能需要尝试不同的算法),以及程序的哪些部分不需要高性能,可以在较低功耗模式下执行(例如,需要 I/O 的部分)?
定义成功的衡量标准对生产力和性能程序员都提出了许多挑战。为异构机器编写的程序的成功衡量标准是什么?这些衡量标准中的许多都与同构机器的传统并行代码的衡量标准有共同之处。当然,第一个是性能。相对于顺序版本和同构计算的并行版本,您获得了多少加速?
第二个衡量标准是可扩展性。随着添加更多核心,您的程序是否会扩展?异构计算中的可扩展性比同构情况更复杂。对于后者,您只需添加更多相同的核心。对于异构机器,您有更多选择:添加更多某种类型的核心,或更多 GPU,或可能是 FPGA。程序在每种情况下的行为如何?
第三个成功的衡量标准是可靠性。随着晶体管变得越来越小,它们变得更容易受到故障的影响,无论是瞬时故障还是永久故障。您是否将处理故障的问题留给硬件、系统软件,还是程序员应该有发言权?每种策略都有其优缺点。一方面,如果将其留给硬件或系统软件,程序员的生产力会更高。另一方面,程序员比系统更了解情况,可以决定如何在核心数量因故障而减少或线程因瞬时故障而产生错误结果时实现性能的优雅降级。例如,程序员可以拥有同一子例程的两个版本:一个在 GPU 上执行,另一个在多个传统核心上执行。
可移植性是另一个问题。如果您正在为明确定义的机器编写小众程序,那么前三个衡量标准就足够了。但是,如果您正在为许多不同的异构计算机器编写公共使用的程序,那么您需要确保可移植性。例如,如果您的代码在具有 FPGA 而不是 GPU 的机器上运行会发生什么?这种情况在不久的将来并非不可能发生。
鉴于这些问题和考虑因素,最佳策略是什么?我们应该引入新的编程模型(和语言),还是应该修复/更新当前的编程模型(和语言)?心理学对此有所看法。一个人拥有的选择越多,就越好——直到达到某个阈值。超过该阈值,人们会变得不知所措,并坚持使用他们正在使用的任何语言。但是我们必须非常小心地修复一种语言。Perl 曾经被称为“只写语言”。我们不想陷入同样的陷阱。决定修复/修改哪种语言是一个非常艰难的决定,错误的决定将付出非常高的代价。对于异构计算,OpenCL(开放计算语言)似乎是共享内存机器的良好候选者,但它需要更加用户友好。分布式内存怎么样?MPI(消息传递接口)足够好吗?目前可用的任何语言/范例是否将可靠性视为成功的衡量标准?
最佳方案似乎是双重的:在学术界发明和测试新范式,同时在工业界进行过滤。过滤是如何发生的?当计算世界中发生拐点时,它就会发生。之前的两个拐点的例子是从单核转向多核以及 GPU 的兴起。我们目前正在同时目睹几个拐点:接近百亿亿次级计算和物联网的兴起。异构计算是这两者的使能技术。
异构计算已经到来,并且将继续存在。充分利用它将需要重新审视整个计算堆栈。在算法层面,请记住,现在计算比内存访问和数据移动便宜得多。编程模型需要处理生产力与性能之间的关系。编译器需要学习使用异构节点。它们还有很长的路要走,因为编译器在并行计算领域(总体而言)的成熟度还不如在顺序编程领域。操作系统需要学习新技巧。计算机架构师需要决定将哪些节点放在一起以获得最有效的机器,如何设计内存层次结构,以及如何最好地连接所有这些模块。在电路级别和工艺技术级别,我们有一个长长的可靠性、功耗、兼容性和成本愿望清单。在计算堆栈的各个层面上都有许多唾手可得的果实,如果我们能找出荆棘,所有这些果实都准备好被采摘。
1. HSA 基金会; http://www.hsafoundation.com/。
2. IBM 研究院。认知时代; https://www.research.ibm.com/cognitive-computing/。
3. Micron。Automata 处理器; http://www.micronautomata.com/。
Mohamed Zahran 是纽约大学计算机科学的临床副教授。他的研究兴趣涵盖计算机体系结构和硬件/软件交互的多个领域。Zahran 获得了马里兰大学帕克分校电气和计算机工程博士学位。
无处理器计算
Satnam Singh
异构系统使我们能够将编程目标对准适当的环境。
https://queue.org.cn/detail.cfm?id=2000516
面向大众的 FPGA 编程
David F. Bacon、Rodric Rabbah 和 Sunil Shukla
如果 FPGA 要成为主流计算的一部分,则必须提高其可编程性。
https://queue.org.cn/detail.cfm?id=2443836
与 John Hennessy 和 David Patterson 的对话
他们撰写了关于计算的书籍
https://queue.org.cn/detail.cfm?id=1189286
版权所有 © 2016 归所有者/作者所有。出版权已许可给 。
最初发表于 Queue vol. 14, no. 6—
在 数字图书馆 中评论本文
David Chisnall - 如何设计 ISA
在过去的十年中,我参与了几个项目,这些项目设计了 ISA(指令集架构)扩展或用于各种处理器的全新 ISA(您甚至可以在 RISC-V 规范的致谢中找到我的名字,可以追溯到第一个公共版本)。当我开始时,我对什么构成好的 ISA 知之甚少,而且据我所知,这在任何地方都没有正式教授。
Gabriel Falcao, João Dinis Ferreira - PiM 还是非 PiM
随着人工智能成为边缘数十亿物联网 (IoT) 设备的普及工具,数据移动瓶颈对这些系统的性能和自主性施加了严格的限制。PiM(内存内处理)正在兴起,成为一种缓解数据移动瓶颈的方法,同时满足依赖 CNN(卷积神经网络)的边缘成像应用的严格性能、能效和准确性要求。
David Chisnall - 没有通用处理器这种东西
计算机体系结构中存在将处理器和加速器归类为“通用”的日益增长的趋势。在今年国际计算机体系结构研讨会 (ISCA 2014) 上发表的论文中,45 篇中有 9 篇明确提到了通用处理器;另外一篇还提到了通用 FPGA(现场可编程门阵列),另一篇提到了通用 MIMD(多指令多数据)超级计算机,将定义拉伸到了崩溃的边缘。本文提出了一个论点,即根本没有真正通用的处理器,并且对这种设备的信念是有害的。
Satnam Singh - 无处理器计算
从程序员的角度来看,硬件和软件之间的区别正在变得模糊。随着程序员努力满足当今系统的性能要求,他们将面临越来越需要利用替代计算元件(例如 GPU(图形处理器),它是为数据并行计算而颠覆的图形卡)和 FPGA(现场可编程门阵列)或软硬件的需求。