5 ms·
It is also useful to know that int128 is not supported as well across all architectures. For example std::atomic<int128>::is_always_lock_free is true for recent
by utopcell 6y ago
It is also useful to know that int128 is not supported as well across all architectures. For example std::atomic<int128>::is_always_lock_free is true for recent x86 architectures but not for PPCs.
- cornstalks 6y agoNot only that, it's not even supported at all on some architectures. Clang supports int128 but not on armv7-a: https://gcc.godbolt.org/z/5dKh6s https://gcc.godbolt.org/z/5dKh6s
- ehvatum 6y agoNeat! x86_64 has CMPXCHG16B. Learn something new every day.
- BruiseLee 6y agoIt has to - to mitigate ABA problem.
- eloff 6y agoDepending what you use it for. The bigger problem with it is you can't just load/store a 128 bit value without this instruction. An SSE 128bit load/store is turned into two 64 bit operations under the hood. So to actually get atomic loads and stores you need to use this very expensive compare exchange operation. That really limits the number of algorithms it's useful for.
- CyberDildonics 6y agoWhy would it? The crucial part is usually a variation of comparing and swapping a 64 bit pointer and a 64 version number at the same time. If you can do that, for most algorithms it doesn't matter much if you do two 64 bit loads to get the values. If you are out of sync your compare and swap is going to fail anyway, which is likely to be rare.
- eloff 6y agoI've personally found it limiting many times. I know the one place where I did actually end up using it, I had 128 bits of information where I had to be very careful with ordering of loads and stores and had to detect torn writes and retry. Maybe my experience is not representative, but it's something to be aware of when designing algorithms with it.
- CyberDildonics 6y agoWhy would you need to do that unless you were writing over individual 128 bit ints from one thread while reading them at the same time from another thread? There are many better ways to do something like that. Anything that writes a buffer, then makes it available atomically would work much better, or you could just use the compare and swap. There is always going to be a limit of what is atomic. At some point you have to work with a data structure meant for larger data. The cut off has to be somewhere.
- eloff 6y agoIt was the primary key index in a database using MVCC. It stored various flags and a version (transaction timestamp) and data pointer. It also stored something else that I don't recall, maybe a previous version record pointer. All packed into 128 bits. Adding a new record version required cmpxchg16b, but reading it or just updating a flag was tricky because the 64bit words only had meaning together so I had to detect torn writes and retry the read with appropriate memory barriers.
- CyberDildonics 6y agoThis means though, that you were somehow synchronizing a larger record using this technique. Maybe you were writing it in one thread, then atomically changing your 128 bit struct to make it available to other threads. Whatever else was part of your 128 bit struct could probably be part of the record instead. You could use a 64 bit address and a 64 bit version number. Looking up could be done by atomically reading the 64 bit version number only. Writing a new record would then require the compare and swap.
- ehvatum 6y agoLet’s keep 80s music out of this ;) Looks like I need to resort to ASM for visual c++. Might do.
- CyberDildonics 6y agoAre you sure about that? 128 bit compare and swap has been on x64 for two decades and ARM has it too. I thought PPC also had it. None of these (as far as I know) can actually do a 128 bit compare and swap when it straddles two cache lines however. These also aren't the same as doing actual 128 bit math operations, they are just for compare and swap.