цикл после разворота
Компилятор msvc вообще не разворачивает циклы и эту работу приходится выполнять вручную.
Компилятор icl разворачивает только циклы for во сценарию больший размер — большая скорость. Причем, циклы с заранее известным количеством итераций — for(a=0;a<const;a++) — где const <= 32 трансформируются в линейный код и цикл как таковой при этом исчезает (см "шелушение циклов"). Как следствие — размер программы существенно возрастает, а вместе с ним возрастает и риск "вылететь" за пределы кэша первого уровня, после чего производительность упадет так, что не поднимешь и домкратом. Если const >
32, цикл разворачивается на кол-во итераций, кратное const, но не более 10h, при этом компилятор учитывает количество инструкций в теле цикла — более компактные циклы разворачиваются на больше число итераций. Циклы, количество итераций которых компилятору неизвестно — for(a=0;a<n;a++) – всегда разворачиваются на 5х, а оставшиеся (n % 5) итераций выполняются в отдельном неразвернутом цикле. Циклы с ветвлениями разворачиваются только при трансформации в линейный код (при этом ветвления, естественно исчезают): for (a =0; a<3;a++) if (a%2) x[a]++; else x[a]--; преобразуется в: x[0]--; x[1]++; x[2]--;
Компилятор gcc по умолчанию не разворачивает циклы даже на уровне оптимизации ?O3, и делает это только с ключом -funroll-all-loops, поддерживающим все виды циклов, а не только цикл for. Циклы с известным количеством итераций, где const <= 32 разворачиваются полностью, при const >
32 — на ~4x (точное значение зависит от количества инструкций в теле цикла). Если внутри цикла присутствует одно или несколько ветвлений, при развороте они неизбежно дублируются, в результате чего производительность оказывается даже ниже, чем была до оптимизации! Циклы с неизвестным количеством итераций не разворачиваются вообще. Для тонкой настройки существуют ключи max-unrolled-insns
(максимальное кол- во инструкций, при котором цикл еще может быть развернут, и если он будет развернут это значение определяет величину разворота), max-average-unrolled-insns
(максимальное оценочное количество инструкций, которое цикл может иметь после разворота) и max-unroll-times (максимальная степень разворота). Разворот по всех случаях выполняется по сценарию больший размер — большая скорость.
* msvc: не разворачивает никакие циклы;
* icl: циклы с переменным кол-вом итераций разворачивает на 5 итераций,
циклы с cost <= 32 разворачивает полностью:
циклы с const >
32 разращивает на величину кратную const, но не больше 10h,
учитывает количество инструкций в цикле;
циклы разворачиваются по сценарию: больший размер — большая скорость
* gcc: на уровне O3 по учаолчанию не разворачивает,
циклы с переменным кол-вом итераций никогда не разворачиваются;
циклы с постоянным кол-вом интераций развариваются на ~4x (но тут все зависит от числа инструкций),