传统的计算机体系结构是冯·诺依曼结构,如图1-1所示。冯·诺依曼的论文确定了计算机体系结构中的5大部件:运算器、控制器、存储器、输入设备、输出设备。
图1-1 冯·诺依曼结构示意图
自1958年罗伯特·诺伊斯(Robert Noyce)和杰克·基尔比(Jack Kilby)发明集成电路以后,冯·诺依曼结构中的各个部件开始逐渐被集成电路所取代:首先是处理器,然后是存储器。早期的磁性存储器无法用集成电路替代,直到1965年IBM发明了基于集成电路的动态随机访问存储器(Dynamic Random Access Memory,DRAM),存储器才被集成电路所取代。摩尔定律(1965年)和Dennard定律(1974年)为集成电路的发展制定了路线图。因为处理器和存储器都适用于摩尔定律,“Amdahl的另一条定律”也得到了保证。在很长一段时间内,计算系统的性能遵循摩尔定律稳步提升。
1.内存墙
由于晶体管级电路设计的局限性,DRAM的读延迟率先跟不上摩尔定律的步伐。DRAM中存储1比特数据的单元由一个电容器和一个晶体管组成。电容器用于存储数据,晶体管用于控制电容器的充放电。读数据时,晶体管被选通,电容器上存储的电荷将非常轻微地改变源极的电压。感测放大器(Sense Amplifier)可以检测到这种轻微的变化,并将电压微小的正变化放大到高电平(代表逻辑1),将电压微小的负变化放大到低电平(代表逻辑0)。感测过程是一个缓慢的过程,感测时间决定了DRAM的访问时间。DRAM访问时间的缩短速度远远落后于摩尔定律下处理器两次访存之间时间间隔的缩短速度。这就是摩尔定律发展中遇到的内存墙问题,如图1-2所示。
如果每次访存都需要耗费几十到几百个周期等待存储器的响应,处理器的性能提升就会变得毫无意义。为了解决这一问题,计算机体系结构研究铸造了两把利剑:高速缓存(Cache)和内存级并行(Memory-Level Parallelism,MLP)。
缓存利用局部性原理,减少了处理器访问主存的次数。简单地说,处理器正在访问的指令或数据后面可能会被多次访问,且这些指令或数据附近的内存区域也可能会被多次访问。因此,在处理器第一次访问这一区域时,这些指令或数据将被复制到处理器的缓存中,这样的话,处理器再次访问该区域的指令或数据时,就不需要再访问外部的存储器了。加入缓存后,冯·诺依曼结构中的存储器就变成了一种层次化的存储结构。
图1-2 内存墙问题
缓存对编程模型而言是一个完全透明的部件。虽然程序员可以根据缓存的特点对程序代码进行特定的优化,从而获得更好的性能,但程序员通常无法直接干预对缓存的操作。因此,在编程模型设计空间的探索中,一般不会考虑缓存的问题。
MLP是指处理器同时处理多个内存访问指令的能力。在层次化存储结构的缓存和DRAM之间,以及DRAM的多个存储体(Bank)之间,多个来自处理器的访存请求可以被并行处理。例如,当访存指令在缓存中未命中而等待DRAM中的数据时,若后续访存指令在缓存中命中,后续访存指令可以被先执行,从而避免处理器阻塞在少数延迟很大的未命中访存指令上。MLP虽然不能减少单个操作的访问延迟,但它增加了存储系统的可用带宽,从而提高了系统的总体性能。在实现MLP时,硬件开发者设计了多线程并行执行、指令多发射和指令重排序等硬件机制。其目的都是引入多个并发的、没有依赖关系的访存指令,从而开发MLP,并让内存墙问题得以大大缓解。
2.功耗墙
随着单个芯片上集成的晶体管数量越来越多、密度越来越大,设计和制造芯片时必须要考虑散热的问题。1974年,罗伯特·丹纳德(Robert Dennard)提出了Dennard缩放比例定律(Dennard Scaling),当芯片的尺寸缩小 S 倍、频率提升 S 倍时,只要芯片的工作电压相应地降低 S 倍,单位面积的功耗就会保持恒定。Dennard缩放比例定律的基本原理如图1-3所示。图中, S 是两代半导体工艺之间的缩放因子,通常 ,故下一代工艺单个晶体管的面积是上一代的1/2(长和宽各缩小为上一代的 ),性能是上一代的 倍,电容值是上一代的 。在新一代工艺中,单位面积的晶体管数量会提高 S 2 倍,频率会提升 S 倍,单位面积的功耗却能保持不变。根据Dennard缩放比例定律,Intel等芯片制造公司可以快速地提高芯片的工作频率,同时利用更多的晶体管提供更复杂的功能,而不需要考虑芯片的散热问题。从1971年的Intel 4004处理器到2006年的Intel Core 2处理器,芯片的工作电压逐渐从15V下降到了1V左右。Dennard缩放比例定律因阈值电压的缘故于2006年左右被终结。
在2005年,芯片的工作电压已低至0.9V左右,非常接近晶体管的阈值电压(0.4~0.8V)。受限于晶体管的材料和结构,阈值电压很难进一步降低,因此,芯片的工作电压也无法再降低。从此,芯片的尺寸每缩小一半,单位面积的功耗将提高一倍。更糟糕的是,当工作电压接近阈值电压时,晶体管的栅极到衬底之间的漏电功耗在总功耗中的占比也越来越大。新一代半导体工艺将面临芯片单位面积功耗提升的挑战。这就是摩尔定律发展中遇到的功耗墙问题。
图1-3 Dennard缩放比例定律的基本原理
为了克服功耗墙的问题,2005年以后的芯片设计普遍采用了“暗硅”(Dark Silicon)的思路:利用多核和异构架构等设计策略限制芯片上全速工作(点亮)的工作区域,从而使芯片满足功耗约束。图1-4展示了Intel Skylake架构的处理器版图,单个芯片上有4个CPU核和一个GPU。在任何给定的时间点,只有一部分的电路在工作,从而使芯片满足功耗的约束。
图1-4 Intel Skylake架构的处理器版图
以上述版图为例,可以将实现“暗硅”的硬件机制分为以下三类。
● 增加低频率模块的数量,如设计更大的缓存、更多的单指令多数据(Single Instruction Multiple Data,SIMD)执行单元等。这里的频率是指工作频率或使用频率。以缓存为例,在“暗硅时代”的CPU上有至多接近一半的面积是用来实现缓存的。图1-4所示的CPU缓存包括最末级缓存(Last-Level Cache,LLC)和每个CPU运算单元(Core)中的L1缓存和L2缓存。一方面,由于MLP的存在,缓存的工作频率可以比处理器数据通路的低,在Intel SandyBridge以前的架构中,可以单独控制L3缓存与内核的电压、频率。另一方面,由于CPU的缓存由许多块静态随机存储器(Static Random Access Memory,SRAM)构成,当前没有被访问到的SRAM可以通过门控时钟(Clock Gating)等技术来降低功耗。通过增加缓存来降低硬件频率的机制对编程模型是完全透明的。
● 增加并行的硬件模块数量。根据Dennard缩放比例定律,当采用先进工艺的晶体管尺寸缩小为上一代工艺的1/2时,如果单个处理器内核的频率保持不变,则它的面积缩小为上一代工艺的1/4,功耗(由于单个晶体管的电容值减小)下降为上一代工艺的1/2。这样,如果芯片的功耗预算不变,我们可以在芯片上再增加三个较低频率的内核。同时,由于在任何给定的时间点,只有一部分的处理器内核在工作,所以芯片可以通过门控时钟和门控电压(Power Gating)等技术来关闭部分内核,以进一步地降低功耗。从2005年以后,x86架构的处理器不再专注于提高芯片的频率,而是在新的芯片中增加处理器内核的数量。ARM架构的BIG-LITTLE架构更是在一个芯片上同时放置高性能BIG核和高能效LITTLE核,充分利用并行硬件模块机制提供的设计空间。但是,为了充分利用芯片的性能,程序员不得不学习多线程编程的技巧。基于多线程的并行机制使得硬件的性能难以被程序员充分开发。
● 定制化硬件。通用处理器为了确保其通用性,会有大量的冗余。2010年的一篇ISCA论文指出,在通用处理器上运行H.264解码后发现,处理器的执行单元消耗的能量仅占总能量的5%,大量的能量被消耗在了处理器的取指、译码等模块上。因此,根据应用需求设计定制化的硬件模块,进而构成异构片上系统(Heterogeneous System-on-Chip),可以极大地提高其能效。图1-4中的Intel Skylake架构处理器上集成的GPU就是专门为处理图像渲染而定制的。此外,Intel SSE/AVX等SIMD运算单元也可以看作一种定制化硬件。SIMD运算单元采用一个控制器来控制多个运算器,同时对一组数据向量中的每个元素分别执行相同的操作,从而在这组数据向量上摊薄了处理器取址、译码的开销。当然,SIMD单元仅适用于非常规整的数据级并行的场景。定制化硬件和异构片上系统的普及带来了编程模型的“巴别塔难题”:不同的定制化硬件模块需要不同的编程模型;同样的应用运行在不同的定制化硬件上时,需要花费大量的人力对应用进行“翻译”。
功耗墙难题虽然没有中止摩尔定律的脚步,但却摧毁了冯·诺依曼结构的随机存取机编程模型。由于片上多处理器(Chip Multi-Processor,CMP)和异构架构逐渐成为主流的硬件设计方法,程序员必须直面并行编程模型和异构编程模型。
正是在这一时期,GPU及GPGPU编程模型因其提供了远比CPU高得多的单位算力能量效率而在计算产业中崭露头角。我们将在第1.4.3节中进一步介绍。
3.I/O墙
冯·诺依曼结构可以分为存储、计算和外设三大功能模块。之前的两次危机分别是由存储速度与计算速度不匹配、计算功耗受限而造成的。与此同时,计算机教材一直给学生灌输外设速度是远远慢于计算速度的理念。然而,2015年前后,这一延续了几十年的教条逐渐开始失效。如今,外设速度与计算/存储速度的不匹配,正在导致一道新的I/O墙形成。
自2010年开始,网络带宽飞速增长。自2015年开始,硬盘的读写速率飞速增长,而同时期CPU-DRAM带宽的增长速度远远落后于网络带宽和硬盘读写速率的增长速度。造成这一现象的主要原因有两个:
● 内存墙、功耗墙的先后出现,使得CPU-DRAM带宽的增长速度远远落后于摩尔定律的步伐。当前主流的CPU-DRAM间的DDR接口,其带宽大约每5年至7年提升一倍。
● 网络和硬盘在物理层的技术突破,使其带宽呈爆炸式增长。在21世纪的头十年,主流的网络传输介质是铜双绞线,主流的硬盘存储介质是磁盘。2010年之后,数据中心光通信模块开始普及,相比基于铜双绞线的网卡,光纤网络单卡的带宽从1Gb/s快速提升到数十Gb/s。2015年以后,固态硬盘(SSD)开始取代机械硬盘(HDD)。HDD使用机械马达在磁碟上寻址。受限于磁碟的转速(大约15000转每分钟),单个HDD的带宽最高只能达到数百MB/s。闪存技术的发展,尤其是闪存的写入持久性(Persistence)的进步,使得SSD开始取代HDD。SSD的寻址过程类似DRAM,完全由电信号驱动,因此带宽不再受寻址速度的限制。
时至今日,如何解决I/O墙的问题依然是一个开放问题。学术界和工业界都提出了大量的方案。大多数方案都在尝试让冯·诺依曼结构走向更加异构的方向:为网络和存储增加计算的功能,从而将原本在CPU上的计算卸载到外设上进行。
传统的软件程序设计以串行计算模式为主流,其具有如下特点:
● 一个问题被分解为一系列离散的指令。
● 这些指令被顺次执行。
● 所有的指令均在一个处理器上被执行。
● 在任何时刻,最多只有一个指令能够被执行。
随着科技的发展,许多科学和工程领域的研究团队在对很多领域问题的建模上依赖于超大规模数据的处理和计算,包括大气与地球环境、应用物理、生物科学、遗传学、化学、分子科学、机械工程、电气工程、计算机科学、数学等。与此同时,我们在日常应用(如玩游戏、播放高清视频)中面临的场景模型和数据计算也越来越复杂,商业领域和工业界对计算速度也提出了更高的需求和期待。这些商业应用程序需要以更复杂的方式去处理大量的数据,例如石油勘探、网页搜索引擎、基于Web的商业服务、医学成像和诊断、跨国公司管理、高级图形学技术,以及虚拟现实、网络视频和多媒体技术、协同工作环境等。
目前,并行计算实际上已经被广泛应用。并行计算是相对于串行计算来说的。它是指同时使用多种计算资源解决计算问题的过程,是提高计算机系统计算速度和处理能力的一种有效手段。它的基本思想是用多个处理器来协同求解同一问题,即将被求解的问题分解成若干个部分,各部分均由一个独立的处理器来并行计算。并行计算系统既可以是专门设计的、含有多个处理器的超级计算机,也可以是以某种方式互连的若干台独立计算机构成的集群。
并行计算可分为时间上的并行和空间上的并行两类。
1.时间上的并行:流水线(Pipeline)技术
以汽车装配为例来解释流水线的工作方式。假设装配一辆汽车需要4个步骤:
(1)冲压:制作车身外壳和底盘等部件。
(2)焊接:将冲压成形后的各部件焊接成车身。
(3)涂装:对车身等主要部件进行清洗、化学处理、打磨、喷漆和烘干。
(4)总装:将各部件(包括发动机和向外采购的零部件)组装成车。
这些步骤分别需要从事冲压、焊接、涂装和总装的四个工人。采用流水线制造方式,同一时刻有四辆汽车在装配。如果不采用流水线方式,那么第一辆汽车依次经过上述四个步骤装配完成之后,下一辆汽车才开始进行装配,最早期的工业制造就是采用的这种原始的方式。未采用流水线的原始制造方式,同一时刻只有一辆汽车在装配。不久之后,人们就会发现,某个时段中有一辆汽车在装配时,其他三名工人都处于闲置状态,这显然是对资源的极大浪费。于是,人们开始思考能有效利用资源的方法:在第一辆汽车经过冲压进入焊接工序的时候,立刻开始进行第二辆汽车的冲压,而不是等到第一辆汽车经过全部四个工序后才开始。之后的每辆汽车都是在前一辆冲压完毕后立刻进入冲压工序,这样在后续生产中就能够保证四个工人一直处于运行状态,而不会造成人员的闲置。这样的生产方式就跟河水一样川流不息,因此被称为流水线。
在工业制造中采用流水线可以提高单位时间的产量。借鉴工业流水线制造的思想,现在CPU也采用了流水线设计,这有助于提高CPU的频率。Intel首次在486芯片中使用流水线设计,它是指在程序执行时多条指令重叠进行操作的一种准并行处理实现技术。在CPU中由5~6个不同功能的电路单元组成一条指令处理流水线,然后将一条指令分成5~6步后再由这些电路单元分别执行,这样就能在一个CPU时钟周期内完成一条指令,从而提高CPU的运算速度。在经典的奔腾处理器中,每条整数流水线都被分为四级流水(即取指令、指令译码、取操作数、执行),浮点流水又被分为八级流水。奔腾流水线技术示意图如图1-5所示。
图1-5 奔腾流水线技术示意图
2.空间上的并行:多处理器/多核技术
多处理器/多核技术是指通过网络将两个以上的处理机连接起来,让多个处理机并行地执行计算,以实现同时计算同一个任务的不同部分,或者解决单个处理机无法解决的大型问题。
假如你拥有一个苹果庄园,秋天苹果大丰收,让一个工人从每棵树上摘取所有的苹果需要4天。你觉得太慢,那么你可以多雇点人,安排每个工人摘不同的苹果树,一天就可以摘完所有的苹果,如图1-6所示。这就是并行算法中的空间并行,将一个大任务分割成多个相同的子任务,以加快速度解决问题。
图1-6 空间上的并行示意图
费林(Michael J.Flynn)于1972年提出了计算平台的费林分类法(Flynn’s Taxonomy),其主要根据指令流和数据流将计算平台分为四类,如图1-7所示。图中的PU是Processing Unit的缩写。
图1-7 计算平台的费林分类法
(1)单指令单数据(SISD)机器。SISD机器是一种传统的串行计算机,它的硬件不支持任何形式的并行计算,所有的指令都是串行执行,并且,在某个时钟周期内,CPU只能处理一个数据流。早期的计算机都是SISD机器,如早期的巨型机和许多8位的家用机等。
(2)单指令多数据(SIMD)机器。SIMD是指采用一个指令流处理多个数据流,它在数字信号处理、图像处理、多媒体信息处理等领域非常有效。Intel处理器实现的MMXTM、SSE、SSE2及SSE3扩展指令集,都能在单个时钟周期内处理多个数据单元。也就是说,我们现在用的单核计算机基本上都是SIMD机器。
(3)多指令单数据(MISD)机器。MISD是指采用多个指令流来处理单个数据流。由于在实际情况中采用多指令流来处理多数据流才是更有效的方法,因此,MISD只是作为理论模型出现,实际应用很少。一般认为,脉动阵列是MISD的实例,例如谷歌的TPU系列深度学习加速器。
(4)多指令多数据(MIMD)机器。MIMD机器可以同时执行多个指令流,这些指令流分别对不同的数据流进行操作。最新的多核计算平台就属于MIMD机器的范畴,例如,Intel和AMD的双核处理器等都是MIMD机器。它是最为通用的体系结构,各个处理程序既可以执行同一程序,也可以执行不同的程序。虽然MIMD机器的通用性高,但设计复杂,故MIMD机器的性能较低。
计算机并行体系结构最基本的形式是单核内指令级并行,即处理器在同一时刻可以执行多条指令。流水线技术是实现指令级并行的使能技术,采用流水线技术设计的指令级并行微处理器内核已经成为设计典范。在这个基础上可以实现多线程和多核并行,即一个芯片上集成多个处理单元或处理核心,以同时完成多个任务。再上一个层次的并行是计算机并行,即多个芯片通过专用的网络连接在一起实现更大规模的并行。更高层次的并行是仓储级计算器,即借助互联网技术将数以万计的处理器和计算节点连接在一起,每个节点是一个独立的计算机。仓储级计算器具备前面描述的多种层面的并行。指令级和数据级并行适合在内核完成,因为它所需要的寄存器传输级(RTL)通信和协作在核内可以以极低的延迟完成。现代处理器中的每个核心都会综合运用流水化、超标量、超长指令、分支预测、乱序执行等技术充分挖掘指令级并行的潜能。相对来说,MIMD的并行层次更高,会更多地利用多个处理单元、多个处理核心、多个处理器或更多节点来实现。
目前,主流计算机中的处理器主要是CPU和GPU。CPU和GPU属于不同架构的处理器,它们的设计理念是不同的。
● CPU的设计理念:注重通用性以处理各种不同类型的数据,同时支持复杂的控制指令,例如条件指令、分支、循环、逻辑判断及子程序调用等。因此,CPU微架构的复杂性高,它是面向指令执行的高效率而设计的。
● GPU的设计理念:GPU最初是针对图形处理领域的,图形运算的特点是大量同类型数据的密集运算。
CPU和GPU的架构对比如图1-8所示,图的左边为CPU架构,右边为GPU架构。对处理器芯片架构设计来说,有两个指标是经常要考虑的:延迟和吞吐量。延迟是指从发出指令到最终返回结果中间所经历的时间间隔。吞吐量是指单位之间内处理的指令的条数。
图1-8 CPU和GPU架构对比
从图1-8可以看到,CPU的架构特点表现在以下几个方面。
首先,CPU采用了多级高速缓存结构。由于处理运算的速度远远高于访问存储的速度,为了提高指令访问存储的速度,CPU设计了多级高速缓存结构。它将经常访问的内容放在低级缓存中,不经常访问的内容放在高级缓存中,从而实现了空间换时间的设计思想。
其次,CPU包含了许多控制单元。具体来说,它有两种控制单元:分支预测机制和流水线前传机制控制单元。这些控制单元使得CPU在运算过程中能够高效地进行指令控制。
最后,CPU的运算单元(Core)非常强大,它能够快速进行整型、浮点型复杂运算。这使得CPU在处理大量复杂运算时能够保持高效和稳定。
与CPU不同,GPU的架构特点表现在以下几个方面。
首先,GPU虽然也有缓存结构,但其数量较少,GPU缓存所占的芯片面积较小。这意味着支持指令访问缓存的次数会比较少,从而影响了GPU在存储访问方面的效率。
其次,GPU的控制单元相对简单,没有分支预测机制和数据转发机制,GPU控制单元所占的芯片面积较小。这使得GPU在处理复杂指令时速度较慢,但这也降低了它的功耗和复杂度。
最后,GPU的运算单元非常多,其采用长延时流水线以实现高吞吐量。每行的运算单元共用一个控制器,这意味着每行的运算单元执行的指令是相同的,只是数据内容不同。这种整齐划一的运算方式使得GPU在处理控制简单但运算量大的任务时效率显著提高。
CPU和GPU在基本架构层面上的差异导致了它们在计算性能方面的巨大差异。CPU拥有庞大而广泛的指令集,能够与更多的计算机组件(如内存、输入和输出)交互,以执行复杂的指令。相比之下,GPU是一种专门的协处理器,在高数据吞吐量的任务上表现出色,但在其他任务上的表现则不如CPU。
CPU更强调低延迟的指定运行,其处理方式主要是串行。如果需要处理多任务并发需求,CPU只能通过任务切换来实现,这需要重置寄存器和状态变量、刷新缓存等。然而,经过延迟优化,CPU在多个任务之间的切换速度非常快,让人感觉它是在并行处理任务,但实际上它仍然是一次运行一项任务。因此,CPU像一个学识渊博的专家,它可以迅速处理各种不同难度的任务,但在面对大量的重复性劳动时也会感到困扰。
为了提高CPU的性能,人们可以通过不断提高主频来提高它的运行速度,常见的CPU主频为2~4GHz。相比之下,GPU更强调高数据吞吐量,其核心主频通常为1GHz左右。除了提高主频和改进架构,增加专门用于并行计算的加速处理器(Accelerated Processor,AP)的数量也是提高GPU处理速度的一种常见方法。CPU和GPU能力差异示意图如图1-9所示,CPU像一个大学里的数学系教授,而GPU更像一群中学生,可以同时处理大量的简单运算,但面对复杂任务则会感到困难。
图1-9 CPU和GPU能力差异示意图
GPU适合重复性和高度并行的计算任务,其最常规也是最初的应用便是图形渲染和显示。后来,人们发现GPU对多组数据执行并行操作的能力也非常适合某些非图形任务,例如机器学习、金融模拟、科学计算等大规模且反复运行相同数学函数的活动。概括起来,适合GPU解决的问题有以下主要特点。
● 计算密集(任务并行):数值计算的比例要远大于内存操作,因此,内存访问的延时可以被计算掩盖。
● 数据并行:大任务可以被拆解为执行相同指令的小任务,因此,对复杂流程控制的需求较低。
随着GPU的发展,GPU异构编程应运而生。由于GPU保留了许多流式处理器的特征,受到早期异构并行编程模型(如2004年出现的BrookGPU)的影响,GPU异构编程采用了流式编程的思想。在GPU异构编程模型中,流(Stream)是核心,它是一组数据的集合,计算在每个数据元素上并行执行,符合单指令多数据(SIMD)或多指令多数据(MIMD)的执行模式。然而,SIMD或MIMD要求流中每个数据元素的操作在控制流上完全相同,这虽然适合多数流媒体应用的特点,但对更广泛的数据并行应用来说过于苛刻。在这种背景下,随着NVIDIA GPU在商业上的巨大成功,2007年出现的CUDA得到了大力推广。它以单程序多数据(SPMD)的形式表达数据并行性,允许同一段操作在不同数据上采取不同的控制流路径。但CUDA只能在以NVIDIA GPU为加速设备的异构系统中使用。于是,在2008年底,多家公司共同制定了跨平台异构并行编程框架标准OpenCL,其适用于任何并行系统。OpenCL将实际的硬件平台抽象为一个统一的平台模型,这也是OpenCL与CUDA最大的不同之处。
(1)CUDA编程。CUDA编程是NVIDIA建立在CPU+GPUs上的通用并行计算平台和异构编程模型。基于CUDA编程,可以利用NVIDIA GPUs的并行计算引擎来更加高效地解决比较复杂的计算难题,其已被广泛应用于深度学习领域,基于GPU的并行计算已经成为训练深度学习模型的标配。
(2)OpenCL编程。OpenCL编程是为异构平台编写程序的框架,此异构平台可由CPU、GPU或其他类型的处理器组成。OpenCL编程由一门用于编写核函数(Kernel,在OpenCL设备上运行的函数)的语言(基于C99)和一组用于定义并控制平台的API组成。OpenCL编程提供了基于任务分割和数据分割的并行计算机制。OpenCL编程类似于另外两个开放的工业标准OpenGL和OpenAL,这两个标准分别用于三维图形和计算机音频方面。OpenCL编程扩展了GPU用于图形生成之外的能力。
(3)MXMACA编程。MXMACA编程是沐曦为沐曦GPU和通用CPU这种异构平台推出的异构编程模型,其不仅继承了CUDA编程和OpenCL编程的优点,而且能结合最新的技术和产品推陈出新。本书正是为普及MXMACA编程而努力的开篇之作。