【ARMv8/ARMv9 硬件加速系列 3 -- SVE 硬件加速向量运算 1】

文章目录

    • [SVE 使用介绍](#SVE 使用介绍)
      • [SVE 特点](#SVE 特点)
      • [SVE2 特点](#SVE2 特点)
    • [SVE 寄存器](#SVE 寄存器)
      • 扩展的向量寄存器
      • 可扩展的谓词寄存器
        • [.d 与 .b 后缀的区别](#.d 与 .b 后缀的区别)
        • 举例介绍
          • [使用 .d 后缀进行64位元素操作](#使用 .d 后缀进行64位元素操作)
          • [使用 .b 后缀进行8位元素操作](#使用 .b 后缀进行8位元素操作)
        • [ptrue 指令](#ptrue 指令)
      • [FFR 寄存器](#FFR 寄存器)

SVE 使用介绍

前面文章:【ARMv8/ARMv9 硬件加速系列 1 -- SVE | NEON | SIMD | VFP | MVE | MPE 基础介绍】 已经对 SVE 做了个大概得介绍,接下来我们就会逐渐深入研究SVE的使用。这里我们再回顾下 ARM 的 SVE :

ARMv9架构中的SVE(Scalable Vector Extension)和SVE2(Scalable Vector Extension 2)是为了增强处理器在处理高性能计算、机器学习、人工智能等领域的性能而设计的关键技术。它们提供了一种可伸缩的向量处理能力,允许更高效地对大量数据进行并行处理。

SVE 特点

SVE是在ARMv8-A架构中首次引入的一种向量扩展,旨在提供一种比传统SIMD(如ARM自己的NEON技术)更灵活的方式来处理向量计算。SVE的关键特性包括:

  • 可伸缩的向量长度 :SVE支持从128 位到2048位的可伸缩向量长度,向量长度可以根据目标处理器的具体实现而变化。这种可伸缩性允许SVE代码在不同的ARM处理器上运行,而不需要为每个处理器重写代码。
  • 谓词执行:通过谓词寄存器,SVE支持掩码执行,允许对向量中的每个元素独立地进行条件执行。这提高了代码的灵活性和效率。
  • 向量化循环:SVE专门优化了向量化循环的执行,使得循环能够更高效地利用向量化指令。

SVE2 特点

SVE2是SVE的扩展,随ARMv8.2-A及后续版本提供,进一步增强了SVE的能力,特别是针对复杂的数据处理模式。SVE2的新增特性包括:

  • 增强的整数和浮点运算:SVE2引入了更多的整数和浮点向量指令,支持更广泛的数据处理需求。
  • 复杂的数据重排操作:SVE2提供了丰富的数据重排(permutation)和交错(interleaving)操作,这对于实现复杂的算法(如加密算法)非常有用。
  • 增强的字符和字符串处理:为了支持更高效的文本和数据处理,SVE2加入了针对字符和字符串操作的指令。
  • 兼容性:SVE2设计为与SVE向后兼容,意味着能够执行SVE指令的处理器同样能够执行SVE2指令。

在高性能计算和人工智能领域,可以利用SVE和SVE2的强大能力来加速计算密集型任务。例如,使用SVE/SVE2进行矩阵乘法运算可以大幅提升深度学习模型训练和推理的速度。通过利用可伸缩的向量长度和谓词执行,开发者可以编写出既高效又灵活的代码,适配不同的硬件实现,以最大化性能和资源利用率。

总之,SVE和SVE2通过提供可伸缩的向量长度和一系列高级向量处理指令,大大增强了ARM架构在高性能计算、机器学习和人工智能应用中的竞争力。

SVE 寄存器

SVE寄存器有4种:

  • 32个可扩展的向量寄存器,Z0-Z31;
  • 16个可扩展的谓词寄存器,P0-P15;
  • 一个First Fault 谓词寄存器(FFR);
  • 可扩展的向量系统控制寄存器ZCR_Elx

扩展的向量寄存器

SVE共有32 个可变长矢量寄存器Z0-Z31(128 位的整数倍, 最高可达2048 位) ,其中Z0-Z31的低128[127:0],与AArch64 SIMD&FP寄存器V0-V31共享硬件资源。假设SVE的矢量长度为256,其矢量寄存器 视图如下:

  • 可以支持64bits,32bits,16bits 和 8 bits 的元素;

  • 支持整型以及双精度,单精度和半精度浮点元素;

  • 可配置每个异常级别 (EL) 的向量长度。

  • .d后缀 :表示操作的数据类型为双字(64位)。当你使用.d后缀(如p0.d)时,这表示谓词寄存器中的每一位控制向量寄存器中对应的64位数据元素。通常用于精细控制对64位数据元素的操作。

  • .b后缀 :表示操作的数据类型为字节(8位)。使用.b后缀(如p0.b)时,每一位控制向量寄存器中对应的8位数据元素。这允许对向量寄存器中的单个字节进行更细粒度的控制。

可扩展的谓词寄存器

SVE 谓词寄存器 用于控制每通道操作,有16个可变长预测寄存器P0-P15,向量寄存器用于存储实际的数据,而谓词寄存器用于控制向量指令的条件执行。假设SVE的矢量长度为256,谓词寄存器在管理32位和64位操作时,其视图如下:

谓词寄存器通常被用作对数据操作的 bit mask

  • 每个谓词寄存器是Zx(可扩展向量寄存器)的 1 / 8
  • P0-P7是控制加载、存储和算术的谓词。
  • P8-P15是用于循环管理的额外的谓词。

SVE引入了谓词寄存器(如p0p15),这些寄存器用于控制向量操作的执行。谓词寄存器中的每一位对应向量寄存器中的一个元素,指示该元素是否应该参与到特定的向量操作中。

  • 当谓词寄存器位为 1 时,相应的向量操作会在对应的元素上执行;
  • 当谓词寄存器位为 0 时,相应的元素不会被操作。

接下来将介绍 .d.b后缀在谓词寄存器使用中的区别,并通过例子进行说明。

.d 与 .b 后缀的区别
  • .d后缀 :表示操作的数据类型为双字(64位)。当你使用.d后缀(如p0.d)时,这表示谓词寄存器中的每一位控制向量寄存器中对应的64位数据元素。通常用于精细控制对64位数据元素的操作。
  • .b后缀 :表示操作的数据类型为字节(8位)。使用.b后缀(如p0.b)时,每一位控制向量寄存器中对应的8位数据元素。这允许对向量寄存器中的单个字节进行更细粒度的控制。
举例介绍

假设我们现在有一个需求,对两个向量z0z1中的数据进行条件性处理,分别涉及对64位(双字)和8位(字节)元素的操作。

使用 .d 后缀进行64位元素操作
assembly 复制代码
// 设置p0,使其对64位元素全开
ptrue p0.d

// 假设z0和z1是两个64位元素的向量
// 使用p0控制的条件加法,只有在p0对应位为真时,z0和z1中对应的64位元素才会相加
add z2.d, p0/m, z0.d, z1.d

在这个例子中,ptrue p0.d指令设置p0中的每一位都为真,表示每一个64位的元素都应该参与下一条add指令的执行。这样,z0z1中的对应64位元素被相加,结果存储在z2中。

使用 .b 后缀进行8位元素操作
assembly 复制代码
// 设置p1,使其对8位元素全开
ptrue p1.b

// 假定z3和z4是包含8位元素的向量
// 使用p1控制的条件加法,只有在p1对应位为真时,z3和z4中对应的8位元素才会相加
add z5.b, p1/m, z3.b, z4.b

在这个例子中,ptrue p1.b指令设置p1中的每一位都为真,意味着每个8位的元素都参与下一条add指令的执行。这样,z3z4中的对应8位元素被相加,结果存储在z5中。

ptrue 指令
  • ptrue 指令用于将谓词寄存器中的元素设置为真(TRUE),指示后续的向量操作应该在所有元素上执行。
  • 例如,ptrue p0.bp0 寄存器中所有的位设置为真,.b 表示操作的最小数据单元是 byte。
小结

.d.b后缀在谓词寄存器使用中代表了操作的数据类型(分别是64位和8位),这允许开发者根据需要对向量寄存器中的数据进行精细的控制。通过使用不同的后缀,可以实现对不同数据大小元素的条件处理,使SVE在处理向量数据时更加灵活和强大。

FFR 寄存器

First Fault Register (FFR) 是一个特殊的谓词寄存器,由 first-fault 加载和存储指令设置,用于指示每个元素的加载和存储操作的成功程度。 FFR 旨在支持推测性内存访问,这使得向量化在许多情况下更容易和更安全。

推荐阅读
https://blog.csdn.net/AngelLover2017/article/details/124808387