Скомпилировано с помощью gcc 4.8.5 и протестировано на двухъядерном 32-битном ARM Cortex-A9, все алгоритмы xxhash работают очень медленно и теряют даже реализацию crc32, независимо от размера ввода. Проверено на dev и v0.8.0, разницы не имеет. НЕОНОВАЯ дорожка активирована.
lscpu:
Флаги: half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
Кажется, что эти коды не так протестированы с 32-битной ARM?
Классическая проблема с gcc
на 32-битной ARM заключается в том, что
он не использует (по умолчанию) способность ЦП поддерживать невыровненный доступ к памяти
(что, я полагаю, A9 может)
что приводит к очень медленному доступу к памяти.
Здесь можно попробовать несколько вещей.
Со стороны библиотеки предусмотрено несколько методов доступа:
https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h#L1117
Самый агрессивный - XXH_FORCE_MEMORY_ACCESS=2
.
Это может привести к некорректной генерации двоичного файла в зависимости от других настроек и возможностей компилятора.
Но если это сработает, это, по крайней мере, даст представление о том, какой должна быть скорость.
Немного безопаснее, XXH_FORCE_MEMORY_ACCESS=1
сгенерирует правильный код.
Но компилятор должен знать, что процессор может получить доступ к невыровненным адресам памяти.
Для этого может потребоваться указать дополнительный флаг компиляции.
Например, -march=armv7a
сообщает gcc
что микросхема руки способна получить доступ к невыровненным адресам памяти,
в результате значительно улучшается генерация кода в сочетании с XXH_FORCE_MEMORY_ACCESS=1
.
(К сожалению, согласно Godbolt, этот флаг, связанный со значением по умолчанию XXH_FORCE_MEMORY_ACCESS=0
прежнему обеспечивает плохую производительность в более старой версии gcc
. В более новых версиях gcc-6
эта проблема устранена).
Не уверен, что это вариант, но clang
также имеет тенденцию генерировать лучший двоичный код для руки.
Наконец, на стороне пользователя
предполагая, что XXH_FORCE_ALIGN_CHECK=1
(https://github.com/Cyan4973/xxHash/blob/dev/xxhash.h#L1179),
обеспечение выровненного ввода (на границах 4 байта для XXH32
)
следует использовать путь кода доступа к памяти с прямым выравниванием.
Это не должно зависеть от компилятора, обнаруживающего возможности невыровненного доступа к памяти,
поскольку доступ к памяти обнаруживается, выровнено с самого начала.
XXH64
, вероятно, будет иметь низкую производительность на 32-битном arm
.
Но XXH32
должно быть в порядке.
Более новый XXH3
находится на балансе, базовый уровень должен быть в порядке,
и с поддержкой neon
ожидается, что он превзойдет XXH32
по скорости.
_edit_: фиксированное значение доступа к памяти, как подчеркнуто @ easyaspi314
Если я не ошибаюсь, правильные флаги общего назначения для этого процессора будут такими:
-O2 -fomit-frame-pointer -march=armv7-a -mfpu=neon -mthumb -munaligned-access
^duh ^saves a register ^sets arch version ^enables neon ^use thumb-2 ^force enable unaligned access
Однако, как сказал Янн, я бы также порекомендовал Clang, поскольку он имеет тенденцию генерировать лучший код, особенно с NEON.
Кроме того, вы пробовали более новую версию GCC? Бэкенды GCC ARM и AArch64 довольно посредственные, и до недавнего времени это было довольно плохо.
@ Cyan4973, кстати, XXH_FORCE_MEMORY_ACCESS=3
безопасен, 2 - лукавый.
Похоже, что цепочка инструментов неправильно включила оптимизацию компилятора. При их явном включении для сборки xxhashes вычисляются так (быстро, как) должны. Спасибо @ Cyan4973 и @ easyaspi314.
Самый полезный комментарий
Похоже, что цепочка инструментов неправильно включила оптимизацию компилятора. При их явном включении для сборки xxhashes вычисляются так (быстро, как) должны. Спасибо @ Cyan4973 и @ easyaspi314.