Простейшие оптимизации программ
Развертка цикла (Loop unrolling) – эта техника призвана уменьшить количество условных переходов в цикле. Может улучшить инструкционный параллелизм. Несколько итераций цикла объединяются в одну. Есть свои минусы. Может повыситься нагрузка на регистры, увеличивается размер кода, что также может привести к ухудшению производительности.
for (int x = 0; x < 100; x++) { delete(x); } => Loop unrolling => for (int x = 0; x < 100; x += 5) { delete(x); delete(x+1); delete(x+2); delete(x+3); delete(x+4); }
Полная развертка (complete unrolling) применяется к небольшим циклам и бывает очень эффективна. Как правило в случае вложенных циклов развертываются внутренние циклы.
Перестановка циклов (Loop interchange) – оптимизация при которой меняется порядок итерационных переменных.
do i=0,10 do j=0,20 a[i,j] = i + j => Loop interchange do j=0,20 do i=0,10 a[i,j] = i + j
Для чего выполняется эта оптимизация ?
Вытеснение данных из кэш:
Разбиение цикла на блоки (Loop blocking)
Определение индукционных переменных
Выражения, которые являются линейной функцией от счетчиков цикла могут вычисляться прибавлением константы к значению на предыдущей итерации.
for(i=0;i<100;i++) { a[i]=i*8+4; } => temp=4; for(i=0;i<100;i++) { a[i] = temp; temp +=8; }
Другие оптимизации
Помимо этих оптимизаций существуют и другие, порой очень нетривиальные:
Компилятору в каждом случае необходимо доказать корректность производимой цикловой оптимизации и определить ее выгодность.
Нормализованный цикл
Предположим у нас есть цикл:
DO I=L,U,S A(I)=… END DO
Для упрощения рассуждений его можно преобразовать к нормализованному циклу:
DO J=1,(U-L+S)/S,1 A(J*S-S+L) = … END DO
Так как любой цикл может быть нормализован будем без ограничения общности рассматривать в примерах нормализованные циклы.
/Qopt-report[:n] generate an optimization report to stderr 0 disable optimization report output 1 minimum report output 2 medium output (DEFAULT when enabled) 3 maximum report output
Пример диагностики:
LOOP INTERCHANGE in loops at line: 8 9 Loopnest permutation ( 1 2 ) --> ( 2 1 ) Fusion loop partitions: (loop line numbers) Fused Loops: ( 9 14 )
Компилятор не ставит пользователя в известность, какие цикловые оптимизации и в каком порядке принимаются. Есть опция /Qopt-report, которая частично информирует пользователя о произведенных преобразованиях.