статические переменные в функциях - PullRequest
4 голосов
/ 09 июля 2011

Есть ли проблема производительности с использованием статических переменных в вычислениях функций, влияет ли это на скорость выполнения функции, поскольку статические переменные инициализируются только один раз?

Вопрос для очень повторяющихся оптимизаций вызовов.

Рассмотрим этот пример

int calcme(int a, int b)
{
 static int iamstatic = 20;
 return a*iamstatic + b;
}

Причиной использования static является надежда, что iamstatic не будет помещаться в стек каждый раз, когда вызывается функция, и она предназначена для изменения в случае необходимости. (Код изменения статической переменной опущен)

Ответы [ 8 ]

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

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

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

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

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

Технически ответ - «нет», потому что стандарт C не определяет его.

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

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

Это наиболее читаемая и наиболее эффективная версия функции.

int calcme(int a, int b)
{
    return a*20 + b;
}

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

Если вы поместите константу в глобальную переменную, компилятор загрузит переменную из памяти.

Выпытаются перехитрить оптимизатор, и это почти всегда плохая идея.

Вот ваш оригинальный код, скомпилированный:

    leal    (%rdi,%rdi,4), %edi
    leal    (%rsi,%rdi,4), %eax
    ret

Это тот же код, сгенерированный return a*20 + b;,но твой код труднее читать.Обратите внимание, что статическая переменная на самом деле нигде не сохраняется, она преобразуется в непосредственный операнд (а затем уменьшение прочности еще больше уменьшает его).Точно такую ​​же производительность вы получите из следующего кода:

int calcme(int a, int b)
{
    int local = 20; // "initialized" every time the function is called
                    // yet the assembly is the same
    return a*local + b;
}
0 голосов
/ 09 июля 2011

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

  1. Если переменная хранит глобальное состояние, которое должно сохраняться при вызовах функции, она должна иметь статическую продолжительность хранения. (Обычно это вредно, но иногда это неизбежное зло или, по крайней мере, делает вещи достаточно легкими, чтобы вы готовы совершить оскорбление написания плохого кода, чтобы сэкономить много времени и средств на разработку.)
  2. Если переменная хранит данные, относящиеся к текущему вызову функции, она должна иметь продолжительность автоматического хранения (по умолчанию).
  3. Если данные принадлежат текущему контексту выполнения, но должны сохраняться после возврата функции, они должны храниться в объекте, полученном malloc.
0 голосов
/ 09 июля 2011

Если вы компилируете с оптимизацией, это зависит от ситуации. В вашем примере, iamstatic является постоянным, я думаю, скорость не изменится.

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

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

Почему бы вам не сделать простое

#define MY_CONSTANT 20

/* ... */

return a*MY_CONSTANT + b;

Может быть, компилятору известна хитрость для умножения на 20 (которую он не сможет применить, если умножить на iamstatic).

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

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

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

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