【小白设计AI芯片】定义指令集

前面陆续讨论了 定义一套AI Core指令集所需要思考的一些问题,比如

飞行小象:【小白设计AI芯片】定义指令集(一)中提到:

了解神经网络的计算需求

异构计算系统中Host与Device的任务划分

指令集的粒度(与神经网络算子的对应关系)

飞行小象:【小白设计AI芯片】定义指令集(二)中提到:

指令集应该包含的指令类型

指令集面向数据对象的特性

本篇是指令集主题的最后一篇,我们一鼓作气把事情说完~

在第一篇开头语中我们提到过,指令集是软硬件任务划分的界面,是硬件功能的接口说明。为了让上层开发人员了解处理器,并且在合理范围内正确的使用处理器,一个真实可用的AI指令集都应包括哪些内容呢?

指令格式

指令格式包括指令字长和指令位域划分两方面。

指令字长

在进行位域划分之前,首先要明确指令位宽(或字长)要定义多少。我们知道CPU指令集有定长(所有指令字长一致)和不定长(不同类别指令字长不一致)的说法。前者常见于RISC指令,比如ARM与Risc-v典型指令位宽都是32bit;后者常见于CISC指令,比如x86指令位宽有32bit、64bit、128bit等几种。

AI Core不像CPU有明显的RISC和CISC之分,不过确有定长与不定长指令的选择。由于AI指令需要描述不同维度的标量、向量、矩阵数据,各自占用的有效指令位宽会有差别,一种不同指令位宽方案的对比见下图。

指令字长方案选择

一般来讲,图中三种方案有如下区别:

不定长方案确保指令字长“各尽其用”的同时,也可以保证用最少的指令实现程序,但会增大处理器前段(取指/译码)的实现难度。

定长方案一,对于标量操作有所"浪费",对于矩阵操作则需要多条指令组合完成,是一种简化硬件设计较好的折中。

定长方案二,则在简化硬件、减少程序指令条数的同时,造成较低的指令字长利用率。

综合几个因素,我个人比较喜好定长方案一的思路。

指令位域

指令位域的含义是指令字内部,占据具体的bit区间的指令参数。比如第一篇Conv指令的ci,co, addr, data_type等都属于Conv的指令位域。

指令位域划分的原则一般包括:

规整统一:不同指令的相同(或相似)含义的参量,划分到相同(或靠近)的bit位置;所谓“简单源于规整”。

位宽适量:各功能参数的位宽不宜过长以免浪费,也不应太短导致表示范围不够,要考虑实际应用场景和硬件开销,并为后续功能扩展留有一定余量。

含义明确:每个位域对应的指令参数要有明确含义,换句话说同一参量尽量不做拆分,不同含义的参量尽量不要合并,以便于理解。

编码规范:有的指令位域需要编码,以表示不同内容,编码的顺序及内容的逻辑顺序要尽量一致、符合直觉。

简单规整的risc-v指令集指令约束

定义完指令格式及具体位域排布之后,需要说明指令的使用限制,即指令约束。指令约束来源于有限的芯片资源,所以指令必有约束。简单来说主要就是指令位域的取值范围或使能条件。

指令位域宽度是天然的指令约束,即对应指令参数的取值不能越界,有时指令位域的取值范围比位宽表示范围更小,则需要特别说明。

稍微复杂一点的约束,来自于多个指令位域的组合使用限制。比如Conv指令若不支持pad_size(一边的大小)大于kernel_size(kw/kh),则需要把二者需满足的大小关系说明清楚。

有些指令位域在某些特定模式下才有意义或使能,则需要把使能条件描述清楚,并且说明不使能时允许的取值以及硬件对应的处理方式。

指令异常

指令异常与指令约束相关,主要描述当不满足指令约束的情况出现时,芯片何时会上报错误状态,为硬件异常(与软件异常相对)。它们之间的关系可参考下图。

指令约束与指令异常

实际情况下,不满足指令约束时,只有部分关键场景才会触发指令异常,过于细致全面的异常检测和上报逻辑会显著增大AI Core的硬件开销。指令异常是硬件异常的一部分,硬件异常与软件异常互为补充,共同处理芯片的异常情况。一般建议硬件只上报核心错误或软件无法监测的错误场景,用于后期辅助软件调试、监测硬件行为。

指令兼容性

前面有讲到过,AI Core的指令集与CPU、GPU指令集一样,其功能会随着应用和版本迭代而发生变化。成熟的商业AI处理器需满足向后兼容性(Backward Compatibility),即老版本的神经网络模型也可以在新版AI Core上实现推理部署。指令的兼容性则是指,对软件层面保持指令功能、指令约束的不变性,即AI Core的变化都在微架构层面,软件不可见。

不过处理器的兼容性也分成硬件层面兼容和软件层面兼容,如果某一版本AI Core指令集发生了较大变化,但编译层面可以将硬件指令的变化给隐藏住,向上层软件提供一个不变的指令接口,一般也是可以接受的。此时就需要在指令集中对兼容性的变化描述清楚。

Two More Things寄存器文件说明

完整的指令集功能描述,还包括寄存器空间划分及相关说明,这里的寄存器指的是程序可见的寄存器。AI Core由于其描述数据的高维度及部分指令的复杂性,往往需要比cpu更多的寄存器,一般分成类似于cpu的通用功能寄存器(GPR)和指令特殊功能寄存器(SPR),有的向量功能单元还有向量寄存器(比如arm sve)和控制状态寄存器(比如risc-v),这些寄存器说明作为指令功能的补充说明,向软件提供了完整的指令应用指南。

硬件融合指令

这一点可以算是AI Core或者DSA特有的指令特点。简单而言就是多个操作融合到一条硬件指令中,使一条指令可以完成多个神经网络中的操作。常见的就是Conv+ 偏置(Bias)求和 + 激活(Activation)的融合,通过将Conv指令增加更多的功能位域,使得一条新的Conv指令能完成这几个操作的完整计算过程。因此融合指令会更复杂,指令位宽要求也会更宽。

conv融合指令对应计算过程

需要说明的一点是,融合指令往往对应芯片中的专用流水线,只有当融合操作在神经网络中非常常见时,付出的硬件开销才有收益,此时由于融合操作的中间计算结果不需要与内存交互,从而减少了计算延时和功耗。如果硬件实现的融合操作并不主流,只在极少情况下会出现,那硬件逻辑利用率就会降低。

不过操作融合是AI加速的常用手段,融合指令是硬件融合,软件层面也会经常做算子融合。

结束语

AI core虽然没有高性能cpu那么复杂,但同一般体系结构一样(不包括非冯架构AI芯片),指令集是架构中最重要的一环。指令集定义过程中的每一个决定,都与上层软件应用和底层芯片微架构息息相关,因此需要多角度全盘考虑。不过也正是因为指令集与架构“休戚与共”,ISA的学习和定义过程才会如此迷人。希望小伙伴们能从这个主题的文章中有所收获,鉴于本人学识有限,文中论述难免有误,大家辩证看待,多多指教哈。

本文完

免责声明:本文章如果文章侵权,请联系我们处理,本站仅提供信息存储空间服务如因作品内容、版权和其他问题请于本站联系