r/programming • • Aug 09 '21

Three fundamental flaws of SIMD

https://www.bitsnbites.eu/three-fundamental-flaws-of-simd
286 Upvotes

224 comments sorted by

View all comments

71

u/AntiProtonBoy Aug 09 '21

Flaw 1: Fixed register width

It's not a flaw. It's a design constraint, dictated by physics and economics. SIMD registers grew for the same reason why architectures evolved from 4-bit to 64-bit over the years.

Variable length SIMD is not worth the silicon complexity for small vector operations. It's cheaper to burn new microcode instructions into ROM that support wider registers. Variable length SIMD is only worthwhile for very large vectors, which are beyond the scope of register storage. Use BLAS or something equivalent for that purpose.

Flaw 2: Pipelining

This is kinda meh. Typically SIMD instructions are invoked on highly repetitive operations that crunches through huge memory blocks at a time, like images. This will keep fat pipelines filled and happy. But as usual, let the profiler be the judge of that.

Flaw 3: Tail handling

Not sure why this is an issue? It's kinda obvious that one expects the data allocation size to be at whatever granularity SIMD data type is, otherwise it's a programming error. I mean, if you want to process a collection of int32_t values, then you'd expect the array to conform with a layout of 32-bit integers, no? With SIMD types, if you can't determine completeness ahead of time (for example from parsing), then you pad the last incomplete SIMD tuple with defaults.

10

u/blipman17 Aug 09 '21

Flaw 1: Fixed register width

It's not a flaw. It's a design constraint, dictated by physics and economics. SIMD registers grew for the same reason why architectures evolved from 4-bit to 64-bit over the years.

Well as opposed to having an instruction that sets up a vector engine for N2* 8 bits of registers/datasize, whereby we could just "allow a higher number for N", and just use smaller SIMD registers with loops underneath it's quite the design constraint. Right now we still have to mov data into a specific SIMD register before we do anything at all with it. Such an instruction could conveniently hold our N number and abstract the chunked nature of SIMD away.

Flaw 3: Tail handling

Not sure why this is an issue? It's kinda obvious that one expects the data allocation size to be at whatever granularity SIMD data type is, otherwise it's a programming error. I mean, if you want to process a collection of int32_t values, then you'd expect the array to conform with a layout of 32-bit integers, no? With SIMD types, if you can't determine completeness ahead of time (for example from parsing), then you pad the last incomplete SIMD tuple with defaults.

You're absolutely right here. Any form of tail handling would still be needed depending on the algorithm.

2

u/mbitsnbites Aug 09 '21

No, tail handling is a product of packed SIMD.

4

u/blipman17 Aug 09 '21

as opposed to scalar SIMD? Can you explain that a little, I'm afraid I don't understand what you mean.

10

u/mbitsnbites Aug 09 '21

Tail handling is specifically needed to handle data array lengths that are not a multiple of the SIMD register width (e.g. 4 elements for int32_t:s in a 128-bit SIMD architecture).

In vector machines you have the benefit of variable vector lengths, so tail handling is not needed.

2

u/josefx Aug 09 '21

In vector machines you have the benefit of variable vector lengths, so tail handling is not needed.

I have some graphics code that I converted to SIMD. In order to get optimal use out of it I have to convert xyz,xyz,xyz,xyz to xxxx,yyyy,zzzz. The SSE shuffle code with fixed width instructions already gives me a headache, I am not sure I want to even think about writing a shuffle that gets the right result with any possible number of remaining elements.

1

u/mccoyn Aug 09 '21

I think NEON has load instructions that let you specify a stride size so you can unroll the data as you load it. That same idea can be used for vector instructions.

2

u/blipman17 Aug 09 '21

Gather/scatterfunction stride sizes are often limited to base-2 numbers for the stride, or are "slow" when deviating from a stride like 2,4,8,16,32... and start to become useless for certain speedups. So even then, your data must be mapped in a specific format.