Re: [PATCH 0/5] RISC-V: Optimize memmove() for speed

m fally <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <CAA_fkGuOe7JZfFPdMt5zGNjr_P-bjbyXYdve6b+PNiyzOVihGQ@mail.gmail.com>
Hi Kito,

thank you for the early feedback :)
I am happy to work on another proposal based on what you suggested!

Also, a little side note: In the comments in memmove.c I wrote that the
(increased) loop-unrolling does not degrade performance for lengths <
SZREG*9.
However, this is not entirely correct as in a few cases, this does
introduce a small penalty of 1-2 instructions retired when the function is
compiled with -mno-strict-align.
In the affected cases, copied lengths were between 11 to 15 bytes for rv32
and 24 to 31 bytes for rv64 (according to my tests).
My apologies for that, I was a bit quick to write that comment and then
forgot to correct it. I'll change it along with any other feedback you may
have after finishing the review.

Best,
M

Op wo 28 mei 2025 om 11:51 schreef Kito Cheng <[email protected]>:

> Hi Fally:
>
> Thanks for your patch! I am still under review yet, I wonder if it is
> possible to just redirect to memcpy when both regions are proven not
> overlapped? I guess that may add few extra instruction count, but
> memcpy also do lots of similar optimization with many different
> extension combination as well, it would be great to just maintain one
> implementation for that pat :)
>
>
> On Mon, May 26, 2025 at 11:06 PM m fally <[email protected]> wrote:
> >
> > This patch series optimizes the RISC-V port of memmove() for speed.
> > The implementation is based on the generic port of the function,
> > since that is what is currently used when compiling newlib for RISC-V.
> >
> > In the stock implementation, an unroll-factor of 4 is used for
> > the word-copy-loop in the case where both source and destination
> > addresses are aligned on a long-boundary, and the memory areas
> > overlap non-destructively or not at all. No unrolling is done in
> > the destructive-overlap case. The proposed implementation uses an
> > unroll-factor of 9 for both overlap-cases when both addresses are
> > aligned to xlen. The unroll-factor was chosen to match memcpy() and
> > speeds up the copying-process for lengths >= 9*SZREG, while almost
> > not at all degrading performance for shorter lengths.
> >
> > If at least one address is unaligned, misaligned accesses are slow
> > or prohibited, and there are >= 2*SZREG bytes left to copy, the
> > proposed implementation first aligns the source address. Then, one
> > whole word (or doubleword for rv64) is loaded at a time and individual
> > bytes are stored back to the destination. The threshold of 2*SZREG was
> > chosen in order to keep the negative effect on shorter copies caused
> > by the additional overhead of the alignment operation low.
> >
> > Furthermore, the function now only uses fixed-width types.
> > Macros from the generic port are replaced with RISC-V-specific macros
> > and static inline functions.
> >
> >
> > The proposed implementation was tested on spike with pk for each of the
> > following configurations (compiled with gcc):
> >
> > rv32ic -mtune=thead-c906 -mstrict-align -O3
> > rv32ic -mtune=thead-c906 -mno-strict-align -O3
> > rv64ic -mtune=thead-c906 -mstrict-align -O3
> > rv64ic -mtune=thead-c906 -mno-strict-align -O3
> >
> >
> > For each configuration, the following cases were considered when
> comparing
> > the old and new implementations:
> >
> > both addresses are xlen-aligned
> > both addresses are unaligned
> > source address is xlen-aligned, destination address is not
> > destination address is xlen-aligned, source address is not
> >
> >
> > For each configuration, 65520 tests were run. In total, there were 67
> cases
> > where the new implementation was slower than the original, with a maximum
> > difference of 10 retired instructions. In 145 cases the implementations
> were
> > equally fast. In all cases where the new implementation was slower,
> copied
> > lengths were < 32 bytes.
> > In all other cases, the new implementation was faster than the original.
> >
> > Please see here for graphical comparisons between the two
> implementations:
> > https://cloud.servus.at/s/BA8ZJoPnE3nCtAK
> >
> > Below tables show the number of cases where the new implementation was
> > faster, slower, or equally fast as the current implementation, as well as
> > the max. differences in instructions retired between the implementations.
> > The graphs and tables show the differences for copied lengths between
> > 2 and 8191 bytes. For lengths < 2, old and new implementations were
> > equally fast.
> >
> > --------- BENCHMARKING RESULTS ---------
> >
> > +--------------------------------------+
> > |        rv32ic -mstrict-align         |
> > +--------------------------------------+
> > |      |Number   |Max. difference in   |
> > |      |of cases |instructions retired |
> > +------+---------+---------------------+
> > |Faster|   65496 |              -18411 |
> > +------+---------+---------------------+
> > |Slower|      13 |                  10 |
> > +------+---------+---------------------+
> > |Tied  |      11 |                     |
> > +------+---------+---------------------+
> >
> > +--------------------------------------+
> > |        rv64ic -mstrict-align         |
> > +--------------------------------------+
> > |      |Number   |Max. difference in   |
> > |      |of cases |instructions retired |
> > +------+---------+---------------------+
> > |Faster|   65509 |              -21474 |
> > +------+---------+---------------------+
> > |Slower|       6 |                   2 |
> > +------+---------+---------------------+
> > |Tied  |       5 |                     |
> > +------+---------+---------------------+
> >
> > +--------------------------------------+
> > |        rv32ic -mno-strict-align      |
> > +--------------------------------------+
> > |      |Number   |Max. difference in   |
> > |      |of cases |instructions retired |
> > +------+---------+---------------------+
> > |Faster|   65488 |               -5231 |
> > +------+---------+---------------------+
> > |Slower|      16 |                   1 |
> > +------+---------+---------------------+
> > |Tied  |      16 |                     |
> > +------+---------+---------------------+
> >
> > +--------------------------------------+
> > |        rv64ic -mno-strict-align      |
> > +--------------------------------------+
> > |      |Number   |Max. difference in   |
> > |      |of cases |instructions retired |
> > +------+---------+---------------------+
> > |Faster|   65375 |               -2609 |
> > +------+---------+---------------------+
> > |Slower|      32 |                   2 |
> > +------+---------+---------------------+
> > |Tied  |     113 |                     |
> > +------+---------+---------------------+
> >
> >
> > m fally (5):
> >   RISC-V: memmove() speed optimized: Add implementation
> >   RISC-V: memmove() speed optimized: Replace macros and use fixed-width
> >     types
> >   RISC-V: memmove() speed optimized: Add loop-unrolling
> >   RISC-V: memmove() speed optimized: Align source address
> >   newlib: Regenerate configuration files
> >
> >  newlib/Makefile.in                            |  52 ++--
> >  newlib/libc/machine/riscv/Makefile.inc        |   2 +-
> >  .../riscv/{memmove.S => memmove-asm.S}        |   0
> >  newlib/libc/machine/riscv/memmove-stub.c      |  14 --
> >  newlib/libc/machine/riscv/memmove.c           | 232 ++++++++++++++++++
> >  5 files changed, 259 insertions(+), 41 deletions(-)
> >  rename newlib/libc/machine/riscv/{memmove.S => memmove-asm.S} (100%)
> >  delete mode 100644 newlib/libc/machine/riscv/memmove-stub.c
> >  create mode 100644 newlib/libc/machine/riscv/memmove.c
> >
> > --
> > 2.49.0
> >
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.