в то время как (1) против для (;;) Есть ли разница в скорости? - PullRequest
149 голосов
/ 20 мая 2009

Длинная версия ...

Сотрудник заявил сегодня, увидев мое использование while (1) в скрипте Perl, что for (;;) быстрее. Я утверждал, что они должны быть такими же, надеясь, что переводчик оптимизирует любые различия. Я установил скрипт, который будет запускать 1 000 000 000 для итераций цикла и столько же циклов while и записывать время между ними. Я не мог найти никакой заметной разницы. Мой сотрудник сказал, что профессор сказал ему, что while (1) делает сравнение 1 == 1, а for (;;) - нет. Мы повторили тот же тест с 100-кратным числом итераций с C ++, и разница была незначительной. Однако это был наглядный пример того, насколько быстрее может быть скомпилированный код по сравнению с языком сценариев.

Короткая версия ...

Есть ли причина предпочитать while (1) над for (;;), если вам нужен бесконечный цикл, чтобы выйти из него?

Примечание: Если из вопроса не ясно. Это была просто веселая академическая дискуссия между парой друзей. Я знаю, что это не очень важная концепция, которую должны мучить все программисты. Спасибо за все замечательные ответы, которые я (и я уверен, что другие) узнали несколько вещей из этой дискуссии.

Обновление: Вышеупомянутый сотрудник получил ответ ниже.

Цитируется здесь на случай, если его похоронят.

Пришло от ассемблера AMD. Он заявил, что программисты C (люди) не понимают, что их код неэффективен. Он сказал сегодня, однако, компиляторы gcc очень хороши, и выдают таких как он бизнеса. Он сказал, например, и рассказал мне о while 1 против for(;;). Я использую это сейчас по привычке, но GCC и особенно переводчики будет выполнять одну и ту же операцию (скачок процессора) в течение обоих дней, так как они оптимизированы.

Ответы [ 20 ]

8 голосов
/ 28 сентября 2010

Я слышал об этом однажды.

Пришло от ассемблера AMD. Он заявил, что программисты на C (люди) не понимают, что их код неэффективен. Однако сегодня он сказал, что компиляторы gcc очень хороши и выводят таких людей, как он, из бизнеса. Он сказал, например, и рассказал мне о while 1 против for(;;). Сейчас я использую его по привычке, но gcc и особенно интерпретаторы будут выполнять одну и ту же операцию (скачок процессора) в течение обоих дней, поскольку они оптимизированы.

5 голосов
/ 20 мая 2009

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

3 голосов
/ 03 сентября 2011

Я удивлен, что никто не проверял должным образом for (;;) против while (1) в perl!

Поскольку perl является интерпретируемым языком, время запуска сценария perl состоит не только из фазы выполнения (которая в этом случае одинакова), но и из фазы интерпретации перед выполнением. Обе эти фазы должны быть приняты во внимание при сравнении скорости.

К счастью, в Perl есть удобный модуль Benchmark , который мы можем использовать для реализации теста, такого как:

#!/usr/bin/perl -w

use Benchmark qw( cmpthese );

sub t_for   { eval 'die; for (;;) { }'; }
sub t_for2  { eval 'die; for (;;)  { }'; }
sub t_while { eval 'die; while (1) { }'; }

cmpthese(-60, { for => \&t_for, for2 => \&t_for2, while => \&t_while });

Обратите внимание, что я тестирую две разные версии бесконечного цикла for: одну, которая короче, чем цикл while, и другую, которая имеет дополнительный пробел, чтобы сделать его такой же длины, как цикл while.

В Ubuntu 11.04 x86_64 с Perl 5.10.1 я получаю следующие результаты:

          Rate   for  for2 while
for   100588/s    --   -0%   -2%
for2  100937/s    0%    --   -1%
while 102147/s    2%    1%    --

Цикл while явно выиграл на этой платформе.

На FreeBSD 8.2 x86_64 с Perl 5.14.1:

         Rate   for  for2 while
for   53453/s    --   -0%   -2%
for2  53552/s    0%    --   -2%
while 54564/s    2%    2%    --

Здесь цикл также является победителем.

На FreeBSD 8.2 i386 с Perl 5.14.1:

         Rate while   for  for2
while 24311/s    --   -1%   -1%
for   24481/s    1%    --   -1%
for2  24637/s    1%    1%    --

Удивительно, но цикл for с дополнительным пробелом - самый быстрый выбор здесь!

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

2 голосов
/ 17 августа 2010

Я удивлен, что никто не предложил более прямую форму, соответствующую желаемой сборке:

forever:
     do stuff;
     goto forever;
2 голосов
/ 16 апреля 2010

Теоретически, полностью наивный компилятор может хранить литерал '1' в двоичном коде (тратить пространство) и проверять, равен ли 1 == 0 на каждой итерации (тратить время и больше места). 1003 *

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

2 голосов
/ 21 мая 2009

while(1) - идиома для for(;;), которая распознается большинством компиляторов.

Я был рад видеть, что Perl тоже распознает until(0).

2 голосов
/ 13 июня 2016

Подводя итог дебатам for (;;) против while (1), очевидно, что первые были быстрее во времена старых неоптимизирующих компиляторов, поэтому вы склонны видеть это в более старых базах кода, таких как Lions Unix Source code Комментарий, однако в эпоху злостных оптимизирующих компиляторов эти выгоды оптимизируются в сочетании с тем фактом, что последний легче понять, чем первый, и я считаю, что это было бы более предпочтительным.

1 голос
/ 06 сентября 2018

Только что наткнулся на эту ветку (хотя и с опозданием на несколько лет).

Мне кажется, я нашел реальную причину, по которой "for (;;)" лучше, чем "while (1)".

в соответствии со «стандартом кодирования barr 2018»

Kernighan & Ritchie long ago recommended for (;;) , which has the additional benefit
of insuring against the visually-confusing defect of a while (l); referencing a variable ‘l’.

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

т.е. 1 против л. (в некоторых шрифтах они выглядят одинаково).

Так что while (1) может выглядеть как цикл while, зависящий от переменной буква L.

while (true) также может работать, но в некоторых более старых случаях C и встроенного C true / false еще не определены, если не включен stdbool.h.

0 голосов
/ 21 мая 2009

Я бы подумал, что оба одинаковы с точки зрения производительности. Но я бы предпочел while (1) для удобства чтения, но я спрашиваю, зачем вам нужен бесконечный цикл.

0 голосов
/ 20 мая 2009

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


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