3 ms·
Zig the language doesn't do this right away, but: 1. IMO it'd be a bit more ziggish to branch at compile time. Zig has cross-compilation as a first-class featu
by hansvm 4y ago
Zig the language doesn't do this right away, but:
1. IMO it'd be a bit more ziggish to branch at compile time. Zig has cross-compilation as a first-class feature, and you generally know the architecture you're targeting.
2. Whether you're branching at runtime or compile time, it'd be easy to build a vectored app with that behavior. The first thing that comes to mind is having code that's generic on the vector type (or bit width) and then just choosing which generic to instantiate in an inline for loop in your app's entrypoint.
3. A lot of the time you don't need that behavior. Select a vector width 8x too big, ensure your data is chunked into multiples of that, and rely on the compiler to break that down into a few instructions of the appropriate length. You can't effectively target a GPU that way, and it's not the same as hand-tuned assembly, but you get decent results on a vast array of problems.
- murkt 4y agoCounterpoint for 1: packages on PyPI or NPM. When I’m publishing an extension for another language. I really have no idea about their architecture. I’ve seen people just compile for the lowest common denominator. E.g. faiss-cpu on PyPI doesn’t even include AVX2 and is slow as heck.
- barrkel 4y agoArchitecture yes, but specific feature set, including exact support for each incremental revision of the SIMD instruction and register set, not so much. If you're e.g. providing a docker image for a service, it's fine to build per architecture, but you don't want the hassle of producing a different one for SSE4, SSE4.1, SSE4.2, SSE4a and so on.
- janwas 4y agoFair point, but we find it useful to have a few clusters: SSE4, AVX2 (Haswell), Skylake, newer AVX-512 Icelake/Zen4. That's still manageable, we're just compiling the SIMD parts 4 times and binary size impact is very modest (we're not replicating the entire binary).
- anonymoushn 4y agoregarding point 2, it's not that simple. A lot of 256-bit-wide goodies are in AVX-512 and a lot of different sets of extensions exist.
- p0nce 4y agoCounterpoint: it's not all positive to do multiversioning. - You pay for it in build times, more IR, more optimizations. - a lot of software is for servers, in that case you mostly know the arch before-hand. Multi-versioning is best for consumer software. - The lowest spec computers, in consumer software, need the optimizations the most. And they don't have latest instructions. - SIMD has biggest gains from memory optimizations, and those do not necessarily require the latest and greatest instructions.
- burntsushi 4y agoIndeed. This is how ripgrep works. It's compiled for just plain `x86_64`, but it looks for whether things like AVX2 are enabled. And if so, uses vector algorithms for substring and multi-substring search. The nice thing about dealing with strings is that the "coarse" requirement is already somewhat natural to the domain. But, this functionality is absolutely critical. It doesn't even have to be automatic. Just the ability to compile functions with certain ISA extensions enabled, and then only call them when the requisite CPU features are enabled is enough. In a nutshell: https://github.com/BurntSushi/memchr/blob/8037d11b4357b0f07be2bb66dc2659d9cf28ad32/src/memchr/x86/mod.rs https://github.com/BurntSushi/memchr/blob/8037d11b4357b0f07b...
- burntsushi 4y agoYou can't branch at compile time. Well, you can, but that's less useful than branching at runtime. If you branch at compile time, then you need to produce binaries that have a minimum supported ISA extension. But if you branch at runtime, then you can produce maximally portable binaries that only use ISA extensions when they're available.