Или все о семантике?
Есть ли разница в производительности между() и while()?
Ответ 1
Короткий ответ: нет, они точно такие же.
Предположим, что теоретически это зависит от компилятора; действительно сломанный может сделать что-то немного другое, но я был бы удивлен.
Просто для удовольствия здесь два варианта, которые скомпилируются с точностью до одного и того же кода сборки для меня, используя x86 gcc версию 4.3.3, поставляемую с Ubuntu. Вы можете проверить сборку, созданную в финальном двоичном файле, с objdump в linux.
int main() { #if 1 int i = 10; do { printf("%d\n", i); } while(--i); #else int i = 10; for (; i; --i) printf("%d\n", i); #endif }
РЕДАКТИРОВАТЬ: Вот пример "апельсинов с апельсинами" в примере цикла, который также сводится к одному и тому же:
while(i) { printf("%d\n", i); --i; }
Ответ 2
Если ваши петли for и while выполняют одни и те же вещи, машинный код, сгенерированный компилятором, должен быть (почти) одинаковым.
Например, в некоторых тестах, которые я сделал несколько лет назад,
for (int i = 0; i < 10; i++)
{
...
}
и
int i = 0;
do
{
...
i++;
}
while (i < 10);
будет генерировать точно такой же код, или (и Нил указал в комментариях) с одним дополнительным jmp, который не будет иметь большой разницы в производительности, чтобы беспокоиться.
Ответ 3
Нет семантической разницы, нет необходимости компилировать разницу. Но это зависит от компилятора. Поэтому я попробовал с g++ 4.3.2, CC 5.5 и xlc6.
g++, CC были идентичны, xlc не был
Разница в xlc была в записи начального цикла.
extern int doit( int );
void loop1( ) {
for ( int ii = 0; ii < 10; ii++ ) {
doit( ii );
}
}
void loop2() {
int ii = 0;
while ( ii < 10 ) {
doit( ii );
ii++;
}
}
XLC OUTPUT
.loop2: # 0x00000000 (H.10.NO_SYMBOL)
mfspr r0,LR
stu SP,-80(SP)
st r0,88(SP)
cal r3,0(r0)
st r3,64(SP)
l r3,64(SP) ### DIFFERENCE ###
cmpi 0,r3,10
bc BO_IF_NOT,CR0_LT,__L40
...
enter code here
.loop1: # 0x0000006c (H.10.NO_SYMBOL+0x6c)
mfspr r0,LR
stu SP,-80(SP)
st r0,88(SP)
cal r3,0(r0)
cmpi 0,r3,10 ### DIFFERENCE ###
st r3,64(SP)
bc BO_IF_NOT,CR0_LT,__La8
...
Ответ 4
Объем переменной в тесте цикла while
шире, чем область переменных, объявленных в заголовке цикла for
.
Поэтому, если есть последствия для производительности в качестве побочного эффекта сохранения переменной дольше, тогда будут последствия производительности при выборе между while и циклом for (а не обертывание while в {}, чтобы уменьшить объем его переменных).
Примером может быть параллельный набор, который подсчитывает количество итераторов, ссылающихся на него, и если существует более одного итератора, он применяет блокировку для предотвращения одновременной модификации, но поскольку оптимизация исключает блокировку, если к ней относится только один итератор, Если у вас тогда было две петли for
в функции с использованием именованных именованными именами в одном и том же контейнере, быстрый путь был бы выполнен, но с двумя циклами while
будет выполняться медленный путь. Точно так же могут иметь место последствия для производительности, если объекты большие (больше кеш-трафика) или использование системных ресурсов. Но я не могу придумать настоящего примера, который я когда-либо видел, где бы это имело значение.
Ответ 5
Компиляторы, которые оптимизируются с использованием разворачивания цикла, вероятно, будут делать это только в случае for-loop.
Ответ 6
Оба эквивалентны. Это вопрос семантики.
Единственное различие может заключаться в do... while construct, где вы откладываете оценку состояния до тех пор, пока после тела, и, таким образом, не сможете сохранить 1 оценку.
i = 1; do { ... i--; } while( i > 0 );
в отличие от
for( i = 1; i > 0; --i )
{ ....
}
Ответ 7
Я пишу компиляторы. Мы собираем весь "структурированный" поток управления (if
, while
, for
, switch
, do
... while
) в условные и безусловные ветки. Затем мы анализируем граф потока управления. Так как компилятор C должен иметь дело с общим goto
в любом случае, проще всего сводить все к инструкциям ветки и условной ветки, а затем не забудьте хорошо обработать этот случай. (Компилятор C должен делать хорошую работу не только по рукописному коду, но и по автоматически сгенерированному коду, у которого может быть много, много операторов goto
.)
Ответ 8
Нет. Если они выполняют эквивалентные вещи, они будут скомпилированы в один и тот же код, как вы говорите, о семантике. Выберите тот, который лучше всего отражает то, что вы пытаетесь выразить.
Ответ 9
В идеале это должно быть одно и то же, но в конечном итоге это зависит от вашего компилятора/интерпретатора. Разумеется, вы должны измерить или просмотреть сгенерированный код сборки.
Доказательство того, что может быть разница: эти строки создают другой код сборки с использованием cc65.
for (; i < 1000; ++i);
while (i < 1000) ++i;
Ответ 10
В Atmel ATMega while() работает быстрее, чем для(). Почему это объясняется в AVR035: эффективное C-кодирование для AVR.
P.S. Оригинальная платформа не упоминалась в вопросе.
Ответ 11
continue ведет себя по-разному в для и , а: в для, он изменяет счетчик в while, обычно это не
Ответ 12
Чтобы добавить еще один ответ: по моему опыту, оптимизация программного обеспечения похожа на большую, густую бороду, сбритую мужчиной.
- Сначала вы удалите его большими кусками с помощью ножниц (обрезайте целые конечности с дерева вызовов).
- Затем вы сократите его с помощью электрического клипера (алгоритмы настройки).
- Наконец, вы бреете его бритвой, чтобы избавиться от последней битки (оптимизация низкого уровня).
В последнем случае разница между for()
и while()
может, но, вероятно, не изменится.
P.S. Программисты, которых я знаю (кто все очень хорош, и я подозреваю, что это репрезентативный пример), в основном идут на него с другого направления.
Ответ 13
Они такие же, как и производительность. Я обычно использую while
, ожидая изменения состояния (например, ожидание заполнения буфера) и for
при обработке нескольких дискретных объектов (например, через каждый элемент в коллекции).
Ответ 14
В некоторых случаях есть разница.
Если вы находитесь в точке, где это имеет значение, вам либо нужно выбрать лучший алгоритм, либо начать кодирование на ассемблере. Поверьте мне, кодирование в сборке предпочтительнее для исправления вашей версии компилятора.
Ответ 15
Является ли while()
быстрее/медленнее, чем for()
? Давайте рассмотрим несколько вещей об оптимизации:
-
Авторы-компиляторы работают очень интенсивно, чтобы сбривать циклы, имея меньше вызовов для перехода, сравнения, увеличения и других типов команд, которые они генерируют.
-
С другой стороны, инструкции вызова потребляют много величин больше циклов, но компилятор почти бессилен сделать что-либо, чтобы удалить их.
-
Как программисты, мы пишем много вызовов функций, некоторые из них, потому что мы имеем в виду некоторые из них, потому что мы ленивы, а некоторые из-за того, что компилятор их проскальзывает, не будучи очевидным.
-
В большинстве случаев это не имеет значения, потому что аппаратное обеспечение настолько быстрое, и наши рабочие места настолько малы, что компьютер похож на собаку гончей, которая волнует ее пищу и просит больше.
-
Иногда, однако, задание достаточно велико, что производительность является проблемой.
-
Что нам делать тогда? Где больший выигрыш?
- Получение компилятора для сбривания нескольких циклов цикла и т.д.
- Найти вызовы функций, которые не выполняются - действительно, нужно сделать так много?
-
Компилятор не может использовать последний. Только мы, программисты, можем.
-
Нам нужно научиться или научиться тому, как это сделать. Это не происходит естественно. Мы врожденно склонны делать неправильные догадки, а затем делаем ставку на них. Получение лучших алгоритмов - это начало, но только начало. Наши учителя должны учить это, если они действительно знают, как.
-
Профилисты - это начало. Я делаю это.
Апокрифическая цитата Вилли Саттона, когда его спросили Почему вы грабите банки?:
Потому что там, где деньги.
Если вы хотите сохранить циклы, узнайте, где они находятся.
Ответ 16
Вероятно, только стиль кодирования.
- если вы знаете количество итераций.
- если вы не знаете количество итераций.