[Hardware翻译]剖析苹果M1 GPU,第一部分。

1,100 阅读6分钟

原文地址:rosenzweig.io/blog/asahi-…

原文作者:rosenzweig.io/

发布时间:2021年1月7日

苹果最新的Mac系列包含了他们自家的 "M1 "系统芯片,采用了定制的GPU。这给我们这些希望在设备上运行Linux的Asahi Linux项目的人带来了一个问题,因为这个定制的苹果GPU既没有公开的文档,也没有开源的驱动。有些人猜测它可能是PowerVR GPU的后裔,就像老款iPhone中使用的那样,而另一些人则认为这个GPU是完全定制的。但是,当我们可以亲自窥探引擎盖下的情况时,传言和猜测就没意思了!

几周前,我购买了一台搭载M1 GPU的Mac Mini作为开发目标,研究指令集和指令流,在之前没有公开了解的层面上了解GPU的架构,并最终加速开发该硬件的Mesa驱动。今天,我已经达到了第一个里程碑。我现在已经理解了足够的指令集 来分解简单的着色器 用GitHub上发布的免费开源工具链来分解

解码GPU的指令集和命令流的过程与我在Panfrost项目中对Mali GPU进行逆向工程的过程平行,该项目最初由Lima、Freedreno和Nouveau自由软件驱动项目开创。通常情况下,对于Linux或Android驱动逆向工程,会编写一个小的封装库,通过LD_PRELOAD注入到测试应用程序中,该库会钩住关键的系统调用,如ioctl和mmap,以便分析用户与内核的交互。一旦发出 "提交命令缓冲区 "的调用,该库就可以转储所有(映射的)共享内存进行离线分析。

同样的整体过程将适用于M1,但有一些macOS主义需要翻译。首先,macOS上没有LD_PRELOAD,对应的是DYLD_INSERT_LIBRARIES,它有一些额外的安全功能,对于我们的目的来说,很容易关闭。其次,虽然macOS上确实存在标准的Linux/BSD系统调用,但它们并不是用于图形驱动程序的。相反,苹果自己的IOKit框架被用于内核和用户空间的驱动程序,关键的切入点是IOConnectCallMethod,是ioctl的模拟。这些差异很容易纸上谈兵,但确实与标准的Linux工具增加了一层距离。

更大的问题是在IOKit世界中定位。由于Linux采用的是copyleft授权,(合法的)内核驱动是开源的,所以ioctl接口是公开的,尽管是厂商特定的。MacOS的内核(XNU)采用的是允许性授权,并没有带来这样的义务;内核接口是专有的,没有文档的。即使在封装了IOConnectCallMethod之后,也需要花费一些精力来确定三个关键的调用:内存分配、命令缓冲区创建和命令缓冲区提交。封装分配和创建调用对于跟踪GPU可见内存(我们有兴趣研究的内容)是必不可少的,而封装提交调用对于内存转储的计时是必不可少的。

扫清了这些障碍,我们终于可以进入shader二进制,本身就是黑盒子。然而,从这里开始的过程是标准的:从尽可能简单的片段或计算着色器开始,对输入的源代码做一个小小的改动,然后比较输出的二进制文件。这个过程的迭代是很乏味的,但会很快揭示出关键结构,包括操作码号。

自由软件拆解器中记录的过程的发现证实了GPU的一些特征。

其一,架构是标量的。与一些GPU对32位是标量的,但对16位是矢量的不同,M1的GPU在所有位数上都是标量的。然而Metal优化资源意味着16位算力应该会有明显的速度,此外还减少了寄存器的使用量,导致线程数(占用率)提高。这表明硬件是超标量的,16位ALU比32位ALU更多,使得该部分比竞争芯片更能从低精度图形着色器中获益,同时消除了编译器的大量复杂性。

二是该架构似乎可以在硬件中处理调度,这在桌面GPU中很常见,但在嵌入式领域就不那么常见了。这又以牺牲更多硬件为代价使编译器变得更简单。指令似乎有最小的编码开销,不像其他架构需要用nop来垫出指令,以适应高约束的指令集。

三、支持各种修改器。浮点ALU可以 "免费 "做clamps(饱和)、负值和绝对值修饰,这是一个常见的shader架构特点。此外,大多数(所有?)指令可以在目标和源上 "免费 "进行16位和32位之间的类型转换,这使得编译器可以更积极地使用16位操作,而不会有转换开销的风险。在整数方面,允许在某些指令上免费进行各种位补和移位。这些都不是苹果设计的独特之处,但同样值得注意。

最后,并不是所有ALU指令的时序都一样。像imad这样用来乘以两个整数并加上第三个整数的指令,要尽可能避免使用重复的iadd整数加法指令。这也表明了一种超标量架构;像我日常工作中的软件调度设计无法利用流水线长度的差异,无意中降低了简单指令的速度,以匹配复杂指令的速度。

根据我之前在GPU上的工作经验,我期望能在指令集中发现一些可怕的东西在等待,以膨胀编译器的复杂性。虽然上述工作目前只覆盖了指令集的一小块表面区域,但到目前为止,一切似乎都很健全。没有任何令人费解的优化技巧,但做掉了这些技巧,创造了一个精简、高效的设计,只做一件事,而且做得很好。也许苹果的硬件工程师们发现,简单是很难被打败的。

唉,如果没有一个开源的用户空间驱动,着色器工具链也没什么用。下一篇:剖析命令流!

免责声明:本作品是基于公开信息进行的业余项目。所表达的观点可能不反映我的雇主的观点。


通过www.DeepL.com/Translator(免费版)翻译