Can someone wake me up when it is a no-brainer to use AVX512 instructions on CPUs that support them? :-)
Daniel Lemire, who I work with on simdjson, wrote this on throttling: https://lemire.me/blog/2018/08/13/the-dangers-of-avx-512-thr...
I don't know specifics (I'm ex-Intel a good bit before SNC, and wasn't a hardware guy) but my impression is the clock throttling impact gen-on-gen goes down. If you're actually getting good value from AVX-512 instructions rather than chucking in 1 in 1000 instructions for the cool factor, you're probably fine.
While you are here... :-)
What do you think about the tendency of glibc to use the latest available instruction set extensions for routines like memcpy? Should we be worried that when we call memcpy() in a program this will effectively mix some wide-datapath instructions into the CPU's instruction stream with potentially hilarious consequences like clock throttling? What's all that about?
Even if you did get 2x, you would have to balance that against clock throttling in circumstances where you have no idea of the _relative_ importance of your library. Are you 95% of the cycles, or 10%?
One related example is Intel CPUs having good cache-DMA integration but this not working across NUMA nodes. Ideally Intel would improve this feature to be NUMA-aware and everybody would be happy. However, it seems like they decided it would be cheaper to send forth an army of software engineers to put NUMA-scheduling kludges into a few key projects like Kubernetes and then call it a day.
/rant!
How do you propose they do this? You can't magically move the physical devices to the other socket, and transferring the data between sockets is what those "NUMA-scheduling kludges" are trying to avoid. The only solution is to have software put the data close to the device.
But IIRC, back when AVX was introduced, there was some issue with that as well, and similar with AVX2. But now those seem to have been mostly addressed. I guess in some years the same will happen with AVX-512 too?
The pattern for me is that I'm excited about a new instruction set when it is announced, then disappointed when it is shipped in silicon, then I have a hard time knowing when it is truly resolved and worth taking a second look at.
My recollection with AVX2 is that glibc shipped those routines since before silicon was generally available, and then kept them enabled even when the clock-throttling issues became apparent. (The water was muddied a bit in one glibc release that shipped a bug in selecting which code to use for the running uarch, but that's a separate issue.)
I will point out three things that make the Sunny Cove exciting to me, beyond the obvious new instructions (based on the available slides):
- There are now two ports for vector shuffles. For shuffle-heavy applications, which is often the case with bit-manipulation kernels, this is great news. This seems improved from Cannonlake.
- This was already present on the Cannonlake, but integer division is drastically improved, and goes from ~30ish uops to 4. Divisions that could take up to 90 cycles will now take <=18.
- There are now 4 LEA ports, up from 2, which for address calculation and small integer multiplications are quite useful.
Integer division is never really on my radar, but yes, that's exciting.
LEA is very useful, but not something I spend a huge amount of time thinking about. It would be interesting to see whether the penalty for a "slow LEA" is relaxed.
You're right that the Skylake-X processors have AVX-512, but they kinda push the 'consumer' envelope. There's also no consistent branding for 'having AVX-512 or not' (they have happily adopted i7/i9 for products that don't have it). These are really obviously rebadged Xeons. Nothing against them, but it's a tiny niche.
Faster integer division is exciting to me, and so is the prospect of faster "slow LEAs."
The other year I was able to speed up a Lua MD5 benchmark by 15% by eliminating slow-LEAs from the JIT backend. I only tracked down half of them though, so if the problem has eased that would save me tracking down the other half :). https://github.com/raptorjit/raptorjit/pull/55
Also, each new Intel platform seems to bring additional instructions but most software isn't made available in a wide range of microarchitecture-specific builds. Is there typically capability detection going on behind the scenes ?
Some of the operations described here seem so specific, that I have a hard time imagining compilers being able to spot the relevant patterns in source code that can make use of them (then again, I'm not a specialist). I guess these are explicitly coded for in Assembly ?
These instruction sets can offer very substantial speedups for code paths when applied judiciously. You do need to check the CPU capabilities at start up time for practical software, you can't assume the environment supports it even when these instructions have been around a long time. Some had very uneven implementation timelines across CPU product lines. Even for explicitly high-performance software, I invariably would get bug reports because someone tried to run it on a 10+ year old machine that did not support the instructions I was using. There are standard open source libraries for doing this feature detection using CPUID.
There's a fair bit of work where people try to autovectorize code. I'm happy that folks are pushing this work, but, well, I drive a manual (in this regard).
It does happen that code does auto-detection and skips to a particularly compelling platform-specific optimization path, but it's a huge pain. It's unlikely that someone will optimize for each and every variant, but they might draw a line here and there through the myriad of architecture choices and offer something.
Sorry that the story isn't better. I generally hand-code stuff - not in asm but with intrinsics (which is getting a lot of the benefit of asm, but without doing all your own codegen for the boring bits, scheduling and register allocation).
(Disclaimer: I wrote software rasterizers, drivers, and compilers for Larrabee.)
And currently, AMD is definitely winning there, and it may be my processor of choice for the next few years, until Intel fixes shortcomings in all those areas. 10nm is a step in the right directions, but the price/performance ratio is nowhere close to the mark.
But that's just my take on that.
In the beginning you write that "VBMI [...] is the only extension that we’ve seen before – it’s in Cannonlake." but later you write that "VPOPCNTDQ is older (from the MIC product line)"
So which is it? Or am I misunderstanding something?
- Using these instructions to encode/decode compressed data structures where evaluation would otherwise be memory-bound, trading the "free" CPU time to reduce memory bandwidth consumption. Large bitmaps are amenable to this.
- Increasing throughput of operations that are CPU bound so that they become (closer to) memory bound, recognizing that the memory bandwidth available to CPU cache-friendly structures may effectively be much higher than RAM bandwidth. Format parsing and cache replacement is a common use case for vector intrinsics in databases for this purpose.
- Reducing branch prediction penalties for data structures that don't play well with branch predictors. Commonly used hot path radix-trie structures often have this issue. Some of the intrinsics don't have a direct scalar equivalent and redesigning around them can significantly reduce branching pressure (both number and predictability).
- Scan operators for vectors of high-level data types, ironically because they allow you to efficiently use a more complex representation than a simple vector. Pages in databases are large enough these days that this is worth doing and you'll spend much of your CPU time here anyway.
I have not (yet) built an operational database kernel that uses AVX-512 intrinsics, though the designs are setup for it, mostly because support is still insufficiently common at the moment. I think the CPU throttling aspects of vector instructions are less of a concern for database engines because good designs tend not to have clock rate as a major throughput limitation in practice, though I've never actually measured it.
Scanning non-DBMS stuff can benefit a lot from good SIMD (although writing code that's tremendously clever that allows you to run faster than memory bandwidth permits is also fairly self-limiting; the faster you go, the less likely anything can keep you fed).
I feel like I met that one other guy in the world.
One of these is not like the others
No 2nd FMA really sucks, hope they add it when they do desktop-
I can't tell from the micro architecture slide if the yellow box labeled "ALU" that is found on port 0 and 5 refers to only integer ops, or if that includes float(add/mul).