последствия для производительности глобальных переменных в с - PullRequest
5 голосов
/ 14 июля 2011

У меня есть 5 функций, которые вызываются 10000+ раз (в среднем). Все они изменяют / используют определенные переменные.

Я знаю, что иметь глобальные переменные - плохая практика. Но ради производительности, имеет ли смысл сохранять их глобальными и не передавать их, особенно, когда я делаю вызов функции много раз?

ИЛИ Я не собираюсь сильно выигрывать в плане производительности?

Ответы [ 7 ]

8 голосов
/ 14 июля 2011

Не вводите глобальные переменные / глобальное состояние для повышения производительности. Это вводит в заблуждение, вопреки всем хорошим практикам кодирования, и, как правило, не влияет на производительность (это может даже повредить).

Если вам кажется слишком дорогим передавать множество переменных, вы можете поместить их все в контекст struct и передать один указатель на struct. Таким образом, вы избегаете создания глобального состояния (даже static переменные продолжительности хранения являются глобальным состоянием), что предотвращает использование вашего кода во многих случаях. Стоимость практически равна нулю, и фактически она будет дешевле, чем глобальные переменные в независимом от позиции коде (совместно используемые библиотеки или независимые от положения исполняемые файлы).

4 голосов
/ 14 июля 2011

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

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

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

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

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

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


Редактировать: я вижу из одного из ваших комментариев, что вы все еще находитесь на стадии разработки этого проекта.

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

3 голосов
/ 14 июля 2011

статические переменные в C имеют область видимости файла, и их может быть достаточно в вашем случае - при условии, что вы можете сгруппировать свои функции в 1 файл.И для меня статические переменные на несколько порядков менее проблематичны, чем глобальные.

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

2 голосов
/ 09 февраля 2012

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

Например, при использовании типичного 8-битного компилятора микроконтроллера (HT-PICC18) стоимость установки глобальной переменной составляет две инструкции / два цикла на байт. Передача одного однобайтового параметра стоит инструкции / один цикл. Передача двух или более байтов параметров стоит два цикла на байт. Таким образом, наиболее эффективный способ передать два однобайтовых параметра - это передать один в качестве параметра и один в качестве глобального.

В компиляторе Introl для 68HC11 подпрограммы, которые имеют любые автоматические переменные или параметры, требуют пролога и эпилога из нескольких команд, которые могут быть опущены, если все переменные являются статическими и параметры передаются как глобальные переменные. Однако если подпрограмма будет использовать какие-либо локальные параметры или параметры, предельные затраты на использование локальных параметров и параметров для всего остального незначительны.

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

2 голосов
/ 14 июля 2011

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

Если ваши функции маленькие, посмотрите на их встраивание. Если они большие, велика вероятность, что размещение одного или двух слов в стеке будет иметь минимальное значение.

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

1 голос
/ 14 июля 2011

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

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

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

Надеюсь, это поможет.

0 голосов
/ 14 июля 2011

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

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

Смотрите здесь

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