高通 Hexagon V65 HVX 编程参考手册(4)
3.7 排序
为了提高性能并减少硬件开销,只对线程内的一部分内存操作进行排序。以下对操作是有序的:
表 3-2 列出了线程中未排序的成对操作。列出的障碍可以放在操作之间以实现它们之间的排序。
Scatter和gather操作适用于上表中的一次元素(即,在scatter/gather指令的元素之间没有排序)。
当较新的操作确定性地取决于较旧的操作时,还可以确保在两个内存操作之间进行排序。例如,当内存写入需要从先前的内存读取的数据时,将在读取后排序写入。这适用于读取,然后是每元素的写入操作,scatter累积。
3.8 原子性
表 3-3 描述了不同类型内存访问的分解原子操作的大小或对齐方式。当访问不是完全原子的时,观察者可以看到访问的原子组件。
单个scatter和gather访问只能与其他scatter访问或gather访问权限。
3.9 性能注意事项
本节介绍了最大化矢量内存系统性能的最佳实践。 HVX矢量处理器直接连接到L2缓存。 VMEM加载/存储将数据移动到/从L2移动,并且不使用L1数据缓存。为了确保与L1相干性,VMEM存储检查L1并在HIT时无效。
3.9.1 最小化 VMEM 访问
从向量寄存器文件 (VRF) 访问数据比从内存访问数据在周期和功耗方面要便宜得多。提高内存系统性能的最简单方法是减少 VMEM 指令的数量。当数据可以托管在 VRF 中时,避免将数据移入/移出内存。
3.9.2 使用对齐数据
VMEMU 指令访问多个 L2 缓存行并且在带宽和功率方面很昂贵。在可能的情况下,数据结构应与向量边界对齐。填充图像通常是提供对齐数据的最有效技术。
3.9.3 避免存储到加载停顿
VMEM 存储跟在同一地址后的 VMEM 加载指令会导致存储到加载损失。存储必须在加载开始之前完全达到 L2,因此惩罚可能会非常大。为避免存储到加载停顿,应该有大约 15 个数据包的干预工作。
3.9.4 L2Fetch
L2Fetch指令应在使用VMEM负载之前使用数据预先填充L2。
L2Fetch最好以小于8 kb的尺寸执行,在使用数据之前,应至少发出数百个周期。如果L2Fetch发出过早的发行,则可以在使用数据之前将其驱逐出现。通常,对图像行或瓷砖的预取和处理最有效。 VMEM使用的所有L2可缓存数据也应预取,即使在计算中不使用它。软件管道循环通常会超载数据,这些数据将不使用。即使PAD数据未在计算中使用,如果尚未将其预取到L2,则VMEM失速。
VMEM 使用的所有 L2 可缓存数据都应预取,即使在计算中未使用它也是如此。软件流水线循环通常会使不使用的数据过载。即使填充数据未用于计算,如果未将其预取到 L2,VMEM 也会停止。
3.9.5 连续访问数据
只要有可能,内存中的数据就应该被安排成可以被连续访问。例如,数据可能首先被平铺、条带化或抽取,而不是反复遍历内存,以便可以连续访问。
以下技术可在内存中实现更好的空间局部性,以帮助避免各种性能危害:
- bank冲突。较低的地址位通常用于并行存储器组。连续访问数据可以很好地分配这些地址位。
- 设置别名。高速缓存包含许多由较低地址位标识的集合。每个集合都有少量方法(通常为 4 到 8 个)来帮助管理别名和多线程。
- Micro-TLB 未命中。记住有限数量的页面以进行快速翻译。将数据包含在较少的页面中有助于提高翻译性能。
3.9.6 对最终数据使用非时态
在最后一次使用数据时,使用“:nt”属性。缓存使用此提示来优化替换算法。
3.9.7 矢量数据的标量处理
当 VMEM 存储指令产生数据时,该数据被放入 L2 缓存中,L1 不包含有效副本。因此,如果标量加载必须访问数据,则必须首先将其提取到 L1 中。
算法通常使用矢量引擎来产生一些必须在标量核心上进一步处理的结果。最佳做法是使用 VMEM 存储将数据放入 L2,然后使用 DCFETCH 将数据放入 L1,然后是标量加载指令。 DCFETCH 可以在 VMEM 存储之后的任何时间执行,但是,在发出标量加载指令之前,软件应该至少预留 30 个周期。
3.9.8 避免scatter/gather stalls
catter和gather操作会争夺内存,由此产生的延迟可能会很长,因此需要格外小心以避免停顿。以下技术应该提高catter和gather的性能。
-
在矢量内地址范围内分布访问(较低地址位)。即使在最不重要的载体间地址位上的分布也可能是有益的。对于V65,地址位[7:1]对于避免冲突很重要。理想情况下,这将适用于每个向量指令,但是在向量指令之间分配这些访问可以帮助吸收向量指令中的冲突。
-
最小化catter和gather指令的密度。将这些指令catter在一个更大的循环中,而不是将它们集中在一个紧密的循环中。硬件可以并行处理这些指令中的一小部分。如果难以展开这些指令,则将给定线程的突发限制为四个(对于 V65)。
-
延迟从收集结果或catter存储发布中加载。如果飞行中的catter和gather(包括来自其他线程)避免冲突,则 12 个或更多数据包的距离应该足够了。如果飞行访问的地址不相关,则需要两倍的距离。