Что быстрее для большого цикла for: вызов функции или встроенное кодирование? - PullRequest
1 голос
/ 04 мая 2010

Я запрограммировал встроенное программное обеспечение (конечно, на C), и сейчас я думаю о том, как улучшить время работы системы. Самый важный единственный модуль в моей системе - это один очень большой вложенный модуль цикла.

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

Я сделал эту функцию, которая должна вызываться намного легче и короче (но все еще работает как следует), и теперь я начал думать, что будет быстрее оторвать этот вызов функции и написать этот процесс непосредственно внутри первые две петли?

Процессор в этой системе - ARM7TDMI, частота - 55 МГц. Сама система не очень критична по времени, поэтому она не должна быть способной работать в реальном времени. Однако чем быстрее он сможет выполнять свои обязанности, тем лучше.

Также было бы быстрее использовать циклы while вместо fors? И любой совет о том, как улучшить время работы приветствуется.

-zaplec

Ответы [ 6 ]

19 голосов
/ 04 мая 2010

ПОПРОБУЙТЕ И ВИДИТЕ !!

Это почти наверняка будет иметь значение. Затраты на вызов функций, как правило, не представляют особой проблемы, но при более чем 100 000 повторений они начинают складываться.

... Но имеет ли это какое-то значение в реальной жизни - это то, на что только вы можете ответить, попробовав и рассчитав результаты.

Что касается for против while ... это не должно иметь значения, если вы не измените поведение при изменении цикла. Если сомневаетесь, заставьте ваш компилятор выплевывать ассемблерный код для обоих и сравнивайте ... или просто измените его и укажите время .

3 голосов
/ 05 мая 2010

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

Если вы не верите, что ваш компилятор много делает для оптимизации, я бы взглянул на некоторые более старые концепции оптимизации C (поиск в SO или google должен дать несколько хороших ссылок).

2 голосов
/ 05 мая 2010

Процессор ARM имеет конвейер команд (кэш). Когда процессор сталкивается с инструкцией ветвления (вызова), он должен очистить конвейер и перезагрузить, тратя, таким образом, некоторое время. Одной из целей оптимизации скорости является уменьшение количества перезагрузок в конвейер команд. Это означает сокращение инструкций ветвления.

Как другие заявили в SO, скомпилируйте ваш код с оптимизацией по скорости и профилю. Я предпочитаю также посмотреть листинг на ассемблере (либо распечатанный из компилятора, либо выведенный в отладчике). Используйте это как основу. Если вы не можете профилировать, вы можете использовать подсчет инструкций по сборке как приблизительную оценку.

Следующим шагом является уменьшение количества веток; или сколько раз берется ветвь. Развертывание циклов помогает уменьшить количество раз, которое берется ветвь. Встраивание помогает уменьшить количество веток. Прежде чем применять эти методы точной настройки, просмотрите дизайн и реализацию кода, чтобы увидеть, можно ли уменьшить количество ветвей. Например, уменьшите количество операторов if, используя булеву арифметику или Karnaugh Maps . Мой фаворит - сокращение требований и устранение кода, который не нужно выполнять.

В реализации кода перемещайте код, который не изменяется, вне циклов for или while. Некоторые циклы могут быть сведены к уравнениям (например, замена цикла сложений умножением). Кроме того, уменьшите количество итераций, задав вопрос: «Действительно ли этот цикл действительно должен выполняться много раз»).

Другой метод заключается в оптимизации для Data Oriented Design . Также проверьте эту ссылку .

Просто не забудьте установить предел для оптимизации. Именно здесь вы решаете, что дальнейшая оптимизация не будет приносить прибыли или удовлетворения клиентов. Кроме того, применяйте оптимизацию поэтапно; что позволит вам получить результат, когда ваш менеджер попросит его.

1 голос
/ 05 мая 2010

Запустите профилировщик своего кода. Если вы просто гадаете, где вы проводите свое время, вы, вероятно, ошибаетесь. Профилировщик покажет, какая функция занимает больше всего времени, и вы можете сосредоточиться на этом. Вы могли бы делать что-то в функции, что занимает больше времени, чем сам вызов функции. Вы смотрели, можете ли вы заменить плавающие операции на целочисленные или целочисленные математические на сдвиги? Вы можете потратить много времени на игры с вещами, которые не имеют большого значения. Запустите профилировщик своего кода и убедитесь, что изменения, которые вы изменяете, будут иметь значение.

0 голосов
/ 05 мая 2010

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

0 голосов
/ 05 мая 2010

Для функции против встроенного, к сожалению, нет простого ответа. То есть это зависит. См. этот FAQ . Что касается «за» и «пока», я бы не подумал, что есть существенная разница в производительности.

...