Сравнение различных флагов компиляции для 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 выдают примерно одинаковый результат. Видимо, код в обоих случаях содержит одни и те же оптимизации компилятора. Или не содержит ни одной.
Третий вывод заключается в том, что скорость приложения не зависит от устройства на котором оно было скомпилировано. Это достаточно очевидный вывод, но я рад, что он подтвердился ещё раз. Это говорит о том, что в прошивке устройства нет каких-либо скрытых опций и оптимизаций.