подсказки по эффективности механизма для цикла

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

Command + Shift + K

При повторном запуске отобразятся обновленные локализации.

5
задан George Stocker 28 February 2009 в 20:38
поделиться

13 ответов

Во-первых, не потейте маленький материал. Детали как подсчет по сравнению со считанием в обратном порядке обычно абсолютно не важны во время выполнения. Люди известно плохи при определении областей в коде, который должен быть ускорен. Используйте профилировщика. Обратите минимальное внимание на любую часть цикла, который не повторяется, если профилировщик не говорит иначе. Помните, что то, что записано во внутреннем цикле, не обязательно выполняется во внутреннем цикле, поскольку современные компиляторы довольно умны о предотвращении ненужного повторения.

Однако очень опасаться разворачивать циклы на современных центральных процессорах. Чем более трудны они, тем лучше они впишутся в кэш. В высокоэффективном приложении я работал над прошлым годом, я значительно улучшил производительность при помощи циклов вместо прямолинейного кода и закручивания их так, как я мог. (Да, я представил; рассматриваемая функция подняла 80% времени выполнения. Я также сравнил времен по типичному входу, таким образом, я знал, что изменения помогли.)

Кроме того, нет никакого вреда в разработке привычек, которые способствуют эффективному коду. В C++ необходимо привыкнуть использовать преинкремент (++ i), а не постинкремент (я ++) для постепенного увеличения переменных цикла. Это обычно не имеет значения, но может иметь значительное значение, это не делает код менее читаемым или перезаписываемым, и не причинит боль.

4
ответ дан 18 December 2019 в 05:14
поделиться

Одно важное предложение: переместите как можно больше вычисления во внешний цикл. Не все компиляторы могут сделать это автоматически. Для eample, вместо:

for row = 0 to 999
    for col = 0 to 999
        cell[row*1000+col] = row * 7 + col

использование:

for row = 0 to 999
    x = row * 1000
    y = row * 7
    for col = 0 to 999
        cell[x+col] = y + col
12
ответ дан 18 December 2019 в 05:14
поделиться

Вы измерили издержки? Вы знаете, сколько потраченная обработка времени для циклов по сравнению с тем, сколько времени проведено, выполняя Ваш код приложения? Какова Ваша цель?

6
ответ дан 18 December 2019 в 05:14
поделиться

Попытайтесь сделать свои циклы непрерывными в памяти, это оптимизирует использование кэша. Таким образом, не делайте этого:

for (int i = 0; i < m; i++)  
    for (j = 0; j < n; j++)  
        s += arr[j][i];
  • При обработке изображений преобразуйте два цикла в один цикл на пикселях с единственным индексом.
  • Не делайте циклы, которые выполнят нулевые времена, поскольку конвейер оптимизирован, чтобы предположить, что цикл продолжится, а не закончится.
9
ответ дан 18 December 2019 в 05:14
поделиться

Развертывание цикла может быть одним путем. Это:

for (i=0; i<N; i++) {
  a[i]=...;
}

преобразовывает в:

for (i=0; i<N; i+=4) {
  a[i]=...;
  a[i+1]=...;
  a[i+2]=...;
  a[i+3]=...;
}

Вам будет нужна специальная обработка, когда N не будет несколькими из 4 в примере выше.

5
ответ дан 18 December 2019 в 05:14
поделиться

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

Внутренне вот в чем разница:

  • Инкремент сообщения

    i++;

    совпадает с:

    int postincrement( int &i )
    {
    int itmp = i;
    i = i + 1;
    return itmp;
    }

  • Пред инкремент

    ++i;

    совпадает с:

    int preincrement( int &i )
    {
    i = i + 1;
    return i;
    }

4
ответ дан 18 December 2019 в 05:14
поделиться

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

for (int i = 0; i < 10; i++) { /* ... */ }

int i = 0;
while (i < 10) {
    // ...
    i++;
}

На большинстве языков/компиляторов, для цикла просто синтаксический сахар для более позднего цикла с условием продолжения. Foreach является другим вопросом снова и является высоко иждивенцем на языке/компиляторе относительно того, как он реализован, но обычно менее эффективно что нормальное для/цикл с условием продолжения. Сколько еще так снова, язык и иждивенец компилятора.

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

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

4
ответ дан 18 December 2019 в 05:14
поделиться

Поскольку Ваши циклы будут иметь O (n^d) сложностью (d=dimension), что действительно рассчитывает, то, что Вы помещаете В цикл, не сам цикл. Оптимизация нескольких циклов далеко в платформе цикла от миллионов циклов неэффективного алгоритма в цикле является просто нефтью змеи.

1
ответ дан 18 December 2019 в 05:14
поделиться

Я соглашаюсь с @Greg. Первая вещь, которую необходимо сделать, помещается некоторое сравнительное тестирование на месте. Будет мало точки, оптимизируя что-либо, пока Вы не докажете, где все Ваше время обработки проводится. "Преждевременная оптимизация является корнем всего зла"!

3
ответ дан 18 December 2019 в 05:14
поделиться

Между прочим, это хороший для использования short вместо int в для цикла, если способность Int16, как гарантируют, будет достаточно?

1
ответ дан 18 December 2019 в 05:14
поделиться

Существует недостаточно информации для ответа на вопрос точно. Что Вы делаете в своих циклах? Делает вычисление в одном повторении, зависят от значения, вычисленного в предыдущем повторении. В противном случае можно почти сократить время в половине путем простого использования 2 потоков, предположения, что у Вас есть, по крайней мере, двухъядерный процессор.

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

Снова, я посмотрел бы на то, что в цикле сначала, где большинство усилений (> 99%) будет, а не инфраструктура внешнего цикла.

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

0
ответ дан 18 December 2019 в 05:14
поделиться

Существует немного релевантной информации среди ответов на другой stackoverflow вопрос, как кэш-память работает. Я нашел статью Ulrich Drepper упомянутой в этом ответе особенно полезный.

0
ответ дан 18 December 2019 в 05:14
поделиться

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

0
ответ дан 18 December 2019 в 05:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: