我一直在阅读最近可用的 AVX-512 说明,我觉得有一个基本概念我不理解。对于已经执行乱序执行的超标量 CPU,SIMD 有什么好处?
考虑以下伪汇编代码。使用 SIMD:
load 16 floats to register simd-a
load 16 floats to register simd-b
multiply register simd-a by simd-b as 16 floats to register c
store the results to memory
没有 SIMD 的情况下:
load a float to register a
load a float to register b
multiply register a and register b as floats to c
store register c to memory
load a float to register a (contiguous to prior load to a)
load a float to register b (contiguous to prior load to b)
multiply register a and register b as floats to c
store register c to memory (contiguous to previous stored result)
[continued for 16 floats]
我已经有一段时间没有完成这样的低级工作了,但在我看来,CPU 可以将非 SIMD 示例转换为按数据顺序运行:
- 并行处理 32 个加载指令(如果内存正确对齐,可能只是对缓存/内存的两个请求)
- 加载完成后并行执行 16 个乘法指令
- 16 次存储到内存,如果正确对齐,这将只是对缓存/内存的单个请求
从本质上讲,感觉 CPU 足够智能,可以在这两种情况下以相同的速度执行。显然,当我们继续向 ISA 添加更多和更广泛的 SIMD 指令时,我在这里遗漏了一些东西,那么这些类型的指令的实用价值从何而来?
区别主要是在硬件上实现这样的设计的可行性。由于各种原因,超标量架构的可扩展性不太好。例如,在一个周期内重命名这么多寄存器是很困难的,因为您重命名的内容可能是相关的(如果它确实是翻译的 SIMD 代码,它们就不会是相关的,但您无法知道这一点)。物理寄存器文件需要大量额外的读写端口,这非常烦人。相比之下,更宽的寄存器很容易。转发网络的规模将呈爆炸式增长。 Alot每个周期都必须将微操作插入到活动窗口中,其中许多微操作必须被唤醒和分派,并且许多微操作必须退出。由于机器现在充斥着更多数量级的微操作,您可能希望支持更大的活动窗口,否则它实际上已经变得更小(对于等效代码,它的效率会降低)。
整个内存业务也变得更加困难,因为现在您必须在一个周期中支持大量访问(所有访问都必须经过单独的翻译,对其应用排序约束,参与转发等等),而不是只是更广泛的访问(这相对容易)。
基本上,这种假设的设计需要很多已经很难通过合理的功率和面积预算有效实施的事情,然后使它们变得更加困难。其中许多事情的复杂性与您想要在一个周期中执行的微指令数量成近似平方关系,而不是线性关系。
添加更宽的 SIMD,他们一直在做的方式,很大程度上只是复制粘贴 SIMD 单元(因此大多数 AVX 和 AVX2 指令的烦人语义)并为某些东西提供更高的位宽。如果你这样做的话,扩展并没有什么不好。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)