HiGHS added a runtime dependency on `libatomic` on 32-bit platforms
We observed this in SciPy, after updating to a recent version of HiGHS, and then receiving reports of broken installs on 32-bit armv7 and 32-bit PowerPC. There is fairly heavy use of std::atomic within HiGHS, however there is no discussion on a libatomic runtime dependency, so I thought I'd open this issue first to ask if that dependency was intended or not.
The details of this are compiler-specific; what seems to be happening is that std::atomic tries to map to lock-free machine instructions when they are available, and if that doesn't work then it needs compiler-specific builtins. And this is more likely to happen for more complex data structures I believe. GCC moved those builtins to a separate library, libatomic, which you explicitly have to link with -latomic. For Clang the situation is similar but more complex, since it can use GCC's runtime libraries or its own compiler-rt runtime. For other compilers, I have no information.
For more detail on this and how we fixed the build issue, see https://github.com/scipy/scipy/pull/17777. Having to vendor libatomic in wheels in order to make them portable is not great. So ideally we'd track down better what the root cause is here and avoid the need for such bundling. In SciPy, both PocketFFT (in scipy.fft) and Boost (in scipy.special and scipy.stats) also use std::atomic, but they do not cause a dependency on libatomic. So it should be possible. My uninformed guess is that constructs like std::atomic<HighsSplitDeque*> and std::atomic<uint64_t> are more likely to trigger the non-lock-free instructions compared to std::atomic<int> & the bool/long/float` equivalents.
Any thoughts here would be helpful.
I'll discuss this with @galabovaa, but who still uses 32-bit platforms?
Maybe it makes more sense to restrict HiGHS to 64-bit platforms.
It's actually quite common - e.g., some series of Raspberry PI's use armv7. There are lots of folks stuck on 32-bit Windows of course. And then Debian supports all sorts of exotic architectures - those don't have many users I imagine, but they do build for all their supported architecture.
I'm sure that examples of people using 32-bit exist, but we can't justify much work for people on such archaic platforms, or because Debian chooses to support all sorts of exotic architectures.
Plus std::atomic<HighsSplitDeque*> is coded that way for a reason, and we're not in a position to modify this code at present
As I say, we'll discuss it, but I can't promise anything.
That makes sense, thanks @jajhall. I just wanted to bring it up, because I couldn't find a previous discussion. For now we can document in the SciPy install docs that with GCC things will work (Python wheel redistributors must then vendor libatomic), other compilers are YMMV.
I'm still trying to wrap my head around what is actually happening, because I'm far from an expert on C++ atomics. From what I can tell, using std::atomic on data structures up to 16 bytes is guaranteed to be lock-free on pretty much all platforms, while for larger data structures that's not the case. In addition, the dependency on libatomic depends on compiler flags like -march=native being used or not (xref SO discussion).