The least interesting part about AVX-512 is the 512 bits vector width
mastodon.gamedev.place
mastodon.gamedev.place
AVX-512 adds many instructions that can replace what used to take 3 less efficient instructions.
This instruction set also double the number of available SIMD (single instruction multiple data) registers.
Those instructions are very useful on 128 bits vectors. And not a lot of people actually need 512 bit vectors.
Because of the number of registers and 512 bits width, it takes a lot of space in silicon. This makes it costly, and so is reserved for more expensive CPUs.
Had it been limited to, or also offered in a 256 bits version, this instruction set would have most likely be included in many more CPUs. Making it much more useful.
From the two desktop vendors AMD has AVX-512 support on all their AM5 CPUs. Intel has support of AVX-512 on all 11th gen CPUs and on some 12th gen CPUs. The supports is there in the silicon on all P-cores in 12/13th gen CPUs, just disabled in microcode.
So AMD and Intel have already paid the cost.
Starting with Alder Lake, Intel has dropped the AVX-512 support in non-server CPUs.
On the other hand, AMD has just launched their Phoenix mobile CPUs (Ryzen x 7x40 HS or U), which have excellent AVX-512 support.
In Intel's case, Cannon Lake did have AVX 512, but was blocked from being a mainstream part due to 10nm yields. And then their rushed efficiency core strategy effectively disabled AVX-512 just as they were getting back on track.
I don't think there's an intrinsic reason you couldn't have efficiency cores run AVX-512 albeit slowly and expect we'll see just that.
I partly blame Linux for that. I remember asking at Kernel Recipes about supporting truly heterogenous multi - processor systems and got shrugged "don't buy broken hardware". Back then, it was for a Broadcom home gateway product, which has an asymmetrical dual core, one with a FPU, the other without. Since then we have seen many examples of such assymetry: most HMP smartphones have asymmetrical instruction set. Mono (and probably all JIT VMs) hit issues of varying cache length so the perfect abstraction is already gone. And now we have Intel E vs P. This is a rather hard problem, I won't pretend otherwise but the amount of dead silicon, and lost power efficiency accumulates significantly.
If the kernel tried to fix that by moving such faulting threads to P-cores that would lead to a memcpy routine with AVX512 instructions cause all threads to be moved off E-cores.
So first intel would have to introduce new CPUID semantics to indicate that e.g. AVX512 is not supported by default and then a separate flag indicating that it's specifically supported on this core and then userspace would have to pin the thread if it wants to use them or stick to the default set if it wants to be migratable.
I think I agree, the thing is that it's a kind-of security issue. I suggested pinning, because it requires CAP_SYS_NICE, which is a feature: If you allow apps to freely declare their usage, they will end up being scheduled not fairly, because system will stick them to P cores.
That being said, you could have indeed an ELF header mentioning since, and then ignore it if caller doesn't have CAP_SYS_NICE. I do feel using an ELF header for that is weird, but my knowledge of ELF is way too little to judge.
Another thing that could work is using file-system attributes or mode (like setuid), but I think FS support of attributes is at best spotty, and I doubt modes can be extended.
Big companies like Samsung should have more than enough resources and interest in doing so. Unlike the guy who answered you at Kernel Recipes, I guess.
> Had it been limited to, or also offered in a 256 bits version, this instruction set would have most likely be included in many more CPUs. Making it much more useful.
Someone it's blatantly ignoring AMD CPUs...
Notice there are 4 functions mapping 1 bit -> 1 bit: const 0, const 1, copy, invert.
There are 16 functions mapping 2 bits -> 1 bit. Think 4 possible inputs, 2 possible output values for each input (0 or 1), so there are 2^4 = 16 such functions.
Likewise 256 functions mapping 3 bits -> 1 bit: 8 possible inputs, 2 possible output values for each input, so 2^8 = 256 such functions.
This means that the set of functions 3 bits -> 1 bit may be indexed by a single byte! With this instruction, you specify the byte as an immediate, it is interpreted as an index into a function table, and so you get any 3-valued boolean function.
I wonder if we'll see a similar instruction for 2 bits -> 2 bits? Could be useful!
You don't even need to support all 16 functions, as a number are duplicates or could be implemented with others. The following list covers all possibilities:
- AND, OR, XOR [supported basically everywhere]
- AND-NOT (a&~b), OR-NOT (a|~b) [sometimes supported]
- NOT-AND (~(a&b)), NOT-OR (~(a|b)), NOT-XOR (aka XNOR)
So only a few basic instructions need to exist to support all combinations of 2-operand bitwise logic.
However, the two bytes below encode the formula for the function, so that the transfer could be JITted more easily. This is not really necessary, since you could just use 512 bytes for the mapping, but memory tradeoffs were different back then...
No, because the way all modern high-performance CPUs work implies that an instruction with two destinations cannot really be any faster than two instructions with a single destination. So you can implement 3 bits -> 2 bits with two VPTERNLOGDs and can't do any better than that for 2 -> 2.
When people talk about algebraic data types, they tend to forget about functions.
The tuple `(a, b)` is a product type because it has #a * #b possible values. The union type `a | b` is a sum type because it has #a + #b possible values. the function `a -> b` is an exponential type because it has #b ^ #a possible values.
It baffles me that clang in particular disregards them. Clang’s intrinsics and builtins generally use the unmasked forms and fake it with subsequent combining operations. This always benchmarks slower in loops, and often demands an extra register. I haven’t delved deeply, but it feels like either the cost model is mispredicting potential k-register bottleneck, or it doesn’t know about masked AVX-512 instructions at all. In comparison, GCC does, but it falls down (on my code at least) in needing more explicit vectorisation than clang.
Really? It's a forced read-write dependency on the destination register. Which makes sense for cores with limited superscalar. But for ops with >1 cycle latency or >1/cycle throughput, chained masks are likely to inhibit ILP and be slower...
Unfortunately the SysV ABI interferes with compilers allocating upper SIMD registers, since they're all call-clobbered. This motivates bigger functions: almost all my intentionally vectorized/vectorizable code is declared inline and very occasionally I've resorted, reluctantly, to inline asm. Whether the ABI design is actually a mistake, and then how/whether it might be remediated, remains a matter of opinion.
Digression:
The consequence of all this is there's often More Than One Way To Do It, which no matter how much mechanical sympathy you might hope to innately possess still means punching lots of variants on your code into uica/iaca et al to paint anything like a decent picture about bottlenecks, as well as doing your damnedest to ensure that any benchmarking of loops/computation you care to perform during development actually corresponds to real execution. The holy grail, viz. writing C or other HLL that auto-vectorizes well on more than one compiler and more than one architecture (because you wanted to support NEON, too, right?), becomes a near-bottomless programmer time sink.
There are real benefits to be had, but given the additional time-investment required to obtain those benefits, it's little wonder that AVX-512 is shortchanged on intentional adoption, and that's even before Intel started crippling Alder Lake. In the long run, only greater strides in compiler auto-vectorization capabilities will fix this for everyday code.
AVX-512 has 32 registers because the Pentium core Larrabee was developed against was in-order. In a real sense, the P5 core dictated much of AVX-512's design.
There isn't a useful way to define a general ABI with callee saved vector registers without saying something like "only bits [127:0] are saved"
Portable SIMD aside (which is sitting forever unstable & unavailable), the actual intrinsics I feel should not be. Quite frustrating, and along with missing allocator_api (still!) makes me feel sometimes like 'reverting' back to C++.
https://doc.rust-lang.org/stable/core/arch/x86_64/fn._mm256_...
Either way I recently had to write a SIMD implementation in both SSE (Intel) and Neon (Arm). This was my first time writing SIMD. I found the neon instruction set much more intuitive and complete than SSE. There are all these weird limitations in SSE (such as trying to do a reduction sum across a vector or shifting across vectors) that made it feel incomplete. Never had a chance to try out AVX.
aka 10nm Enhanced SuperFin aka Intel 7 (12000 and 13000 series)
Which funnily enough don't support AVX512, unlike the previous 10000 (14nm++) and 11000 (14nm+++) series.
Some motherboards allowed you to enable AVX512 on those chips if you disabled the E-cores, but then Intel started permanently fusing off AVX512 in hardware on later batches.
(and instead of making a new feature that allows VL without F, Intel's "solution" seems to be about piecemeal backporting EVEX instructions to VEX (e.g. VNNI, IFMA))
NEON is generally a more "complete" SIMD ISA than SSE/AVX, though it has less "fancy" stuff. AVX-512 fills in a bunch of gaps that was missing in earlier ISAs, but still has odd omissions (like no 8-bit bitwise shift).
Disclosure: I am the main author.
Maybe this doesn't matter, almost certainly wouldn't for most people, but I'm compiling the whole system myself so the compiler at least has the freedom to use AVX-512 wherever it pleases. Does anyone know if AVX-512 actually makes a difference in workloads that aren't specifically tuned for it?
My guess is that given news like https://www.phoronix.com/news/GCC-AVX-512-Fully-Masked-Vecto... that compilers basically don't do anything interesting with AVX-512 without hand-written code.
I know game console emulators use it to great effect with significant performance increases.
1: https://www.tomshardware.com/news/ps3-emulation-i9-12900k-vs...
The tools are there in the instruction set, but that still leaves the issues of time and effort to implement in compilers, and enough performance improvement on enough machines in some market (browsers, games, etc) capable of running it all before any of this possibility becomes real.
The skylake-xeon/icelake false start here really can’t have helped. It’s still a much more pragmatic thing to target the haswell feature set that all the intel chips and most amd chips can run (and run well).
Sometimes the second comer to a game has the advantage of taking their time to implement something, with fewer compromises and a better overall fit.
My question is just... does it? (And does it use AVX-512 profitably?)
Depends on a couple factors (i.e. Ice Lake client only has 1 FMA unit) but I'd be surprised if Tiger Lake was a major regression relative to Ice Lake. It seems like they had it in an OK spot by then.
I'm not rebuilding specifically for this one potential optimization.
Unless you have a very specific AVX-512 workload or you need to run AVX-512 code for local testing, you won’t see any net benefit of keeping your older AVX-512 part.
Newer parts will have higher clock speed and better performance that will benefit you everywhere. Skipping that for the possibility of maybe having some workload in the future where AVX-512 might help is a net loss.
AMD Phoenix is far better than any current Intel mobile CPU anyway, so it is an easy choice (and it compiles code much faster than Intel Raptor Lake, which counts for a Gentoo user or developer).
The only reason to not choose an AMD Phoenix for an upgrade would be to wait for an Intel Meteor Lake a.k.a. Intel Core Ultra. Meteor Lake will be faster in single-thread (the relative performance in multi-thread is unknown) and it will have a bigger GPU (with 1024 FP32 ALUs vs. 768 for AMD).
However, Meteor Lake will not have AVX-512 support.
For compiling code, the AVX-512 support should not matter, but it should matter a lot for the code generated by the compiler, as it enables the efficient auto-vectorization of many loops that cannot be vectorized efficiently with AVX2.
While gcc and clang will never be as smart as hand-written code, their automatic use of AVX-512 can be improved a lot and announcements like that linked by you show progress in this direction.
However, compilers have so far been slow to implement this, with the relevant patches only going into GCC right now.
Some interesting replies too, eg https://mastodon.gamedev.place/@TomF/110572967731705754
A story I would have believed was that the instruction set was designed with some useful seeming instructions and a hope that compilers would improve. But it sounds like it was designed much more closely with actual example programs and a compiler, just not the kind that attempts to vectorise scalar code.
https://upcommons.upc.edu/bitstream/handle/2117/77204/VSR%20... shows how radix sort can be vectorized much more efficiently using these types of instructions.
I wonder if this would be useful for implementing cryptographic algorithms.
VPTERNLOGD basically works by constructing a truth table for 3 inputs.
| A | B | C | R
| 0 | 0 | 0 | x
| 0 | 0 | 1 | x
| 0 | 1 | 0 | x
| 0 | 1 | 1 | x
| 1 | 0 | 0 | x
| 1 | 0 | 1 | x
| 1 | 1 | 0 | x
| 1 | 1 | 1 | x
You pick the values you want for R, then pass this 8-bit value as the operand to the instruction along with the 3 values.For example, A ∧ B ∧ C would be 0b10000000. A ∧ ¬B ∧ ¬C would be 0xb00010000
There are 256 such tables and many of them can be represented by multiple boolean expressions.
#define A 0xf0
#define B 0xcc
#define C 0xaa
And then you can build immediate for VPTERNLOG operation by writing bitwise expression with A/B/C values in source code.For example, A^B^C=150. A^(~B&C)=210. And so on...
Also mentioned by Fabian here: https://twitter.com/rygorous/status/1187032693944410114
[1]: https://whatcookie.github.io/posts/why-is-avx-512-useful-for...
That’s an interesting point. Does anyone know—the Knights Landing Phi had AVX-512 and was based on Atom cores. Did they bolt on all these extra registers?
In fact, it looks like Haswell and Skylake-X had the same number of physical registers, 168. So that's a straightforward doubling from 256x168 to 512x168.
But further into the thread it looks like the first gen E cores had about 200 128-bit register lines, so trying to fit 512x32 would have been very tight.
To put some of that a different way: The vector design headed for E cores was 128 bits stretching to 256 bits. If it had been 256 bits all the way through, it's likely they would have added AVX-512 support, even if they couldn't increase the size of the register file at all.
There's a chips and cheese article on this.