12.2. 使用向量指令

对于计算密集型程序,向量指令往往能带来明显加速。以图像处理为例,常见图像数据格式 YUV 中,Y 表示亮度(灰阶值),U 和 V 表示色度,用于描述色调和饱和度;这类数据元素通常占8位。若要对大量此类数据执行加法操作,使用通用基础指令时,需要先用两条 load 指令分别读取两个8位操作数,再用 add 指令求和,最后通过 store 指令写回结果。对应指令如下:

ld.b   t1, addr1
ld.b   t2, addr2
add.w  t3, t1, t2
st.b   t3, addr3

通用寄存器虽然宽度为32位或64位,但这里实际只使用低8位。因此,执行4条指令只能完成1组数据加法。

若改用向量指令,例如采用龙芯高级向量扩展,其向量位宽为256位。同样执行4条指令,就可以一次处理32组8位数据,计算效率会显著提高。示例如下:

xvld     x1, addr1
xvld     x2, addr2
xvadd.b  x3, x1, x2
xvst     x3, addr3

向量指令也有使用成本。由于向量寄存器复用浮点寄存器,某些场景下可能触发浮点模式切换,进而产生额外开销。因此,编写程序时应尽量避免在同一个函数中混用向量指令和浮点指令,并优先把向量化用于热点函数或循环计算体。热点函数或热点循环,是指程序运行过程中被频繁执行,或耗时占比较高的代码区域。

受篇幅限制,本书不逐条介绍 LoongArch 向量指令。进行向量优化时,可查阅龙芯架构参考手册中关于向量指令集的章节。