Форум программистов, компьютерный форум CyberForum.ru

Соптимизирует ли (любой) компилятор такой код? - C++

Восстановить пароль Регистрация
 
#pragma
Временно недоступен
 Аватар для #pragma
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
23.09.2012, 22:26     Соптимизирует ли (любой) компилятор такой код? #1
Вопрос знатокам: нужно ли выносить за цикл создание переменной, или любой компилятор сделает оптимизацию и переменная не будет пересоздаваться? Где-то была тема как раз об этом, про фигурные скобки в С++ и области видимости, но я не смог её найти..
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 // intermediate planes 
 CVector3D intermediatePoints[4]; 
 for(int i = 0; i < intermediates; ++i) 
 { 
    float t = (i+1.0)/(intermediates+1.0); // Вот это место
 
    for(int j = 0; j < 4; ++j) 
       intermediatePoints[j] = nearPoints[j]*t + farPoints[j]*(1.0-t); 
 
 
       glBegin(GL_POLYGON); 
           glVertex3fv(&intermediatePoints[0].X); 
           glVertex3fv(&intermediatePoints[1].X); 
           glVertex3fv(&intermediatePoints[2].X); 
           glVertex3fv(&intermediatePoints[3].X); 
       glEnd(); 
 }
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Kgfq
74 / 37 / 2
Регистрация: 23.09.2012
Сообщений: 408
23.09.2012, 22:33     Соптимизирует ли (любой) компилятор такой код? #2
#pragma, 100% не знаю, но это плохой стиль - полагаться на компилер. Лучше полагаться на себя.
#pragma
Временно недоступен
 Аватар для #pragma
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
23.09.2012, 22:37  [ТС]     Соптимизирует ли (любой) компилятор такой код? #3
Цитата Сообщение от Kgfq Посмотреть сообщение
#pragma, 100% не знаю, но это плохой стиль - полагаться на компилер. Лучше полагаться на себя.
Я полностью согласен, исходники не мои, поэтому хотел спросить у знающих людей

о
Я вообще-то поиграть собирался в это http://www.wildfiregames.com/0ad/ а оказалось, что игра жутко тормозит на моей машине (вроде должна была пойти, хз), ну и стало интересно, как выглядят исходники. Там очень часто встречаются конструкции подобного рода, вот и подумал: хоть и не поиграю, так может польза какая будет с этого.
I.M.
 Аватар для I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
23.09.2012, 22:45     Соптимизирует ли (любой) компилятор такой код? #4
На всяких олимпиадных задачках нам говорили, что в циклах лучше вообще переменных не создавать. Причем не важно какого типа - стандартного или своего.
Для повышения читаемости кода, напротив, рекомендуют минимизировать область видимости.
Т.е. то, как писать, зависит от того, зачем и для чего это пишется.
А вообще такие ситуации современные компиляторы разруливают достаточно успешно. И выносят за цикл все, что нужно.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
23.09.2012, 23:03     Соптимизирует ли (любой) компилятор такой код? #5
С большой вероятностью накладных расходов на создание такой переменной не будет. Даже при отключённой оптимизации.
#pragma
Временно недоступен
 Аватар для #pragma
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
23.09.2012, 23:06  [ТС]     Соптимизирует ли (любой) компилятор такой код? #6
Цитата Сообщение от grizlik78 Посмотреть сообщение
С большой вероятностью накладных расходов на создание такой переменной не будет. Даже при отключённой оптимизации.
А если там повсюду такие конструкции, это что-то меняет (и ещё функция может использоваться много раз)? Видимо, без профилирования тут не обойтись..
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
23.09.2012, 23:11     Соптимизирует ли (любой) компилятор такой код? #7
Цитата Сообщение от #pragma Посмотреть сообщение
А если там повсюду такие конструкции, это что-то меняет?
Нет. Под автоматические переменные компиляторы обычно резервируют место в стеке ещё до начала циклов, где-то в начале функции. Причём само резервирование представляет собой одну арифметическую операцию.

Добавлено через 54 секунды
Цитата Сообщение от #pragma Посмотреть сообщение
Видимо, без профилирования тут не обойтись..
В данном случае надёжнее изучить ассемблерный листинг.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
23.09.2012, 23:16     Соптимизирует ли (любой) компилятор такой код? #8
Цитата Сообщение от #pragma Посмотреть сообщение
Видимо, без профилирования тут не обойтись..
без профилирования вообще не стоит начинать думать об оптимизации
а то превратив код в нечитаемый можно соптимизировать 5%, когда рядом будет действительно дыра
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16827 / 5248 / 321
Регистрация: 30.03.2009
Сообщений: 14,129
Записей в блоге: 26
24.09.2012, 00:13     Соптимизирует ли (любой) компилятор такой код? #9
Никаких дополнительных накладных расходов на "создание" переменной внутри цикла нет. AzaKendler уже как-то задавался похожим вопросом. Там всё шло без привязки к лексическим блокам и т.п., но суть в общем-то одна и та же. Далее кидаю ссылки с моими ответами, где основная суть, ну полезно прочитать всю тему, хоть там и много букв

[C++] Взятие адреса конструктора. Физическое время существование объекта.
[C++] Взятие адреса конструктора. Физическое время существование объекта.
[C++] Взятие адреса конструктора. Физическое время существование объекта.

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

C
void func (void)
{
  int x, y;
  ...
  {
    /* "x" используем только в данном блоке */
  }
  ...
  {
    /* "y" используем только в данном блоке */
  }
  ...
}
В этом примере будет отведено две ячейки памяти под переменные x и y.

А если рассмотреть случай с объявлением переменных внутри блоков:

C
void func (void)
{
  ...
  {
    int x;
    ...
  }
  ...
  {
    int y;
    ...
  }
  ...
}
то в этом случае по достижении закрывающей фигурной скобки первого блока компилятор освободит ячейку памяти, отведённую под переменную "x", а по достижении открывающей фигурной скобки второго блока эту ячейку памяти переиспользует для переменной "y". Таким образом мы имеем две локальные переменные, про которые программист явно указал, что их времена жизни не пересекаются, а потому компилятор использует для них одну и ту же ячейку памяти

Однако современные компиляторы в реальности даже в первом примере для переменных "x" и "y" сумеют заиспользовать одну и ту же ячейку памяти или регистр. Потому как оптимизации в современных компиляторах довольно-таки умные. Но скорее всего будет ряд сложных случаев, когда компилятор не сумеет с этим справиться. В основном это касается случаев, когда аггрегатные переменные (массивы, структуры, классы) распределены в память. Из-за того, что при работе с полями идёт сложная работа с разными подчастями переменной, то полноценный анализ кода компилятором оказывается дорогим с точки зрения времени компиляции и потребляемой компилятором памяти. Поэтому такие анализы в компиляторах сильно упрощают.

Как итог можно сказать следующее. Если время жизни переменной реально ограничивается каким-то лексическим блоком, то переменную лучше объявить в блоке. Помимо того, что это улучшает читаемость кода, это упрощает работу компилятора, а потому в каких-то случаях (особенно после того, как сделали много inline-подстановок) это может положительно повлиять на скорость кода. Навскидку мне кажется, что для Си++ эффект будет больше, чем для Си, потому как в Си++ львиная доля библиотечной поддержки реализована в виде коротеньких шаблонных функций или inline-методов, а потому из-за массового inline код отдельно взятой процедуры становится сложным
#pragma
Временно недоступен
 Аватар для #pragma
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
24.09.2012, 00:17  [ТС]     Соптимизирует ли (любой) компилятор такой код? #10
Цитата Сообщение от Evg Посмотреть сообщение
Никаких дополнительных накладных расходов на "создание" переменной внутри цикла нет. AzaKendler уже как-то задавался похожим вопросом. Там всё шло без привязки к лексическим блокам и т.п., но суть в общем-то одна и та же. Далее кидаю ссылки с моими ответами, где основная суть, ну полезно прочитать всю тему, хоть там и много букв
Прочитал. Немного непонятно, почему накладных расходов нет, иначе зачем тогда лексические блоки, о которых ты сам и писал в той теме, где говорилось, что в С++ нет явного управления памятью для объектов. И поэтому, якобы рекомендуется ограничивать область видимости.
Ещё помню, что ты писал, что пока не закончится выполнение цикла, все эти созданные переменные висят в стеке. Жаль, не могу найти тему(

UPD: пока писал, ты написал дополнение, в-общем, примерно понятно теперь, в данном случае (переменные простые) лучше положиться на компилятор.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16827 / 5248 / 321
Регистрация: 30.03.2009
Сообщений: 14,129
Записей в блоге: 26
24.09.2012, 09:15     Соптимизирует ли (любой) компилятор такой код? #11
Цитата Сообщение от #pragma Посмотреть сообщение
иначе зачем тогда лексические блоки
Когда изобретали язык Си, в первую очередь заботились о производительности кода, а не о красоте его написания. Компиляторы в те времена были очень слабые (т.к. памяти было мало), а потому возможность ограничивать время жизни переменной диктовалось в первую очередь попытками ручных "указаний" компилятору о том, что и где можно сэкономить

Добавлено через 26 минут
Цитата Сообщение от Evg Посмотреть сообщение
Если время жизни переменной реально ограничивается каким-то лексическим блоком, то переменную лучше объявить в блоке
Но при этом надо учитывать следующее. Если мы работаем с переменной типа "класс" или "структура" в Си++, то надо учитывать, как работают конструктор и деструктор. Потому как для переменной, созданной внутри лексического блока, конструктор будет вызываться, грубо говоря, при каждом достижении открывающей фигурной скобки, а деструктор - при каждом достижении закрывающей фигурной скобки. Таким образом, если мы поместим такую переменную вовнутрь цикла из 100 итераций, то у нас 100 раз вызовется конструктор и 100 раз деструктор. Если конструктор и деструктор представляют собой inline-реализации которые тупо модифицируют значения полей (типа обнуляют или что-то ещё), то это не страшно, т.к. компилятор в процессе оптимизаций всё равно лишнее выкинет. Типа если в конструкторе обнуляли поле класса, а затем в коде в это поле мы что-то записывали, то код по обнулению поля компилятор выкинет за ненадобностью, т.к. мы всё равно после этого что-то другое записываем. Но вот если в конструкторе идёт формирование динамических массивов, а в деструкторе - их освобождение, то затаскивание переменной вовнутрь цикла может существенно программу замедлить
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.09.2012, 09:37     Соптимизирует ли (любой) компилятор такой код?
Еще ссылки по теме:

C++ поправьте код компилятор выдает ошибки
Компилятор запускает предыдущий код C++
Как написать такой код в си++? C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
24.09.2012, 09:37     Соптимизирует ли (любой) компилятор такой код? #12
Как то обсуждали уже: Насколько критично обьявление переменной в теле цикла?
Yandex
Объявления
24.09.2012, 09:37     Соптимизирует ли (любой) компилятор такой код?
Ответ Создать тему

Метки
оптимизация
Опции темы

Текущее время: 14:39. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru