Хорошо, решение состоит в том, чтобы убедиться, что вы очистили папку сборки, если удалили локализацию:
Command + Shift + K
При повторном запуске отобразятся обновленные локализации.
Во-первых, не потейте маленький материал. Детали как подсчет по сравнению со считанием в обратном порядке обычно абсолютно не важны во время выполнения. Люди известно плохи при определении областей в коде, который должен быть ускорен. Используйте профилировщика. Обратите минимальное внимание на любую часть цикла, который не повторяется, если профилировщик не говорит иначе. Помните, что то, что записано во внутреннем цикле, не обязательно выполняется во внутреннем цикле, поскольку современные компиляторы довольно умны о предотвращении ненужного повторения.
Однако очень опасаться разворачивать циклы на современных центральных процессорах. Чем более трудны они, тем лучше они впишутся в кэш. В высокоэффективном приложении я работал над прошлым годом, я значительно улучшил производительность при помощи циклов вместо прямолинейного кода и закручивания их так, как я мог. (Да, я представил; рассматриваемая функция подняла 80% времени выполнения. Я также сравнил времен по типичному входу, таким образом, я знал, что изменения помогли.)
Кроме того, нет никакого вреда в разработке привычек, которые способствуют эффективному коду. В C++ необходимо привыкнуть использовать преинкремент (++ i), а не постинкремент (я ++) для постепенного увеличения переменных цикла. Это обычно не имеет значения, но может иметь значительное значение, это не делает код менее читаемым или перезаписываемым, и не причинит боль.
Одно важное предложение: переместите как можно больше вычисления во внешний цикл. Не все компиляторы могут сделать это автоматически. Для 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
Вы измерили издержки? Вы знаете, сколько потраченная обработка времени для циклов по сравнению с тем, сколько времени проведено, выполняя Ваш код приложения? Какова Ваша цель?
Попытайтесь сделать свои циклы непрерывными в памяти, это оптимизирует использование кэша. Таким образом, не делайте этого:
for (int i = 0; i < m; i++)
for (j = 0; j < n; j++)
s += arr[j][i];
Развертывание цикла может быть одним путем. Это:
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 в примере выше.
BTW, если Вам не нужен постинкремент, необходимо всегда использовать преинкрементный оператор. Это - только незначительные различия, но это более эффективно.
Внутренне вот в чем разница:
Инкремент сообщения
i++;
совпадает с:
int postincrement( int &i )
{
int itmp = i;
i = i + 1;
return itmp;
}
Пред инкремент
++i;
совпадает с:
int preincrement( int &i )
{
i = i + 1;
return i;
}
Это не вопрос об агностике языка, он зависит высоко от не только язык, но также и компилятор. Большинство компиляторов, которым я верю, скомпилирует эти два эквивалентно:
for (int i = 0; i < 10; i++) { /* ... */ }
int i = 0;
while (i < 10) {
// ...
i++;
}
На большинстве языков/компиляторов, для цикла просто синтаксический сахар для более позднего цикла с условием продолжения. Foreach является другим вопросом снова и является высоко иждивенцем на языке/компиляторе относительно того, как он реализован, но обычно менее эффективно что нормальное для/цикл с условием продолжения. Сколько еще так снова, язык и иждивенец компилятора.
Ваш лучший выбор состоял бы в том, чтобы, вероятно, выполнить некоторые сравнительные тесты с несколькими различными вариациями на тему и видеть то, что преуспевает.
Править: С этой целью предложения здесь, вероятно, сохранят Вас больше времени вместо того, чтобы вызвать беспокойство о самом цикле.
Поскольку Ваши циклы будут иметь O (n^d) сложностью (d=dimension), что действительно рассчитывает, то, что Вы помещаете В цикл, не сам цикл. Оптимизация нескольких циклов далеко в платформе цикла от миллионов циклов неэффективного алгоритма в цикле является просто нефтью змеи.
Я соглашаюсь с @Greg. Первая вещь, которую необходимо сделать, помещается некоторое сравнительное тестирование на месте. Будет мало точки, оптимизируя что-либо, пока Вы не докажете, где все Ваше время обработки проводится. "Преждевременная оптимизация является корнем всего зла"!
Между прочим, это хороший для использования short
вместо int
в для цикла, если способность Int16, как гарантируют, будет достаточно?
Существует недостаточно информации для ответа на вопрос точно. Что Вы делаете в своих циклах? Делает вычисление в одном повторении, зависят от значения, вычисленного в предыдущем повторении. В противном случае можно почти сократить время в половине путем простого использования 2 потоков, предположения, что у Вас есть, по крайней мере, двухъядерный процессор.
Другая вещь посмотреть на состоит в том, как Вы получаете доступ к своим данным при выполнении обработки большого массива, чтобы удостовериться, что Вы получаете доступ к данным последовательно, поскольку это хранится в памяти, избегая сбрасывания Вашего кэша L1/L2 на каждом повторении (замеченный это прежде в меньших кэшах L1, различие может быть резким).
Снова, я посмотрел бы на то, что в цикле сначала, где большинство усилений (> 99%) будет, а не инфраструктура внешнего цикла.
Но с другой стороны, если Вашим кодом цикла является связанный ввод-вывод, то любое время, проведенное на оптимизации, потрачено впустую.
Существует немного релевантной информации среди ответов на другой stackoverflow вопрос, как кэш-память работает. Я нашел статью Ulrich Drepper упомянутой в этом ответе особенно полезный.
Я думаю, что большинство компиляторов, вероятно, сделало бы, это так или иначе, уходя для обнуления должно быть более эффективно, поскольку проверка на нуль очень быстра для процессора. Снова, хотя, любой компилятор, стоящий, тот - вес, сделал бы это с большинством циклов так или иначе. Вам нужно к туалету в том, что делает компилятор.