4 ms·
The sibling comments mention the hardware specific dynamic linking in glibc that's used for function calls. But if your compiler inlines memcpy (usually for sho
by the8472 3y ago
The sibling comments mention the hardware specific dynamic linking in glibc that's used for function calls. But if your compiler inlines memcpy (usually for short, fixed-sized copies) into the binary then yes you'll have to compile it for a specific CPU to get optimal performance. But that's true for all target-dependent optimizations.
More broadly compatible routines will still work on newer CPUs, they just won yield the best performance.
It still would be nice if such central routines could just be compiled to the REP-prefixed instructions and would deliver (near-)optimal performance so we could stop worrying about that particular part.
- saagarjha 3y agoThey are, glibc already has an ERMS code path for memcpy.
- the8472 3y agoDid you miss the part about inlined calls? I was saying that if it weren't for these issues we could have them turn into a single instruction without worrying about perf.
- gpderetta 3y agoI theory the compiler could always statically inline a memcpy to a (possibly nop-padded) rep mov. Then the dynamic linker could dynamically patch the instructions to a call to an out of line function if rep mov is known not to be optimal to the actual CPU the code is running. The reverse (patching a call to memmove with a rep mov) is also possible.
- saagarjha 3y agoGenerally the compiler will not inline a memcpy if it doesn't know the size it is dealing with.
- dzaima 3y agoSome quick searching gives that FSRM is used for at least 128 bytes or so (ERMS for ≥~2048 bytes for reference); in base x86 (i.e. SSE2) that's 8 loads & 8 stores, ~62 bytes of code. At that point calling into a library function isn't too unreasonable (at the very least it could utilize AVX and cut that in half to 4 loads+4 stores, though at the cost of function call overhead & some (likely correctly-predicted) branches).
- the8472 3y agohttps://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/commit/?h=x86/asm&id=f444a5ff95dce07cf4353cbb85fc3e785019d430 https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/... Suggests that it should be usable for even shorter copies. And that's really my point. We should have One True memcpy instruction sequence that we use everywhere and stop worrying. And yet...
- dzaima 3y agoUnfortunately, we can't change the past, and seemingly in the past it wasn't worth it to have a fast One True memcpy (and perhaps to a decent extent still isn't). I'm still typing this on a Haswell CPU, which don't have FSRM (rep movsb of 16 bytes in a loop takes ~10ns=36 cycles per iteration avg). But, yeah it does seem that my 128 bytes of a quick search was wrong. (though, gcc & clang for '-march=alderlake' both never generate 'rep movsb' on '-O3'; on `-Os` gcc starts giving a rep movsb for ≥65B, clang still never does)