Going faster than memcpy
Как обогнать memcpy
Профилируя Shadesmar, увидел: при больших (>512 КБ) сообщениях 97 % времени уходит на memcpy
между процессной и разделяемой памятью. Решил ускорить копирование.
Разбор memcpy
perf
показал:
__memmove_avx_unaligned_erms
— это memcpy
через memmove
, AVX, 32 байта за раз, поддержка не выровненных блоков и ERMS (железный цикл REP MOVSB
).
memmove
выбран, т.к. допускает перекрытие.- Для <4 КБ используется SSE2, иначе —
REP MOVSB
+ AVX. - Не-временные (
NT
) инструкции иprefetcht0
уменьшают кэш-промахи.
Способ 1: простой REP MOVSB
void _rep_movsb(void *d, const void *s, size_t n) {
asm volatile("rep movsb"
: "=D"(d), "=S"(s), "=c"(n)
: "0"(d), "1"(s), "2"(n)
: "memory");
}
Тот же цикл, что и в glibc
, но без лишней логики.
Комментарии (63)
- Часть выгоды даёт отказ от лишнего копирования: часто данные можно использовать на месте.
- Несколько участников отмечают, что без контроля кэшей и правильной сериализации бенчмарки теряют смысл.
- График в конце вызывает сомнения: скачки пропускной способности выглядят неправдоподобно.
- Для IPC обсуждают zero-copy через размещение данных сразу в shared memory (Iceoryx, Boost.Interprocess, DPDK).
- Большинство сходится к выводу: для обычных задач лучше довериться стандартному
memcpy
/std::memcpy
, особенно в glibc.