x86准备好迎接ACE了吗?
CPU设计必须随着工作负载的变化而演变。有时,这种演变涉及扩展指令集,以有效表示某些类型的工作。英特尔的AMX扩展就是一个这样的例子。AMX通过提供一组2D平铺寄存器和配置寄存器来加速机器学习工作负载中的矩阵乘法。程序员可以配置专门的执行单元(“加速器”)以针对那些平铺寄存器中的矩阵数据。AMX首次在英特尔的Sapphire Rapids服务器CPU上实现,配备了平铺矩阵乘法单元(TMUL)加速器。现在,x86生态系统咨询小组编写了一份有关ACE的白皮书和规范,引入了第二种加速器类型。虽然ACE是与TMUL并行的AMX加速器,但我将称之为“AMX”和“ACE”,因为TMUL是AMX推出时存在的唯一加速器实现,并且至今仍是硬件中唯一可用的AMX加速器。文档也通常称其为“AMX”和“ACE”。AMX TMUL提供了高度可配置的设置,其中代码会为每个平铺寄存器指定矩阵平铺参数。例如,平铺寄存器tmm0可以通过指定16行和每行64字节(“colsb”)来设置为一个16x64的INT8值矩阵。TMUL矩阵乘法指令,如TDPBSSD,将考虑平铺配置,并在指定平铺之间执行整个矩阵乘法操作。在数据类型方面,AMX TMUL能够操作INT8、FP16和BF16值。TMUL的最新版本在Granite Rapids-D CPU上实现,也支持具有FP16实部和FP16虚部的复数。ACE取消了平铺寄存器配置选项,始终将其视为16行64字节。复数被移除,但FP8被纳入。在计算端,ACE提供外积指令,而不是AMX提供的内积指令。Arm的可扩展矩阵扩展(SME)及其SME2扩展是一个显然的比较点。这两个ISA扩展都寻求在CPU ISA的框架内加速矩阵乘法,提供一种低延迟的替代方案,以使用如GPU等较少集成的加速器。然而,这两个ISA扩展在许多方面有所不同。ACE建立在AMX之上,继续使用AMX的8KB平铺寄存器来保存矩阵值。相比之下,Arm的SME具有可变的“流式”向量长度(SVL),就像SVE的向量长度(VL)一样。SVE和SME的向量长度不必相同,且通常不相同。像SVE一样,SME允许向量长度从128到2048位,以二的幂增长。流式向量长度定义了“ZA”存储阵列的大小,这是SME等同于AMX平铺寄存器的存储区。ZA存储是一个二维数组,每一侧与SME流式向量长度相匹配。因此,ZA存储的容量从128位流式向量长度的256字节到最大2048位向量长度的64 KB不等。而AVX512-VNNI和AMX加速内积,ACE和SME加速外积。两个向量a和b的内积(或在这个特殊情况下的点积)是,\(oldsymbol a ullet oldsymbol b = oldsymbol a^ ext{T} oldsymbol b = extstyle igsum_{i=1}^n a_i b_i\) 或者如果你是物理学家,你可能通过几何解释学到了它,\(oldsymbol a ullet oldsymbol b = |oldsymbol a| imes |oldsymbol b| imes ext{cos} heta\),其中θ是两个向量之间的角度。另一方面,向量a和b的外积(或在一般情况下的张量积)会产生这样的秩-1矩阵C。\(oldsymbol{a} igotimes oldsymbol{b} = oldsymbol a oldsymbol b^ ext{T} = oldsymbol C = egin{bmatrix} a_1b_1 & a_1b_2 & ext{...} & a_1b_n \ a_2b_1 & a_2b_2 & ext{...} & a_2b_n \ ext{...} & ext{...} & ext{...} & ext{...} \ a_mb_1 & a_mb_2 & ext{...} & a_mb_n \\ ext{...} \ ext{.} \ ext{.} \ ext{.} \ ext{.} \ ext{.} \ ext{.} \ ext{.} \ ext{.} \ ext{...} ext{...} \ ext{...} ext{...} \ ext{.} ext{.} & ext{.} ext{.} & ext{.} ext{.} & ext{.} ext{.} & ext{...} \ ext{...} ext{.} \ ext{.} ext{...} ext{.} ext{.} \ ext{...} ext{...} \ ext{...} ext{.}} \ ext{.} \ ext{.} \ ext{.} ext{.} \ ext{}} \ ext{...} \ ext{...} \ ext{...} \ \} \ \text{每一列都是与a成比例的,这就是我们知道它是一个秩-1矩阵的原因,而矩阵乘法只不过是外积的总和,如,\(oldsymbol C = oldsymbol AB = extstyle igsum_{i=1}^n oldsymbol a_i^{ ext{行}} oldsymbol b_i^{ ext{列}}\)。实际上,线性代数中的许多操作可以被视为外积的线性组合,从而使外积成为实现在处理器中自然的基本操作,最明显的例子是矩阵的奇异值分解,\(oldsymbol M = oldsymbol{U oldsymbol ext{Σ} oldsymbol V}^ ext{T}\)。当以内积形式书写时,它并不是很简单理解,但它仅仅是U和V列的外积的总和乘以每个对应的奇异值,即,\( extstyle igsum_{i=1}^{ ext{rank}(A)} (oldsymbol u_i igotimes oldsymbol v_i) ext{σ}_i\)。甚至一些不那么明显的算法也可以用外积形式进行转换,例如FFT,Arm给出了如何做到这一点的示例,但如果你搜索一下论文,你可以发现各种更有效的方法。我们历史上主要使用内积,因为这减少了计算量。
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡