Сравнение различных флагов компиляции для Raspberrypi

Недавно мне на глаза попалась самая первая версия Raspberry pi и я решил немного поэкспериментировать со старым железом.

Мне было интересно насколько отличается производительность библиотеки volk в зависимости от различных флагов компиляции.

arm1176jzf-s

Для начала необходимо определиться с процессором. Как известно, Raspberrypi использует system-on-the-chip (SoC) от broadcom. Это даже написано на самом процессоре: Broadcom BCM2835. Внутри этого чипа находится несколько логических компонентов:

  • ядро CPU - ARM arm1176jzf-s
  • ядро GPU - VideoCore 4

К сожалению, стандартные linux инструменты выдают совершенно неправильную информацию о процессоре, поэтому приходится смотреть маркировку прямо на плате и искать информацию в Интернете.

Согласно, спецификации arm1176jzf-s в нём нет поддержки NEON. А значит каких-то откровенных различий в производительности volk вряд стоит ожидать. Тем не менее мне захотелось докопаться до цифр и попробовать пару идей.

Опции компиляции

Итак, на основе информации о ядре, я составил два различных набора флагов:

  • export CXXFLAGS="-mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard". По-умолчанию, в Debian все флаги “-mfpu” выключены. Однако, arm1176jzf-s содержит самое базовое расширение для работы с плавающими числами - vfp. Имеет смысл его включить и посмотреть насколько изменится скорость работы программы.
  • export CXXFLAGS="". Флаги по-умолчанию.

Помимо компиляции volk с этими группами флагов я решил протестировать:

  • результат работы в Debian stretch (gcc 6.3.0)
  • результат работы в Debian buster (gcc 8.3.0)
  • результат работы скомпилированный на Raspberry pi 3, но запущенной на Raspberry pi 1

В качестве тестовой программы я выбрал перемножение комплексных чисел. Если бы был доступен NEON, то скорость этой программы была раз в 5 больше, чем при использовании обычных регистров. В данном тесте я не рассчитывал на какое-либо ускорение. Наверное, единственной причиной, по которой я выбрал именно его было то, что он наиболее часто встречается в цифровой обработке сигналов.

volk_profile -R volk_32fc_x2_dot_prod_32fc

Результаты

Результаты выполнения тестов я поместил в таблицу:

Флаги Stretch Stretch RPi3 Buster
"-mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard" 28548.9 мс 28515.9 мс 28669 мс
"" 28088 мс 28022 мс 28095.8 мс

Как видно из таблицы, особой разницы в скорости выполнения нет. Правда, есть небольшое ускорение при компиляции без каких-либо флагов. В среднем на 500 мс. Возможно, в операционной системе есть какие-то флаги по-умолчанию, которые чуть-чуть помогают.

Ещё один интересный вывод заключается в том, что различные версии GCC выдают примерно одинаковый результат. Видимо, код в обоих случаях содержит одни и те же оптимизации компилятора. Или не содержит ни одной.

Третий вывод заключается в том, что скорость приложения не зависит от устройства на котором оно было скомпилировано. Это достаточно очевидный вывод, но я рад, что он подтвердился ещё раз. Это говорит о том, что в прошивке устройства нет каких-либо скрытых опций и оптимизаций.