Техника оптимизации под линуха

       

цикл после разворота


Компилятор 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 (но тут все зависит от числа инструкций),


Содержание раздела