4 ms·
> Better C code is often 2x faster than hand optimized assembler Only if you suck at optimising assembly. > my C memcpy with inlined and vectorized clang beat
by moonchild 3y ago
> Better C code is often 2x faster than hand optimized assembler
Only if you suck at optimising assembly.
> my C memcpy with inlined and vectorized clang beats glibc or gcc memcpy in assembler easily
1. For what workload?
2. glibc strings functions are ok, but not particularly good, ime
The advantage of compilers is economy. They can not—at least not at present—beat a good human.
- pjmlp 3y agoIt is quite easy to suck at optimizing Assembly unless we are talking about 8 and 16 bit classical CPUs. First of all, if one isn't using something like V-Tune to profile the microcode of the written Assembly, they are doing it wrong. Second, better keep up with all those opcodes.
- brucehoult 3y agoWhat is this "microcode" you speak of? "all those opcodes"? This post is about RISC-V. Also, in the near future, this is going to be the only optimised `memcpy()` you need on Applications-class (and many embedded too) RISC-V processors: memcpy: mv a3,a0 1: vsetvli a4, a2, e8,m4 # Vectors of bytes vle.v v0, (a1) # Load bytes add a1, a1, a4 # Bump pointer sub a2, a2, a4 # Decrement count vse.v v0, (a3) # Store bytes add a3, a3, a4 # Bump pointer bnez a2, 1b # Any more? ret
- pjmlp 3y agoIt can be VHDL or Verliog for the ISA, if it makes you happier. So have you validated that Assembly example works the same way across all RISC-V vendors, and memory controllers, in regards to performace?
- brucehoult 3y agoAll that exist at the moment! i.e. - THead C906 in-order single-issue core in e.g. AllWinner D1 and Bouffalo BL808 SoCs - THead C910 3-wide OoO core in THead TH1520 and Sophon SG2042 SoCs LMUL=4 (64 bytes per loop) is optimal for all the above. It is unlikely to be bad on anything. I look forward to the first shipping RVV 1.0 implementations, maybe sometime in 2024. The same code is binary compatible between RVV draft 0.7.1 (which the above implement) and the ratified RVV 1.0, and source compatible with the addition of ",ta,ma" to the `vsetvli` (sadly, a decision was made not to allow that to default in asm) As can be seen at... https://hoult.org/d1_memcpy.txt https://hoult.org/d1_memcpy.txt ... a test I ran on the Allwinner D1 two years ago. Compared to glibc memcpy() at the time, the vector version is 2-3 times faster for sizes up to 1k, then gradually slides back to equality at sizes in L2 cache and RAM where normal integer code can saturate the bus. That's a core (C906) which today is available on for example the $6 Pine64 Ox64 board.
- xoranth 3y ago> 2. glibc strings functions are ok, but not particularly good, ime Do you mean for RISC-V, or in general? (and in particular, what about x64?) What problems do they have? [Also what are in your experience better implementations?]
- moonchild 3y agoI only have experience with their amd64 code. > What problems do they have? Nothing in particular, just not particularly amazing performance. They work fine. One thing they have going for them is that they typically have separate versions for every interesting architecture feature level/set, whereas e.g. bionic only has sse code. I guess I can point at my own implementations of memset and memcmp (https://github.com/moon-chilled/fancy-memset https://github.com/moon-chilled/fancy-memset https://github.com/moon-chilled/fancy-memcmp https://github.com/moon-chilled/fancy-memcmp), both of which employ novel techniques not used by glibc; but I've not yet gotten around to doing proper benchmarks on either.
- xoranth 3y agoThank you! I'll take a look.