4 ms·
> the best code almost always must be tuned for one specific CPU There’re very few relevant differences between CPUs of the same instruction set. The author of
by Const-me 5y ago
> the best code almost always must be tuned for one specific CPU
There’re very few relevant differences between CPUs of the same instruction set. The author of that PR implemented fast paths for SSE2, AVX2, and NEON. Combined, they cover like 90% of CPUs; the only notable missing one is the 32-bit ARMv7, C# doesn’t support vector intrinsics for that architecture.
> do you assume the SIMD hardware is powered up?
Modern AMD64 CPUs never power off just the SIMD. For AMD64 ISA, SSE1 and SSE2 are included in the base instruction set. Modern C++ compilers compile FP32 and FP64 math into SSE1 and SSE2 respectively, e.g. double y=x*3.0 compiles into MULSD instruction from SSE2 SIMD subset. Powering down that hardware would be too expensive for many programs.
Some early Intel’s AVX CPUs, like Sandy Bridge from 2011, powered down half of their SIMD hardware. On these CPUs, first time a program uses AVX instructions which process 32-byte vectors, the instructions run at half the throughput and +1 cycle of latency. The performance penalty lasts until the state transition is complete, like ~100 nanoseconds or something. AFAIK, for 32-byte AVX vectors, that got fixed years ago in the newer processors.
- MaxBarraclough 5y ago> double y=x*3.0 compiles into MULSD instruction from SSE2 SIMD subset Why is this? Isn't there a scalar instruction for handling just one float? Or does it have different precision characteristics or something?
- ygra 5y agoThat is the instruction for multiplying just one double (the SD suffix stands for scalar double); the respective instructions for handling more than one number at the same time have a PD suffix (for packed double). The alternative would be to use the x87 FPU registers and instructions, which are a lot slower these days (but yes, also with different precision characteristics). So they're usually not used at all in code targeting x64.
- MaxBarraclough 5y agoThanks, didn't realise SSE included non-SIMD instructions.
- Const-me 5y agoTechnically, that instruction is a scalar one. It multiplies just one number in the lowest lane of the vectors, and copies the second lane from the first vector register without changing it. BTW, on modern processors, the performance of such scalar instructions is exactly the same as their vector equivalents which handle all lanes of the registers. Before AMD64 took off, that C++ code compiled into x87 instructions https://en.wikipedia.org/wiki/X87 https://en.wikipedia.org/wiki/X87 That thing is ancient with first implementation from 1980, and some architectural features make it borderline impossible to be performant. For instance, internally it operates on 80-bit floats. Both FP64 and FP32 IEEE floats are being emulated based on bits in the control register.