2012-01-27 4 views
2

В локальной области (как функции), приведенные эти 4 примера:Есть ли разница в производительности с этими типами инициализации переменных?

(1)

int x; 
int y; 
// code... 
x = 4; 
y = 5; 

(2)

int x = 4; 
int y = 5; 
// code... 

(3)

// code... 
int x = 4; 
// code... 
int y = 5; 

(4)

// any other possibility 

Существует некоторая разница в производительности в форме, которую я объявляю и инициирую свои переменные, или скомпилируйте ее для меня?

Редактировать

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

func(){ 
    int x,y,z,w; 
    long bla,ble; 
    MYTYPE weeee; 
    // more declarations.. 
    //code.. 
} 

Но я не знал почему.

+0

Вы не можете делать # 3 в C, только на C++. – dasblinkenlight

+0

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

+5

@dasblinkenlight С C99 вы действительно можете. – unwind

ответ

1

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

Я могу гарантировать, что это чистая чепуха. Люди, делающие такие заявления, понятия не имеют, как код C переводится в машинный код.

Я был бы очень удивлен, если бы какой-либо из ваших 3-х примеров дал другой машинный код.


Однако существует особый случай: если бы переменные были объявлены как «глобалов» или статические, то они будут иметь статическую продолжительность хранения. И тогда они будут инициализированы до вызова main(). Все globals/statics, которые явно не инициализированы программистом, установлены на ноль. Таким образом, в этом случае, ваш пример 1) был бы медленнее:

int x; /* global variable, no explicit init so it will get set to 
      zero before main() is called */ 
... 
x = 4; // variable gets set a second time, elsewhere, in "runtime" 

медленнее, чем

int x = 4; // global variable, gets initialized before main() is called 

Разница в производительности между этими двумя, однако, скорее всего, только одна инструкция CPU, так что в 99,9% все приложения это не имеет значения.

0

Отсутствие универсальной предсказуемой разницы в производительности.

1

Если ни один из блоков // code не касается x и y, маловероятно, чтобы вы столкнулись с ощутимой разницей в производительности между этими параметрами.

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

+0

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

0

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

+0

Почему? Это не имеет смысла. Можете ли вы привести пример любого немого компилятора в истории, где второй пример привел к ускорению машинного кода? – Lundin

+0

Я не знаю об историческом компиляторе, но я думаю, что первый код сделает что-то вроде 'sub rsp, 8' ...' mov [rsp + 4], 4' 'mov [rsp], 5' , а второй сделает что-то вроде 'push 0x00040005' – asaelr

+0

Я сомневаюсь в этом. Я думаю, что любой случай приведет к тому, что значения 4, 5 будут сохранены непосредственно либо в регистре CPU, либо в стеке. – Lundin

3

C ничего не говорит о спектаклях.

(C99, 5.1.2.3p1) «Семантические описания в этом международном стандарте описывают поведение абстрактной машины, в которой вопросы оптимизации не имеют значения».

Это зависит от реализации, но любой хороший компилятор, скорее всего, производит тот же код.

0

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

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

1

1) Там было бы - в отладочном. Компилятор должен позаботиться о вас в выпуске.

2) Вы можете одобрить это для удобства чтения. Компилятор может «стереть» постоянную ценность.

3) Это может иметь значение. Локальные объявления часто бывают лучше, но это более важно в C++, где фактические конструкторы выполняют определенную работу. Иногда вы можете измерить разницу, если большой объект выведен из цикла (но ваш компилятор должен сделать это для вас).

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

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

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

Попробуйте провести сравнительный анализ и профилирование реального мира. Глядя на asm (как сказал Aix), также может помочь.

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

1

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

func(){ 
    int x,y,z,w; 
    long bla,ble; 
    MYTYPE weeee; 
    // more declarations.. 
    //code.. 
} 

Нет, единственная причина этого в том, что в начале C вы имели поместить все объявления перед кодом в функции.

Это правило было изменено в конце прошлого века.

Смежные вопросы