Какие шаги / стратегия для анализа и улучшения производительности встроенной системы - PullRequest
5 голосов
/ 06 августа 2010

Я разобью этот вопрос на подвопросы.Я смущен, если я должен задать их отдельно или в одном вопросе.Поэтому я просто остановлюсь на одном вопросе SO.

  1. Каковы обычно этапы анализа и улучшения производительности приложений на C?

  2. если я занимаюсь разработкой для встраиваемой системы, меняются ли шаги?

  3. Какие есть инструменты, которые могут мне помочь?

Недавно мне дализадача повысить производительность нашего продукта на платформе ARM11.Я относительно новичок в этой области встраиваемых систем, и мне нужны гуру, чтобы помочь мне.

Ответы [ 6 ]

4 голосов
/ 06 августа 2010

Простая смена компиляторов может повысить производительность C для одного и того же исходного кода во много раз. За последние годы GCC не обязательно улучшил производительность, так как для некоторых программ gcc 3.x производит более жесткий код, чем 4.x. Когда у меня был доступ к инструментам, компилятор ARM создавал значительно лучший код, чем gcc. Целых в 3 или 4 раза быстрее. LLVM догнал GCC 4.x, и я подозреваю, что пропустит gcc с точки зрения производительности и общего использования для кросс-компиляции встроенного кода. Попробуйте разные версии gcc, 3.x и 4.x, если вы используете gcc. Компилятор Metaware и оружие adt бегали по кругу вокруг gcc3.x, gcc3.x будет запускать gcc4.xa за свои деньги с кодом arm, для кода с большим пальцем gcc4.x лучше и для thumb2 (который к вам не относится) также gcc4.x лучше. Помните, я не сказал ни слова об изменении одной строки кода (пока).

LLVM способен полностью оптимизировать программу в дополнение к бесконечно большему количеству ручек настройки, чем у gcc. Несмотря на то, что сгенерированный код (версия 27) только догоняет текущий gcc 4.x по производительности для нескольких программ, которые я пробовал. И я не пробовал n факторального числа комбинаций оптимизации (оптимизировать на этапе компиляции, разные параметры для каждого файла, или объединить два файла или три файла или все файлы и оптимизировать эти пакеты, моя теория состоит в том, чтобы не оптимизировать C на bc шаги, свяжите все bc вместе, затем сделайте один проход оптимизации для всей программы, разрешите оптимизацию по умолчанию, когда llc доставит ее к цели).

Точно так же простое знание вашего компилятора и оптимизаций может значительно улучшить производительность кода без необходимости что-либо менять. У вас есть ARM11 arr, который вы компилируете для arm11 или generic arm? Вы можете получить от нескольких до десятка процентов, указав компилятору, в частности, какая архитектура / семейство (например, armv6) по сравнению с универсальным armv4 (ARM7), который часто выбирается по умолчанию. Умение использовать -O2 или -O3, если вы смелы.

Часто это не так, но переход в режим большого пальца может повысить производительность для определенных платформ. Не относится к вам, но продвижение gameboy - отличный пример, загруженный 16-битными шинами с ненулевым состоянием ожидания. У Thumb несколько процентов накладных расходов, потому что для выполнения той же задачи требуется больше инструкций, но за счет увеличения времени выборки и использования некоторых функций последовательного чтения кода большого пальца gba можно выполнить значительно быстрее, чем код руки для тот же исходный код.

с arm11 у вас, вероятно, есть кэш L1 и, возможно, L2, они включены? Они настроены? У вас есть mmu и кешируется ли ваша интенсивная память? или вы работаете с нулевой памятью состояния ожидания и вам не нужен кеш и следует его отключить? В дополнение к тому, что вы не понимаете, что вы можете взять один и тот же исходный код и заставить его работать во много раз быстрее, изменяя компиляторы или опции, люди часто не понимают, что когда вы используете кеш, просто добавляете один или несколько nops в ваш стартовый код ( в качестве хитрости, чтобы отрегулировать, где код помещается в память на одно, два, несколько слов), вы можете изменить скорость выполнения кода на целых 10–20 процентов. Где эти строки чтения кэша попадают в интенсивно используемые функции / циклы, имеет большое значение. Даже сохранение одной прочитанной строки кэша путем настройки места расположения кода заметно (например, сокращение от 3 до 2 или от 2 до 1).

Зная вашу архитектуру, процессор и окружение памяти - вот где начнется настройка, если таковая будет.Большинство библиотек C, если вы достаточно высокого уровня, чтобы использовать одну из них (я часто не использую библиотеку C, поскольку я работаю без операционной системы и с очень ограниченными ресурсами) как в своем коде C, так и иногда добавляют некоторый ассемблер для создания процедур с узким местом, таких как memcpy,намного быстрее.Если ваши программы работают на выровненных 32 или даже лучше 64-битных адресах, и вы настраиваете, даже если это означает использование нескольких байтов большего объема памяти для каждой структуры / массива / memcpy, чтобы быть целым кратным 32-битным или 64-битным, вы увидитезаметные улучшения (если ваш код использует структуры или копирует данные другими способами).В дополнение к выравниванию по размеру ваших структур (если вы их используете, я, конечно, не со встроенным кодом), даже если вы тратите память, выравнивая элементы, рассмотрите возможность использования 32-битных целых чисел для каждого элемента вместо байтов или полуслов.В зависимости от вашей системы памяти это может помочь (это может повредить слишком кстати).Как и в приведенном выше примере GBA, в котором рассматриваются конкретные функции, которые, как вы знаете, с помощью профилирования или интуиции не реализуются таким образом, чтобы использовать преимущества вашего процессора, платформы или библиотек, вы можете захотеть обратиться к ассемблеру либо с нуля, либо с самого начала компилируя из Cзатем разборка и ручной тюнинг.Memcpy - хороший пример того, что вы можете знать производительность памяти вашей системы и можете создать свой собственный memcpy специально для выровненных данных, копируя 64 или 128 или более битов на инструкцию.

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

Компилятор должен записывать и удалять регистры, чтобы выполнять вызовы функций, плюс если вы используете локальные переменные, может потребоваться кадр стека, поэтому вызовы функций дороги, но в то же время, в зависимости от кодавнутри функции, которая теперь увеличилась в размере, избегая функций, вы можете создать проблему, которую пытались избежать, исключая регистры для их повторного использования.Даже одна строка кода на C может сделать разницу между всеми переменными в функциях, подходящими в регистрах, к необходимости начинать исключать группу регистров.Для функций или сегментов кода, которые, как вы знаете, вам нужно некоторое повышение производительности, компилируйте и разбирайте (и посмотрите на использование регистров, как часто он выбирает память или записывает в память).Вы можете и найдете места, где вам нужно взять хорошо используемый цикл и сделать его собственной функцией, даже если вызов функции имеет штраф, потому что благодаря этому компилятор может лучше оптимизировать цикл, а не исключать / повторно использовать регистры, и вы получаетеобщий чистый доход.Даже одна дополнительная инструкция в цикле, которая повторяется сотни раз, является измеримым ударом по производительности.

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

Большинство наборов команд не имеют функции деления.Старайтесь не использовать деления или по модулю в своем коде настолько, насколько это возможно, поскольку они снижают производительность.Естественно, это не относится к полномочиям двух, чтобы спасти компилятор и мысленно избегать делений, а по модулю стараются использовать сдвиги и и.Мультяшки проще и чаще встречаются в наборах команд, но все же стоят дорого.Это хороший пример написания ассемблера для умножения, вместо того, чтобы делать это на C-компиляторе.Умножение рычага составляет 32 бита * 32 бита = 32 бита, поэтому для точной математики без переполнения необходимо добавить дополнительный код C, обернутый вокруг умножения, если вы уже знаете, что не переполнитесь, запишите регистры для вызова функции и выполните умножение вассемблер (для рычага).

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


float a,b;

...

a = b * 7.0;

Остальная часть проблемы заключается не в понимании точности с плавающей запятой и в том, насколько хорошими или плохими являются библиотеки C, просто пытающиеся получить ваши константы вФорма с плавающей точкой.Опять же, float - это еще одно долгое обсуждение проблем с производительностью.

Я - продукт Майкла Абраша (у меня на самом деле есть печатная копия дзен на ассемблере), и нижняя строка - время вашего кода.Придумайте точный способ определения времени кода, вы можете подумать, что знаете, где находятся узкие места, и вы можете думать, что знаете свою архитектуру, но пробуете разные вещи, даже если считаете, что они ошибочны, и рассчитывая их, вы можете найти и в конечном итоге придетсявыяснить ошибку в вашем мышлении.Добавление nops для начала. S в качестве заключительного шага настройки является хорошим примером этого, вся другая работа, которую вы проделали для повышения производительности, может быть мгновенно стерта из-за отсутствия хорошего выравнивания с кешем, это также означает реорганизацию функций внутри вашегоИсходный код, так что они приземляются в разных местах в двоичном изображении.Я видел скачки скорости на 10-20 процентов в результате выравнивания строк кэша.

1 голос
/ 06 августа 2010

Мой опыт.

  1. Вызовы функций медленные, устраняются с помощью макросов или встроенных методов. Посмотрите на список дизассемблера, чтобы увидеть.
  2. Если вы используете GCC, пометьте оптимизированные разделы #pragma GCC optimize("O3") или скомпилируйте их отдельно.
  3. Играйте с различными комбинациями применения встроенного атрибута (в основном, найдите баланс между размером и скоростью).
1 голос
/ 06 августа 2010

Уф !! Довольно большой вопрос!

Каковы обычно шаги к анализировать и улучшать показатели С приложения?

Как и другие статические анализаторы кода, упомянутые здесь, существует довольно дешевая версия под названием PC-Lint , которая существует уже много лет. Иногда выдает много ошибок и предупреждений для одной ошибки, но к концу вы будете счастливы и узнаете больше о C / C ++ из-за этого.

Со всеми анализаторами кода некоторые проблемы могут быть более структурными для кода, поэтому лучше начинать анализировать его с первого дня кодирования; Выполнение анализа на старом программном обеспечении может затмить вас проблемами, которые могут занять некоторое время, лучше всего поддерживать их в чистоте с самого начала.

Но анализаторы кода не улавливают все логические ошибки, т. Е. Не делают того, что вы хотите! Лучше всего это сделать сначала с помощью анализа кода, а затем тестирования. Производительность часто повышается за счет того, что алгоритмы стараются сделать как можно более простыми, держать инструкции в циклах плотными, возможно, развернуть циклы (это может сделать оптимизация вашего компилятора), использовать быстрые кэши при доступе к данным, которые получают медленно.

Обзоры кода могут вызвать много вопросов от глаз других людей, смотрящих на него. Не набирайте слишком много людей, старайтесь по возможности привлечь еще 3 человек, иногда начинающие разработчики задают самые проницательные вопросы, такие как «почему мы это делаем?».

Тестирование можно условно разделить на два раздела: автоматический и ручной. Автоматизированное тестирование требует усилий по созданию обработчиков тестов для функций / модулей, но после запуска их можно запускать снова и снова очень быстро. Ручное тестирование требует планирования, самодисциплины, чтобы выполнить их все в соответствии с требованиями, воображения, чтобы придумать сценарии, которые могут ухудшить производительность, и вы должны быть наблюдательны (возможно, вы прошли тест, но «трассировка объема» имеет некоторую аномалию до / после теста).

"Измените ли эти шаги, если я разработка для встроенной системы? "

Анализ производительности может быть разным для встраиваемых систем и систем приложений; с очень широкой кистью, которая теперь «встраивается», зависит от того, насколько аппаратно вы ориентированы. Это можно сделать с помощью профилировщиков. Если вам нужен более дешевый и дешевый метод, используйте тестовые выходные выводы для измерения фрагментов кода или измерьте их с помощью точек останова на симуляторах, которые поставляются со средой разработки.

Убедитесь, что измеряется не только типичная длина задачи, но и максимальная, поскольку именно здесь одна задача может начать мешать другим задачам, а запланированные задачи не будут выполнены вовремя.

Какие есть инструменты, которые могут помогите мне?

Симуляторы в IDE, инструменты статического анализа, инструменты динамического анализа, но больше всего вы и другие люди правильно выполняете требования, достойный обзор (кода и тестирование) и тщательное тестирование (автоматическое и ручное).

Удачи!

1 голос
/ 06 августа 2010
  1. Проверка кода:

    Что такое хорошие методы проверки кода?

    Статический и динамический анализ кода.

    Инструменты для статического анализа: Воробей, Предотвращение, Klockworks

    Инструменты для динамического анализа: Valgrind , Очистка

    Gprof позволяет узнать, где ваша программа проводила свое время и какие функции вызывали какие другие функции во время ее выполнения.

  2. Шаги такие же

  3. Помимо пункта 1, есть такие инструменты, как memcheck и т. Д. Существует большой список здесь в зависимости от платформы

0 голосов
/ 06 августа 2010

В ближайшее время на этот вопрос сложно ответить, поскольку были предложены различные методы, такие как блок-схема и диаграмма состояний, поэтому вы можете взглянуть на некоторые заголовки:

Архитектура ARM System-on-Chip, 2-е издание - Стив Фербер

Руководство разработчика систем ARM - Проектирование и оптимизация системного программного обеспечения - Эндрю Н. Слосс, Доминик Саймс, Крис Райт и Джон Рейфилд

Полное руководство по ARM Cortex-M3 - Джозеф Ю

C Программирование для встраиваемых систем - Кирк Зурелл

Embedded C - Майкл Дж. Понт

Программирование встроенных систем на C и C ++ - Майкл Барр

Учебник по встроенному программному обеспечению - Дэвид Э, Саймон

Встраиваемые микропроцессорные системы, 3-е издание - Start Ball

Глобальная спецификация и проверка встраиваемых систем - интеграция гетерогенных компонентов --G. Николеску и А.А Джеррая

Встраиваемые системы: моделирование, технологии и приложения - Gunter Hommel & Sheng Huanye

Встроенные системы и компьютерная архитектура - Грэм Уилсон

Проектирование встроенного оборудования - Джон Кацулис

0 голосов
/ 06 августа 2010
  1. Вы должны использовать профилировщик. Это поможет вам определить узкие места вашего приложения. Затем сосредоточьтесь на улучшении функций, в которых вы проводите больше всего времени, и тех, которые вы вызываете чаще всего. Повторяйте эту процедуру, пока не будете удовлетворены производительностью вашего приложения.

  2. Нет, не делают.

  3. В зависимости от платформы, на которую вы разрабатываете:

    Windows: AMD Code Analyst, VTune, Sleepy

    Linux: valgrind / callgrind / cachegrind

    Mac: профилировщик Xcode довольно хорош.

Попробуйте найти профилировщик для архитектуры, с которой вы на самом деле работаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...