5 ms·
> On x86_64, on modern micro-archs, "rep stos[bwdq]" and "rep movs[bwdq]". I bet that, in modern binaries, memcpy/memset call sites are actually place holders f
by brucehoult 3y ago
> On x86_64, on modern micro-archs, "rep stos[bwdq]" and "rep movs[bwdq]". I bet that, in modern binaries, memcpy/memset call sites are actually place holders for such instructions
You'd lose that bet.
An optimised memcpy/memset using normal instructions is typically much faster than "rep movsb" (etc).
It is however a lot of code, so "rep movsb" has its place in low-memory low-performance settings.
> hardware optimized and accelerated short and big memcpy/memset
Classic CISC fallacy: if they made an instruction to do it then it must be the fastest way to do it.
Nope. That wasn't even the intention of the designers of things such as the VAX and 8086. Those complex instructions were provided to let assembly language programmers write code a little more quickly, even if it ran a little more slowly, because according to the 1970's "Software crisis" theory computers were rapidly getting cheaper, but programmers were scarce and expensive, and vast amounts of software needed to be written.
The whole key was to make (assembly language) programmers more productive, and if that made the code slightly inefficient that didn't matter because you could easily buy an extra computer or two, and anyway next year's model will be faster.
- adrian_b 3y agoSee my other reply for more details. An optimized memcpy/memset using normal instructions is much faster than "rep movsb"/"rep stosb" only in certain ranges of the copy/fill size (on all modern Intel/AMD CPUs). Using normal instructions for memcpy can have around a double speed for copy sizes under 1 kB, but it is always slower for very big copies. For an optimized memcpy/memset, one must choose between normal instructions and "rep movsb"/"rep stosb" for each copy/fill, depending on the CPU model and on the copy/fill size.
- brucehoult 3y agoGosh that's complex. On all RISC-V CPUs I have currently access to with the pre-ratification RVV 0.7.1, the simple 9 instruction memcpy function shown by camel-cdr is faster than any other kind of memcpy (simple byte-by-byte loop with no decision overhead, or complex glibc function) at EVERY sensible size. These range from the C906 core found in Linux-capable boards costing $6 or $10 (Pine64 Ox64, Sipeed M1s, Milk-V Duo), the the C920 OoO cores in the 64 core SOPHON SG2042. Here are some numbers I ran on a 1 GHz C906 over two years ago: https://hoult.org/d1_memcpy.txt https://hoult.org/d1_memcpy.txt The short RVV function has absolutely constant execution time out to n=64 AND this time is 40% less than standard memcpy even at size 0 or 1 byte, and from 8 to 128 bytes it is at least 3x faster. A 1.8x advantage is maintained for any size that fits in L1 cache, then after that both are able to saturate the memory bus. Remember, this is a low-end in-order core (similar to Cortex-A35) designed in 2019, with only 128 bit vector registers and ALU. But the same thing applies on newer, higher-performance cores.
- camel-cdr 3y agoI found that for randomly aligned data, memcpy that aligns the destination pointer to vlenb is more stable when copying more data, on my MangoPi MQ Pro. (https://i.postimg.cc/Z4r29hnM/1.png https://i.postimg.cc/Z4r29hnM/1.png) I've got the best results from this code: memcpy_rvv_align_dest_hybrid: mv a3, a0 csrr t0, vlenb slli t1, t0, 8 # skip costly division for more values bltu a2, t1, 2f # len < vlen sub t1, zero, a0 remu t1, t1, t0 # align = (-dest) % vlen vsetvli t0, t1, e8, m8, ta, ma # align dest to vlen 1: vle8.v v0, (a1) add a1, a1, t0 sub a2, a2, t0 vse8.v v0, (a3) add a3, a3, t0 2: vsetvli t0, a2, e8, m8, ta, ma bnez a2, 1b ret
- camel-cdr 3y agoI'd actually expect the final version to also incorporate the Zihintntl extension, which would allow the load/stores to bypass the cache, since the equivalent non temporal instruction on x86 are also the fastest.
- brucehoult 3y agoOMG you've bloated a 9 instruction function to 15 instructions!!!! Well, ok, scalar optimised memcpy() gets into hundreds of instructions. Your result may well be hardware dependent. That's the kind of thing that you kind of have to wait for hardware to appear to actually know (or be in the team designing the hardware). Just how much faster is it on C906? And does the same happen on C910?
- icelusxl 3y ago"rep stosb" has been optimized since Ivy Bridge CPUs. > Beginning with processors based on Ivy Bridge microarchitecture, REP string operation using MOVSB and STOSB can provide both flexible and high-performance REP string operations for software in common situations like memory copy and set operations. > Beginning with processors based on Ice Lake Client microarchitecture, REP MOVSB performance of short operations is enhanced. The enhancement applies to string lengths between 1 and 128 bytes long. * https://www-ssl.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html https://www-ssl.intel.com/content/www/us/en/architecture-and... * https://stackoverflow.com/a/33485055 https://stackoverflow.com/a/33485055