C++ Советы по оптимизации кода на устройствах ARM
Я разрабатывал код C++ для дополненной реальности на устройствах ARM, и оптимизация кода очень важна для поддержания хорошей частоты кадров. Чтобы поднять эффективность до максимального уровня, я думаю, что важно собрать общие советы, которые облегчат жизнь компиляторам и уменьшат количество циклов программы. Любое предложение приветствуется.
1- Избегайте дорогостоящих инструкций: деление, квадратный корень, грех, кос
- Используйте логические сдвиги, чтобы разделить или умножить на 2.
- Умножьте на обратное, когда это возможно.
2. Оптимизируйте внутренние циклы "for": они являются узким местом, поэтому мы должны избегать многих вычислений внутри, особенно делений, квадратных корней.
3- Используйте справочные таблицы для некоторых математических функций (sin, cos, ...)
ПОЛЕЗНЫЕ ИНСТРУМЕНТЫ
- objdump: получает код сборки скомпилированной программы. Это позволяет сравнить две функции и проверить, действительно ли они оптимизированы.
2 ответа
Чтобы ответить на ваш вопрос об общих правилах при оптимизации кода C++ для ARM, вот несколько советов:
1) Как вы упомянули, инструкции по разделению не существует. Используйте логические сдвиги или умножьте на обратное, когда это возможно.
2) Память намного медленнее, чем загрузка процессора; используйте логические операции, чтобы избежать маленьких справочных таблиц.
3) Старайтесь записывать 32-битные за раз, чтобы наилучшим образом использовать буфер записи. Написание шорт или символов значительно замедлит код. Другими словами, быстрее логически-ИЛИ меньшие биты вместе и записать их как DWORDS.
4) Знайте о своем размере кеша L1/L2. Как правило, ARM-чипы имеют гораздо меньший кэш, чем Intel.
5) Используйте SIMD (NEON), когда это возможно. Инструкции NEON достаточно мощные и для "векторизованного" кода могут быть довольно быстрыми. Встроенные функции NEON доступны в большинстве сред C++ и могут быть почти такими же быстрыми, как и написанные вручную ASM-коды.
6) Используйте подсказку предварительной выборки в кэш (PLD) для ускорения циклического чтения. У ARM нет умной логики предварительного кэширования, как у современных чипов Intel.
7) Не доверяйте компилятору генерировать хороший код. Посмотрите на вывод ASM и перепишите горячие точки в ASM. Для битовых / байтовых манипуляций язык C не может определять вещи так эффективно, как это может быть достигнуто в ASM. ARM имеет мощные 3-операндные инструкции, мультизагрузку / сохранение и "свободные" сдвиги, которые могут превзойти то, что способен генерировать компилятор.
Лучший способ оптимизировать приложение - использовать хороший профилировщик. Всегда полезно писать код, думая об эффективности, но вы также должны избегать внесения изменений, когда вы "думаете", что код может быть медленным, что может ухудшить ситуацию, если вы не уверены на 100%.
Узнайте, где узкие места и сосредоточиться на них.
Для меня профилирование - это итеративный процесс, потому что обычно, когда вы исправляете одно узкое место, другие менее важные проявляются.
В дополнение к профилированию ПО проверьте, какой тип профилирования HW доступен. Проверьте, можете ли вы получить различные метрики HW, такие как пропуски кэша, доступ к шине памяти и т. Д. Также очень полезно знать, является ли узкая область вашей шины mem или кэша.
Недавно я задал этот похожий вопрос и получил несколько хороших ответов: Ищу слабовязкий профилировщик C++