Reconsider XXH_X86DISPATCH_ALLOW_AVX check #839
Labels
No labels
announcement
bug
build
CI
dependencies
documentation
duplicate
enhancement
experience feedback
feature request
github_actions
help wanted
install
invalid
Long-term
optimization
portability
question
target-specific
test issue
wontfix
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-Cyan4973/xxHash#839
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Distributions are beginning to build with
-march=x86-64-v3, for example Fedora ELN, so they trip over this.This conditional
#errorseems to be more of a reminder to xxHash developers and not users who recompile an unchanged xxHash distribution. I think it's reasonable to assume that if the toolchain defaults to-march=x86-64-v3(either implicitly or via injectedCFLAGS), there is no assumption that the result will run on machines without AVX support.xxh_x86dispatchwas designed for a scenario where the produced binary doesn't know if it will run on a cpu supporting a specific vector instruction set. Therefore, it compiles all potential variants, and then, at runtime, will select the most appropriate one, i.e. the fastest supported one on local cpu.My understanding is that adding
-mavx2or equivalent to the command line, which is one consequence of-march=x86-64-v3, messes with this design, in the sense that it's no longer possible to generate asse2-only variant ofxxhash. The reason is, using__attribute__((__target__("xxxx"))), it's possible to add a specific vector support if it was not already present on the compilation command line, but it's not possible to remove one.Therefore, with no additional precautions, such design would end up generating a
sse2variant which actually needsavx2. And then, at runtime, on a platform withoutavx2support, it would select this variant, and crash.So this is not great, but for people who nonetheless want to do that, presumably because they assume that the binary will never run on a platform without
avx2support, the build variableXXH_X86DISPATCH_ALLOW_AVXcan be enabled, removing the restriction.Somehow, it looks to me that this is a relatively safe default behavior. Without it, it would be relatively easy and unfortunately completely silent to produce the scenario described above, and then experience a ton of issues during deployment on a diverse set of platforms.
The build variable solution looks also fine by me, it makes the builder fully aware of the limitations of the produced binary, and requires to accept them by enabling the variable. This is very different from enabling the scenario transparently.
Now, one thing that could be improved is the error message. The way it's phrased, it just tells to not use
-mavxtarget, but it doesn't explain why nor provide any lead towardsXXH_X86DISPATCH_ALLOW_AVX(though both are explained in the source code documentation). This could be improved, so that package maintainers have an easier time discovering the build variable solution.Now, should it become default and transparent,
that's where I am rather cautious.
For the time being, I don't think it's a good idea. It will likely make build easier, but then will possibly result in massive support headaches at deployment time. The requirement to add a build variable in order to fully acknowledge and buy in the "no-sse2-available" limitation sounds like a comparatively minor inconvenience to me.
But what makes xxHash special that it needs this treatment? There are hundreds of other packages in a typical distribution, some with run-time dispatch, some without, and they don't do have
#errors like xxHash. If people copy incompatible binaries from machine to machine, they will likely encounter problems elsewhere.I agree that good diagnostics are important, but ideally, we want a run-time diagnostic if a binary is executed on an incompatible machine. We have implemented that in glibc, but so far it is only effective for glibc itself because it is difficult to generate the appropriate markers automatically in the link editor (because it does not know if the AVX code linked into the output file is executed conditionally or not).
libxxhashisn't supposed to use nor link tostdio.There's no way to generate any message of any kind from the library at run time.
Printing diagnostic messages could be done from the CLI, though that is a completely different target.
Issue is,
xxh_x86dispatchis not tied to the CLI, it's designed to be integrated at both library and CLI levels.Another thing I'm not sure to understand is why it is such a problem to add a compilation variable ?
The default build adds
xxhashonly, and this unit conforms to the set of flags provided at compilation time,meaning it will have no problem compiling with
-march=x86-64-v3, and will useAVX2mode in this case.Inserting
xxh_x86dispatchis not a default operation, and ironically requires setting a build variable. Hence, what's the problem with adding another one ?Summarizing the position expressed in this issue :
If a build config enables
AVX2extension, then it accepts that the produced binary will not work on a platform withoutAVX2support.Therefore, it's not useful to produce an auto-vectorization library which supports
SSE2only.This is understandable.
Unfortunately,
xxh_x86dispatchwasn't created with this scenario in mind. So, instead, it simply required that this scenario doesn't exist.Proper adaptation to this new requirement would require an ability to bypass
SSE2code path generation (currently it's always produced), and be paired with an ability to provide a clear error message for platforms withoutAVX2support (instead of a segfault), which can only be done in the CLI code.In the meantime, the current work around which simply removes the "no avx2" protection and let the library be built with the
AVX2capability flag will do. It will "work" fine on compatible systems. It's just that it will nonetheless produce a (now useless)SSE2code path, and will segfault on systems without AVX2 support.Looking back at this issue, it inspires some comments :
XXH_X86DISPATCH_ALLOW_AVXdoesn't feel correct, as a build macro name. Rather, I believe it should have beenXXH_X86DISPATCH_REQUIRE_AVX2, aka the produced binary will fail if not run on a system supporting at leastAVX2.DISPATCHvariant which doesn't supportSSE2, and would then crash on systems withoutAVX2.AVX2support would result in a crash. That's undesirable. A better outcome would be a clean exit. Problem, this is not possible atxxh_x86dispatch.clevel, sincestdiois not present there, and some functions are not even allowed to fail. But it would be possible at CLI level. The consequence though would be some additional complexity to support this scenario in the CLI and test framework, and its ongoing maintenance. Without specifics, it's not clear at this point if this is a desirable trade off.The next release of
xxhash(v0.8.3) will use a different policy, whereDISPATCH=1will be automatically enabled when target system isx86/x64, and compilation will work whatever is the minimum instruction set required, without the need to employ a specific build variable.Of course, in such a case, the produced binary can only work on systems featuring the requested instruction set.