迎接多核编程时代:你准备好了吗?

如今具有上千个内核的集群已经司空见惯了。在普通的台式机和笔记本电脑中可以见到具有数百个内核的GPU芯片,这些芯片除了完成图形处理任务外,现在还被用于计算事务。

为目前的服务器、台式机和笔记本电脑系统编程相对来说还比较简单。不过,随着内核数量呈1个或2个数量级的增加,事情变得越来越具有挑战性。举例来说,服务器可能包含多个多核芯片,每个芯片可向对称多处理(SMP)系统提供数十个支持虚拟机(VM)的内核,从而允许系统运行数百个虚拟机。

过去,一般使用高速总线或交换系统链接芯片内的多个内核。但***架构倾向于采用非统一内存架构(NUMA)方法。芯片通常含有大量片上内存(采用一级、二级或三 级缓存的形式)。Intel、AMD和其它公司还为内核配置了多个内存控制器。

片上内核可以快速访问它们的一级缓存,但由于数据远离内核,因此具有较长的延时。片外访问请求通过芯片互连进行传送。当这些请求没有期望的信息时,Intel和AMD采用芯片之间的多个点到点连接并通过相邻芯片传送这些请求。

遗憾的是,发送到数量极其庞大的内核要求采用不同的方法,如网格或更常见的网络/集群技术。诸如串行快速I/O(SRIO)、InfiniBand和以太网等网络接口就经常被用来实现集群。消息包用来处理通信事务。与片上通信相比,此时的延时一般较长。

SRIO具有最少的开销和最小的数据包,并提供端到端的握手。InfiniBand一般用于处理较大的消息,是许多超级计算机集群的***。以太网具有明显的开销和延时问题,但使用十分普及,已经成为互联网的最主要接口。这三种接口都可以用于片外通信,但对于片上通信而言,设计变化较大。



SMP NUMA芯片

许多公司正在致力于研究具有数百甚至数千个内核的芯片,一些公司现在已经可以供货。Tilera公司的64位Tile-Gx产品线非常适合通信应用,而该公司的***产品还可以满足云和服务器集群要求(参见electronicdesign.com网站上发表的“Single Chip Packs In 100 VLIW Cores”)。Adapteva公司的32位Epiphany(图1)架构则支持嵌入式信号处理(参见electronicdesign.com网站上发表的“Multicore Array Targets Embedded Applications”)。

图1:Adaptewa的Epiphany 32位内核通过矩形的网格链接在一起。

Tilera和Adapteva公司给每个处理内核都配套了通信交换机,该交换机是通信网格的一部分。每个内核有自己的实现方式和特点,但它们非常类似,因为网格由多种通信网络组成,可承载不同类型的信息。

Tilera在这种网络中还加入了缓存支持功能,因为该公司实现了一种复杂的缓存一致机制,允许将内核组织起来形成“计算岛”。这些内核允许隔离,因此单颗芯片可以一次运行多个操作环境。对这些区域中的内存的访问操作相同,与所涉及的内核无关,因为缓存是分布式的,但这也给访问与另一个内核相关的数据带来了额外延时。

Adapteva的内核也存在类似的访问延时问题和功能,但这些内核没有任何本地缓存。同样,所有内核都能访问系统中的所有内存。每个内核有32kB的存储器供代码和数据共享。这种方法使编程人员需承担更多的责任,但极大地简化了芯片设计。该方法还能降低复杂性和对电源的要求。Epiphany内核主要用于嵌入式应用,该类应用中,设计人员通常需要管理整个系统,而安全等细节要求并没有提升。

这两种方法只是强调了编程人员在处理大量内核时面临的一些挑战。只有大部分内核在做有用工作时,这些系统才是高效的。在单颗内核上运行串行算法无法从相邻内核获得任何优势。

Intel公司的Larrabee(参见electronicdesign.com网站上发表的“Intel Makes Some Multicore Lemonade”)催生了Intel的22nm Knights Corner多集成内核(MIC)平台(图2)。Knights Corner拥有32个支持四线程的1.5GHz内核,总共支持128个线程。Knights Corner还在使用了环的内核间提供缓存一致性。这种环在Larrabee中使用过,可连接到GDDR5(图形化双倍数据速率第5版)内存控制器、I/O和一些固定功能逻辑(图3)。

图3:Knight Corner平台通过一个高速环连接Intel架构(IA)内核。

共享内存可用于进程间通信,并用来实现消息传递系统。换句话说,一些硬件设计用硬件实现消息传递,这样可以简化软件设计。当多芯片系统创建出来后,这些系统将更容易发展。



消息传递芯片与系统

消息传递网格网络在Intel的单芯片云计算机(SCC)上将24个片(tile)联结在一起。每一片有一个5端口的路由器,其中一个端口专属于两个x86 IA内核。这两个内核共享一个16MB的消息缓存。每个内核有自己的一级和二级缓存。4个DDR3(双倍数据速率3)内存控制器分布于通信网格的四周。

这种网格网络具有2TB/s的带宽。与Adapteva的Epiphany类似,SCC使用固定的X-Y路由机制。区别在于,Epiphany工作在字级,而Intel的芯片工作在消息级。SCC路由器支持两个消息类,可实现8个虚拟通道。

SeaMicro公司没有把许多内核放到单颗芯片上,而是用256个双内核、1.66GHz Intel Atom N570芯片搭建了一个系统(参见electronicdesign.com网站上发布的“512 64-Bit Atom Cores In 10U Rack”)。有个1.28Tb/s的环形结构连接着这些64位芯片。消息传递用于芯片之间的通信。这种环形结构还能将处理器连接到SATA存储控制器和以太网控制器。



多道程序设计方法

并行编程方法多种多样,有时取决于基本的硬件架构。许多方法要求共享内存,而基于消息的解决方案可以被映射到各种架构。

消息传递接口(MPI)包含大多数网络平台都提供的基本套接字。采用最基本的形式时,消息传递接口是任务之间面向字符或面向记录的管道。通过消除与二进制数据有关的许多问题,可扩展标记语言(XML)改变了数据向四周传递的方式,但这需要花费更多的编程开销。

MPI论坛提供的MPI标准库经常用于任务级并行编程通信,它支持从集群到大量并行机器的所有设备。

MPI规范包括进程、组和通信器。一个进程可以属于一个或多个组。通信器提供了进程之间的链路,并包含一组有效参与者。内部通信器在组内工作。中间通信器在组间工作。通信器的创建和销毁是动态进行的。

OpenMP(开放式多处理)是一种共享内存的应用编程接口(API),经常与SMP系统一起使用。编译器内部的支持是必须的,C、C++和Fortran等众多编程语言都可以获得OpenMP支持。OpenMP比MPI简单,但缺乏细微的任务控制机制,而且不支持GPU。

多内核协会(MCA)设计的规范不仅提供了系统之间的互操作性,而且提供了操作系统之间的可移植性。其OpenMCAPI(开放多内核通信API)可促进基本的多内核共享内存通信。

MCAPI 1.0规范发布于2008年,它定义了轻量级进程间通信(IPC)系统,这种系统支持种类广泛的环境,包括SMP、不对称多处理(AMP)、集群甚至ASIC和FPGA。

MCAPI提供基本的消息传递支持,可以帮助开发人员在上面搭建更为复杂的系统。MCAPI能够充分发挥共享内存系统和其它架构的优势。MCA多内核资源管理API(MRAPI)作为MCAPI的有效补充,提供了应用级的资源管理功能。MRAPI可应用于SMP和AMP系统。

共享内存系统本身可用于矩阵操作,像GPU那样的多内核平台也运作良好。MathWorks公司的Matlab因为支持数字运算而非常出名,它不仅可以利用多内核SMP系统,还能充分利用GPU功能(参见electronicdesign.com网站上发表的“Mathworks Matlab GPU Q And A”)。Matlab可以隐藏基本的计算系统。一些Matlab应用程序在GPU上运行时可以取得显著的加速效果,但许多Matlab应用程序在CPU上运行得一样好甚至更好。

凭借NVidia GPU的CUDA功能,GPU开创了非图形化显示应用的先河(参见electronicdesign.com网站上发表的“SIMT Architecture Delivers Double-Precision Teraflops”)。NVidia的CUDA支持C、C++和Fortran等编程语言,但正如指出的那样,仅适用于NVidia硬件。

Kronos Group的OpenCL(开放计算语言)是可以在各种GPU和CPU上运行的一种更为通用的解决方案(参见electronicdesign.com网站上发表的“Match Multicore With Multiprogramming”)。OpenCL提供了与CUDA相似的架构和功能。

在OpenCL术语中,内核(kernel)是一个可以在GPU等器件上运行的函数,可以被主程序调用。内核有点类似于远程过程调用(RPC)。OpenCL可以在同时也是主机的CPU上运行,但一般情况下OpenCL用于充分发掘其它计算资源的优势。

OpenCL内核具有一个与之关联的OpenCL程序。程序所做的工作在ND-Range环境中进行定义,这种环境包含了工作组(work-group),而工作组又包含了工作项(work-item)。工作项与CUDA线程是一样的。OpenCL模型基于的是GPU中采用的单指令多线程(SIMT)架构。

工作项执行计算任务。工作组定义了工作项相互之间如何进行通信。SIMT方法有许多线程在处理不同的数据,但运行相同的代码。虽然不是所有应用程序都能很好地映射到这种架构,但还是许多应用程序可以做到这一点,GPU可以将性能较CPU提高10至100倍,因为GPU内部具有数百个内核。

主应用程序定义了使用OpenCL API的所有组件,包括器件上的内存分配,并提供内核程序。这种内核程序以源码形式提供,在运行时编译。这种方法提供了可移植性,并且因为计算过程通常在大型数据数阵列上完成,可将开销减至最小。

同样,编译只在内核建立时执行一次,而不是每次调用内核时都要执行。发往内核的参数将进入队列,从而使得主机能以异步方式提供数据。结果从队列消息中读取。

CUDA和OpenCL对并行计算来说相对较新,面向的是数据并发机制。目标管理集团(OMG),也即统一建模语言(UML)的传播者,做了许多工作来标准化并行计算。

UML可以用来定义并行处理,但大多数编程人员更愿意使用基于其它OMG规范的工具,如公共对象请求代理架构(CORBA)(参见electronicdesign.com网站上发表的“Software Frameworks Tackle Load Distribution”)和数据分布式服务(DDS)(参见electronicdesign.com网站上发布的“DDS V1.0 Standardizes Publish/Subscribe”)。



分布式任务

CORBA提供了一个远程过程调用环境,这一环境可在协同操作任务的异类网络中工作。CORBA使用了一种接口定义语言(IDL)来规范数据如何在系统之间映射,从而允许基本系统汇集可能具有不同格式、压缩率或编码(如小端与大端格式整数)的数据。CORBA为所有主要的编程语言(如Ada、C、C++、Java甚至COBOL和Python)提供了标准映射,并为许多其它语言提供了非标准的实现。

CORBA也使用对象请求代理(ORB)。ORB提供了对由ORB组成的CORBA网络的程序访问。ORB额外提供许多服务,包括目录服务、调度和事务处理。来自不同源的ORB可以在一起工作。

CORBA实现一般都较大,可满足复杂的应用需求。多个系统提供相似的服务,如微软的DCOM(分布式组件对象模型)和.NET框架或Java的远程方法调用(RMI)。一些方法提供更适合嵌入式系统的较轻量级环境。其它方法则提供了层次化的实现,这允许低端节点成为更复杂环境的一部分。

OMG DDS代表用于数据分发的一类发布/订阅方法,但它有别于RPC方法。利用DDS,数据源将把信息发布为主题,不管有多少订阅者都能访问这些主题。数据在可用或改变时即向外提供。

DDS可能像CORBA一样复杂,因为涉及许多问题,包括汇集、流控制、服务质量和安全等细节。其它发布/订阅接口的复杂性通常都没DDS高,因为它们被设计为与特定的操作系统或语言一起使用。同样,有许多途径将并行通信方法混合在一起。

微软的分散软件服务(DSS)是一种轻量级、REST风格(代表性状态转移)、基于.NET的运行时环境,最初是微软机器人开发平台(RDS)的一部分(参见electronicdesign.com网站上发布的“Frameworks Make Robotics Development Easy—Or Easier, At Least”)。当然,轻量级是一个相对术语,因为DSS相当深奥复杂。

DSS设计为在并发和协调运行时(CCR)之上运行,而CCR也是机器人开发平台(RDS)的一部分。事实表明,DSS对其它应用来说也非常有用。DSS是一种基于web的技术,因此每个DSS节点都有一个通用资源标识符。DSS提供了一种动态发布和识别服务的机制。

对机器人技术来说,微软DSS/CCR的另外一种替代技术是开源机器人操作系统(ROS)(参见electronidesign.com网站上发布的“Cooperation Leads To Smarter Robots”)。ROS同样基于web,但它将诸如安全等许多问题转移到了外部网络支持。



并行语言

诸如MathWorks的Matlab等编程语言在处理矩阵操作时提供了并行操作功能,可充分发挥GPU(如果有的话)的优势。并行计算工具箱增加了语言功能,如并行的for循环、特殊的数组类型和并行的数字函数。

Intel的Parallel Studio遵循相似的方法(参见electronicdesign.com网站上发表的“Dev Tools Target Parallel Processing”)。其功能特性包括线程创建模块(TBB),该模块用于表达基于C++任务的并行机制(参见electronicdesign.com网站上发布的“Parallel Programming Is Here To Stay”)。***版本提供诸如parallel_pipeline等函数,这种函数提供了强类型、lambda友好的管线接口。

Parallel Studio的另外一个部分是Intel的Cilk++软件开发套件(SDK)。Cilk++是通过Parallel Studio C/C++编译器对C++进行的并行扩展。它增加了cilk_for、cilk_spawn和cilk_sync等关键词。与大多数并行编程语言扩展一样,Cilk++设计允许任务的低开销创建、管理和同步。运行时支持负载均衡、同步和任务间通信。

像Java等一些编程语言已经具有先进的任务管理功能。Ada就是一种非常成熟的编程语言,在研究并行编程时应加以考虑。Ada对任务管理的支持非常好,在要求高度安全和可靠性的应用中使用Ada说明了为何该语言有助于大型复杂的并行处理应用。

爱立信(Ericsson)最初为电话管理应用开发了Erlang编程语言。这种语言使用演员模型进行并发处理。Erlang也像Java一样提供自动碎片收集功能。函数式语言子集有严格的评估、单赋值和动态类型。对于并行编程来说,函数式编程语言具有许多优势。

Haskell是最重要的函数式编程语言之一(参见electronicdesign.com网站上发表的“Embedded Functional Programming Using Haskell”)。由于Haskell同样还用于研究,因而并行编程支持处于不断变化中。某种方法采用的“策略”可以针对特定应用或主机进行调整。

Haskell的Hindley-Milnet全局类型推论在处理并行算法时可提供许多优势,但函数式编程的单赋值(不可变的变量)、惰性评估以及Monads的使用将使习惯于C/C++和Java的编程人员感到困惑。

谷歌(Google)的Go和Scala是全新设计的两种语言,与Haskell相比更加传统,可提供并发编程环境(参见electronicdesign.com网站上发表的“If Your Programming Language Doesn’t Work, Give Scala A Try”)。这两种语言吸收了函数式编程和其它编程语言的许多长处。Scala虽然不是Java的超集,但非常接近。

Go包含了被称为goroutines的轻量级线程,这些线程使用图案匹配通道进行通信。Scala在Java虚拟机(JVM)上运行,它包含了具有收集接口的并行收集功能,但可以使用并行语义处理内容。

美国国家仪器(NI)公司的LabVIEW是少数几种数据流编程语言中的其中一种(参见electronicdesign.com网站上发表的“LabVIEW 2010 Hits NI Week”)。数据流语义允许并行出现计算任务,而LabVIEW应用程序可以很好地映射到包括FPGA和GPU在内的并行硬件。LabVIEW的图形化特性使得并行操作对编程人员来说更加透明。

并行编程有许多种选择。像Cilk++或OpenCL等逐步增强型语言可能适合许多场合使用,但开发人员也不应忽视那些更加激进的变化。

免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删

QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空