Three fundamental flaws of SIMD
https://www.bitsnbites.eu/three-fundamental-flaws-of-simd/
文章列举了SIMD的几个缺陷。使用SIMD的确提高了CPU的使用效率,但是它似乎是以某种break abstraction的方式来提供了,从长远来看这似乎并不是一种可持久的方式。
第一个问题就是fixed register width. 每一代的SIMD都会提供更多的指令,但是同时寄存器的宽度也加大了。看起来这似乎是个好事情,但是这样会将许多其他事情复杂化:ABI需要考虑寄存器的save, CPU会有更多的opcodes, 指令长度增加了,对于定长指令的CPU解码不友好,而且许多操作都是有着重复语义的。
第二个问题是pipelining. 如何有效地执行SIMD指令。通常SIMD需要好几个指令周期才能完成,这就要求CPU提供流水线和乱序执行方式,否则retire inst的速度就跟不上。
第三个问题是做tail handling. 对于满足不了SIMD宽度的循环次数,需要做尾部展开,一方面会引入逻辑错误,另外一方面会让代码的体积增加。不过通常编写C/C++代码的时候,都需要考虑如果CPU不支持某种指令集的case, 所以通常也会有scalar处理的代码,而这部分代码正好可以用于tail handling. 所以我觉得实际上并不是太大的问题。
作者最后给出了几个alternatives, 不过因为自己对体系结构也没啥研究,只能看看而已。作者给出了一个 z=a*x+y的例子来证明SIMD的冗长,那么真的真的很长,而设计良好的指令集就没有这个问题。
saxpy: beq0 r1,1f ; Nothing to do? mov r8,#0 ; Loop counter = 0 vec r9,{} ; Start vector loop lduw r6,[r3+r8<<2] ; Load x lduw r7,[r4+r8<<2] ; Load y fmacf r6,r6,r2,r7 ; x * a + y stw r6,[r5+r8<<2] ; Store z loop ne,r8,r1,#1 ; Increment counter and loop 1: ret
SIMD should basically be unceremoniously clubbed to death and buried as the worst and most deeply embarrassing mistake in the history of mainstream computing of the past 50 years.