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.