Пытался тут ускорить копирование памяти на ESP32-P4.
Там есть стандартный memcpy() и реализованный через SIMD, наподобие этого .
Но для самообразования решил запилить свой, нестандартный.
В datasheet на ESP32-P4 описан регистр-аккумулятор QACC, который имеет ни много ни мало - 512 бит унутре. И присутствуют ассемблерные инструкции которые напрямую загружают из памяти в этот регистр и сохраняют в память тоже напрямую. (без использования промежуточных 128битовых регистров Q0-Q7). Его и было решено использовать, вместо 4х 128 битных регистров (версия memcpy от Espressif)
Тест приближен к реальности: буфер размером 64КБ копируется 1024 раза в цикле.
Скорость копирования : ~690 МБайт в секунду. Это не быстрее, чем SIMD код от Espressif для этого же процессора, но он зато раза в 4-5 короче.
Вот код, может кому-то нужен будет когда нибудь. Длина буфера должна быть кратна 64 байтам. Выравнивание - 16 байт.
Код надо положить в файл с расширением .S и кинуть в каталог с вашим проектом.
.text
.align 2
.global p4_memcpy
.type p4_memcpy, @function
.balign 4
.option norvc
p4_memcpy:
# a0: void *store_ptr
# a1: const void *load_ptr
# a2: const int length(bytes)
# t0: счетчик циклов для аппаратного цикла
srli t0, a2, 6 # count = length / 64
esp.lp.setup 0, t0, .Lend # заряжаем наш for(i=0; i<t0; i++)
esp.ld.qacc.h.h.128.ip a1, 16 # загружаем QACC, a1 += 16
esp.ld.qacc.h.l.128.ip a1, 16 # загружаем QACC, a1 += 16
esp.ld.qacc.l.h.128.ip a1, 16 # загружаем QACC, a1 += 16
esp.ld.qacc.l.l.128.ip a1, 16 # загружаем QACC, a1 += 16
esp.st.qacc.h.h.128.ip a0, 16 # выгружаем
esp.st.qacc.h.l.128.ip a0, 16
esp.st.qacc.l.h.128.ip a0, 16
.Lend:
esp.st.qacc.l.l.128.ip a0, 16 # последняя инструкция в аппаратном цикле
ret
Использовать в своем Си++ коде так:
extern "C" void p4_memcpy(void *store_ptr, const void *load_ptr, const int length);
...
...
p4_memcpy(Dst, Src, Length_In_Bytes);
Вроде ничего не напутал.