在上一期中,我们详细讲解了ARM Mali GPU架构的发展历程,以及新的Midgard架构的设计方向、架构概览、无固定硬件单元的曲面细分功能设计等内容。而在本期中,我们将继续带你深入ARM Midgard架构的内部,去进一步地探索这个非常重要的移动GPU架构的方方面面。
目前的SoC产品受到诸如电源、芯片尺寸、内存带宽等诸多规格参数的影响,但是毫无疑问,内存带宽比任何参数都更能直接的影响到产品的性能。为了进一步优化内存带宽使用并提高效率,Midgard提出了一种名为Hierarchical Tiling system(层级区块体系)的算法,顾名思义—这种算法来自于将Midgard所要渲染的目标根据层级进一步的分块,终使得每个区块达到了所需要的、能够直接在GPU内部处理的尺寸,这样可以进一步节约资源。
所谓“区块”,是目前绝大部分移动GPU采用的一种数据处理和渲染方式,Midgard自然也不例外。简单来说,传统的GPU在数据处理时,会使用一整张大贴图对画面进行计算。但这样做贴图受制于体积,必须存放在内存中,这样一来频繁的GPU和内存间的数据交换会很快耗尽极为有限的带宽资源。因此,Mali以及高通的Adreno、IT的PowerVR等厂商都采用了Tile(区块)的贴图方式。这种方式是将整个场景先划分为一个个小小的区块(一般是16×16尺寸),由于区块很小因此可以直接放在GPU的缓存中,然后GPU再对这个区块进行处理,这样一来就极大的避免了数据传输对系统总线带来的巨大压力,同时也节约了资源。
除了有关Tile技术外,Midgard还在加强工作效率、降低无谓的性能消耗上做出了很多努力。Midgard在内核架构中添加了两个Z轴检查模块,分别为前置Z轴检查和后置Z轴检查。早期Z轴模块被放置在每个着色器核心中,它用于检测是否存在一些多边形被覆盖或者不可见但进入了渲染管线,前置Z轴模块会将其剔除。当然这还是不够的,在Mail-T620以后的Midgard架构GPU上,又加入了一个名为“前置像素剔除(Forward Pixel Kill)”的模块,用于进一步检查一些无用的、被遮挡的像素,大效率地节省带宽和资源。
再来看看Midgard的功耗优化方面。Midgard采用了一些新技术来优化功耗。比如加入了大量的门控时钟和细粒度的电源门控来优化整个GPU的电能使用。而在GPU空闲时,Midgard允许GPU空闲部分(甚至可以是部分核心)休眠或者关闭;每个着色器单元都拥有自己的电源控制模块,着色器本身的频率根据需要降低以同时控制功耗。此外,Midgard还拥有一些比较常见的频率调节技术,比如拥有动态频率,可以在不同的状态下自动调节频率以节约能量。总之,Midgard的能耗控制是比较出色的。
双精度和异构计算—Midgard为未来计划
接下来,我们来谈谈有关Midgard在计算能力和内存访问上的一些问题。ARM一直以来都是以设计高性能功耗比的CPU模块为主的,尤其是目前非常火爆的ARM 64架构。在CPU上,ARM的目标是全面扩展到64位计算架构,而在GPU上ARM也这样做了。目前Midgard完全支持64位计算,包括64位整数计算、双精度计算(FP64)使用、使用64位内存地址等。
一般来说,在一款移动SoC GPU上实现64位计算的意义并不大,尤其是FP64,但ARM考虑的显然并非只是计算精度。Midgard可以调用64位存储器地址,和ARMv8系列CPU使用相同的64位地址空间—这样一来意义就变得非同凡响了。这种能力使得Midgard和ARMv8架构的CPU在I/O上实现一定的一致性,比如Midgard直接去读取CPU的缓存。虽然Midgard和ARMv8 CPU之间不一定存在缓存一致性,但是这个功能主要是用于让GPU更有效率的访问CPU的缓存,数据在CPU和GPU之间的传递可以更为直接、高效。当然,完整的缓存一致性显然也是ARM的目标之一。
作为一款移动SoC GPU,Midgard在电能控制上主要使用了功耗门控和频率门控两种技术。
ARM一直都非常关心有关异构计算的内容。因此,Midgard加入了64位寻址和I/O的一致性功能后,ARM可以在有关GPU和CPU的异构计算方面更为有效率—别忘了ARM一直都是HAS异构计算联盟的一员。虽然目前看起来ARM依旧处于单一的CPU或者GPU计算的阶段,但是路要一步一步走,ARM为了节约电能、提高计算效率,在异构计算上做出的努力应该会有成果展示的。
我们在比较宏观的角度描述了Midgard的架构内容。接下来的部分,需要继续深入Midgard GPU的心脏部分,它的核心单元设计。一般来说,判断GPU设计是否优秀并非只是一些漂亮的参数,而是它的核心单元方案。
Midgard的核心单元设计采用了VLIW超长指令集方案,拥有SIMD单指令多数据流特性。这样的设计需要ARM在指令层面有非常强的指令调配能力。在下图中,展示了一个Midgard的核心算术单元,图中以FP32操作为例。在一个算术管线中,Midgard混合了标量和矢量ALU,每个部分含有3个矢量ALU和2个标量ALU,每种都会负责一个特定类型的操作。