для цикла VS в то время как цикл в языках программирования, C ++ / Java? - PullRequest
0 голосов
/ 25 ноября 2011

Что лучше для производительности? Это может не соответствовать другим языкам программирования, поэтому, если они отличаются или если вы можете ответить на мой вопрос своими знаниями на определенном языке, пожалуйста, объясните.

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

int x = 0;
 while (x < 10) {
    cout << x << "\n ";
    x++;
  }

VS

for ( int x = 1; x < 10; x++)   
 cout << x << "\n ";

Какой из них работает лучше? Если это цикл for, то допустим, что уже объявлено целое число, которое мы могли бы использовать в приращении цикла while, которое нам не нужно было создавать только для цикла while?

пример:

int age = 17; //this was made for something else in the code, not a while loop. But fortunately for us, our while loop just so happened to need the number 17.

 while (age < 25) {
        cout << age << "\n ";
        age++;
      }

Будет ли этот экземпляр сделать цикл while лучшим выбором, чем создание цикла for? И я видел вопросы, несколько похожие на это, но я не считаю, что это дубликат, или какой-либо из ответов на эти другие вопросы ответил на мой вопрос.

Я хочу получить объяснение по этому вопросу, объяснив, является ли он специфичным для компилятора, как он работает или что-то хорошее для ответа на этот вопрос.

Ответы [ 9 ]

4 голосов
/ 25 ноября 2011

Все разумные компиляторы должны компилировать эквивалентные циклы в идентичный код ассемблера / IL, включающий переходы и переходы. (по крайней мере, с включенной оптимизацией)

3 голосов
/ 25 ноября 2011

На некоторых архитектурах ЦП характеристики цикла могут предоставить возможности для большей оптимизации, чем выбор for против while.

В частности, FORTRAN и Pascal рекомендовали постоянную(а не переменная) для числа итераций цикла, которые могут оптимизировать некоторые процессоры.Например, в Cyber ​​(мэйнфрейм 1970-х годов Железный динозавр ) 15-битный регистр содержит индекс цикла for, который можно легко сравнить.Вместо этого while использует один или два трудных для доступа 60-битных регистра.Кроме того, инструкция ветвления Cyber ​​значительно дороже, чем ведение цикла или, возможно, содержимое цикла.В таких случаях высокий уровень оптимизации может развернуть цикл, чтобы избежать всех накладных расходов.

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

2 голосов
/ 25 ноября 2011

Пример, который вы опубликовали, на самом деле имеет разное поведение для while и for.

Это:

for (int x = 0; x < 100; ++x) {
  foo y;
  y.bar(x);
}

Эквивалентно этому:

{ // extra blocks needed
  int x = 0;
  while (x < 100) {
    {
      foo y;
      y.bar(x);
    }
    ++x;
  }
}

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

Хотя в современном компиляторе различий между этими понятиями нет, for может лучше оптимизироваться при более явном изложении своего поведения.

2 голосов
/ 25 ноября 2011

Мне трудно представить себе ситуации, когда примеры кода, которые вы даете, имели бы разные характеристики производительности.

Хотя у меня есть небольшое любопытство к вам.В языках, подобных Паскалю (например, Delphi), пределы цикла оцениваются только один раз.Это отличается от языков, подобных C, где пределы цикла оцениваются на каждой итерации.Это может повлиять на производительность, но, конечно, тривиально писать код на языке C, например, на языке C, вводя локальный код за пределами цикла.

Например:

Delphi

for i := 0 to List.Count-1 do
  DoStuff(List[i]);

List.Count вычисляется только один раз.

C ++

for (int i=0; i<List.getCount(); i++)
  DoStuff(List.getItem(i));

Здесь List.getCount() вызывается каждый раз вокруг цикла.

Если выясняется, что оценка пределов цикла является дорогостоящей, тогда это различие может иметь значение.Естественно, тривиально оценить List.getCount() вне цикла и сохранить результат в локальной переменной.

Сравнив циклы for в Pascal и C / C ++, я бы сказал, что версия Pascal очень упрощенная.в сравнении.Это не обязательно плохо, потому что для более сложных всегда есть while.

1 голос
/ 25 ноября 2011

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

Это имело бы значение, только если код внутри цикла был бы действительно быстрым. Здесь быстрое значение, означающее даже не иметь инструкции чтения из памяти, поскольку уже тогда пропускная способность памяти ЦП снова будет доминировать.

Так что, если вам действительно любопытно, и вам это кажется, прочитайте ассемблер и посмотрите на код. Если у вас есть только две маленькие функции только с каждым типом цикла, вывод не так сложен для чтения, на самом деле, не пугайтесь. Я бы посоветовал сделать это с C, однако, это, вероятно, ближе всего к сборке и проще всего определить детали.

Вы не сказали нам, какая у вас система / компилятор. С gcc параметры будут -S -O3 -march=native, чтобы он генерировал файл .s.

1 голос
/ 25 ноября 2011

Это не будет иметь никакого значения с оптимизацией компилятора!

Мои 2cts, когда речь идет о выборе реализации цикла, важно использовать тот, который соответствует логике алгоритма.Проще прочитать код.

1 голос
/ 25 ноября 2011

Я бы посоветовал вам написать небольшой пример и указать разницу во времени. Затем выберите наиболее быстрое решение.

1 голос
/ 25 ноября 2011

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

1 голос
/ 25 ноября 2011

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

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

Ваш второй пример может быть записан как цикл for снет выражения инициализации.

int age = 17; // This was made for something else in the code

for (; age < 25; age++) {
    cout << age << endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...