Оптимизирующие преобразования программ. Учебное пособие
.pdf
Эффект полезности слияния2.4. Преобразованияцикловизвестен, опишем его для полноты изложения.
Пусть имеются два последовательно записанных (в конкатенации) цикла, обрабатывающих общие массивы b, c.
for (i = 1; i < N; i++) LoopBody1(a[i], b[i], c[i],…); (3)
for (i = 1; i < N; i++)
ПредположимLoopBody2(b[i],, что данныеc[i],, которыеd[i],обрабатывает…); (4) цикл (3), не помещаются в кеш-памяти (все равно, какого уровня). Тогда на последних итерациях цикла (3) первые элементы массивов b, c будут вытеснены из кеш-памяти. Поэтому при выполнении цикла (4) массивы b, c придётся подкачивать в кеш-память заново.
Предположим, что циклы (3) и (4) можно слить в один цикл for (i = 1; i < N; i++)
{
a[i] = LoopBody1(b[i], c[i],…);
b[i] = LoopBody2(c[i], d[i],…);
Тогда} элементы массивов b, c считываются в кеш-память один раз и используются для выполнения каждого исходного тела цикла.
Слияние циклов с использованием
вспомогательных преобразований
Следующие два цикла нельзя слить непосредственно (Примернарушится75.корректность, результирующий цикл не будет эквивалентен исходному). Нарушение корректности связано с характером информационной зависимости между вхождениями переменной b: после слияния циклов возникает дуга графа информационных связей, ведущая снизу вверх.
for (i = 10; i < 20; i++) a[i] = b[2 * i - 9]; for (i = 10; i < 20; i++) b[2 * i - 7] = d[i];
81
Но если от первого 2цикла. Преобр зованияотщепитьпрограмм начальные итерации (в данном случае одну), а во втором цикле отщепить последние итерации (в данном случае тоже только одну), затем все полученные циклы привести к каноническому виду (левая граница единица и шаг цикла единица), то слияние циклов будет корректно.
for (i = 10; i < 11; i++) a[i] = b[2 * i - 9];
for (i = 0; i < 9; i++)
{
a[i + 11] = b[2 * i + 13]; b[2 * i + 13] = d[i + 11];
}
for (i = 19; i < 20; i++)
Далееb[2для упрощения* i - 7] кода= d[i];можно сделать раскрутки коротких первого и последнего циклов.
Суть инверсии в 2изменении.4.15. Инверсияпорядкациклавычисления итераций цикла на противоположный. Если все итерации цикла независимы, то инверсия цикла является эквивалентным преобразованием. Это означает, что в теле цикла нет циклически порождённых зависимостей.
Пример 76. Данный цикл
FOR (I=1; I<=N; I++); {
равносиленX[I] =следующемуA[I] * B[I];: }
FOR (I=1; I<=N; I++); {
ИнверсияX[N+1-I]является= A[N+1равносильным-I] * B[N+1преобразованием-I] ; } не только для независимых циклов.
Пусть # – ассоциативная операция с нейтральным элементом $ и пусть задан одномерный цикл вида
82
2.4. Преобразования циклов
FOR (I=1; I<=N; I++); {
ИнверсияX = A[i]этого# X;цикла} состоит в замене этого одномерного цикла на следующий фрагмент программы:
Y = $;
FOR (I=1; I<=N; I++); {
Y = Y # A[N-I+1]; }
ЕслиX = операцияY # X; # ещё и коммутативна, то инверсия состоит в замене исходного цикла на следующий:
FOR (I=1; I<=N; I++); {
99 XПримерами= A[N-I+1]ассоциативной# X; } и коммутативной операции # могут служить сложение и умножение чисел, конъюнкция и дизъюнкция булевых переменных, максимум и минимум (двух чисел). Некоммутативной, но ассоциативной операцией является, например, произведение матриц. По поводу ассоциативности операций над числами с плавающей запятой следует отдельно удостовериться в достаточной точности при округлениях.
В данном цикле есть циклически порождённая антизависимостьПри ер 77, .и он не может быть инвертирован.
FOR (J=1; J<=N; J++); {
H[J] = A[J]* H[J+1]; }
В данном цикле все итерации независимы, и он может бытьПримеринвертирован78. . Циклически независимая зависимость не препятствует инверсии.
FOR (J=1; J<=N; J++); {
КонецH[J] примера= A[J]*. H[J]; }
В данном цикле есть истинная информационная зависимостьПример,79которая. является циклически порождённой, и он не может быть инвертирован.
83
2. Преобразования программ
FOR (I=1; I<=N; I++); {
КонецH[J] примера= A[J]*. H[J-1]; }
В данном цикле выполняется ассоциативная (не коммутативнаяПример 80.) операция «дробно-линейное преобразование», и этот цикл может быть инвертирован.
FOR (J=1; J<=N; J++); { КонецH = (A[J]*H+B[J])примера. / (C[J]*H+D[J]); }
Инверсия цикла меняет информационный граф программы и этим самым может привести к возможности распараллеливания изначально не распараллеливаемого фрагмента программы.
Решётчатый граф программы следующего нетесного гнездаПримерциклов81. содержит путь, проходящий через все вершины этого графа. Это не позволяет одновременно вычислять никакие две итерации этого фрагмента программы.
FOR (I=1; I<=N; I++); {
FOR (J=1; J<=I-1; J++);{
H[N-I+1] = H[N+I-1] - A[N-I+1,N-I+J+1]* H[N-
I+J+1];}
ЕслиH[N-I+1]сделать= H[N+Iинверсию-1]/A[Nвложенного-I+1,N-циклаI+1];, то} решётчатый граф программы изменится, и его можно будет распараллеливать.
FOR (I=1; I<=N; I++); {
FOR (J=1; J<=I-1; J++);{
H[N-I+1] = H[N+I-1] - A[N-I+1,N-J+1]* H[N-J+1];}
ЗаметимH[N-I+1], что= программаH[N+I-1]/A[Nданного-I+1,Nпримера-I+1];представляет} собой решение системы линейных алгебраических уравнений с треугольной матрицей.
Конец примера.
84
2.4.Преобразования циклов
2.4.16.Вынос оператора из цикла
Данное преобразование заменяет цикл
FOR (I=1; I<=N; I++); { S1
..........
S(k-1) Sk S(k+1)
..........
Sm
на следующий} фрагмент программы:
Sk
FOR (I=1; I<=N; I++); { S1
..........
S(k-1)
S(k+1)
..........
Sm
}
Пусть тело исходного цикла состоит из трёх фрагментовТеорема, каждый22. из которых имеет один вход и один выход.
FOR (I=1; I<=N; I++); { FRAG1[i];
FRAG2[i];
ПустьFRAG3[i];во фрагменте} FRAG2 все генераторы не зависят от счётчика цикла, и предположим, что в этом фрагменте нет истинных циклически порождённых зависимостей. Тогда:
• Если нет дуг графа информационных связей, ведущих во фрагмент FRAG2 из фрагментов FRAG1 и FRAG3, то исходный цикл равносилен следующему:
85
2. Преобразования программ
FRAG2[N];
FOR (I=1; I<=N; I++); {
FRAG1[i];
• ЕслиFRAG3[i];нет дуг графа} информационных связей, ведущих из фрагмента FRAG2 во фрагменты FRAG1 и FRAG3, то исходный цикл равносилен следующему:
FOR (I=1; I<=N; I++); { FRAG1[i];
FRAG3[i]; }
FRAG2[N]; Заметим, что данное преобразование может бытьДоказательствосведено к двум: к. разрезанию цикла, а затем к удалению заголовка. Рассмотрим подробно первый случай, а второй может быть рассмотрен аналогично.
Поскольку нет дуг графа информационных связей, ведущих во фрагмент FRAG2 из фрагментов FRAG1 и FRAG3, то исходный цикл с помощью разрезания (и предварительной перестановки фрагментов) может быть преобразован к следующему равносильному фрагменту:
FOR (I=1; I<=N; I++); {
FRAG2[i]; }
FOR (I=1; I<=N; I++); {
FRAG1[i];
ПосколькуFRAG3[i];во}фрагменте FRAG2, который является телом цикла, все генераторы не зависят от счётчика цикла и в этом фрагменте нет истинных циклически порождённых зависимостей, заголовок цикла можно удалить, а вместо счётчика цикла подставить его последнее значение N. В результате получится описанный в формулировке теоремы фрагмент.
Пример 82. Цикл
FOR (I=1; I<=100; I++); {
X = A+1;
K[I] = X; }
86
эквивалентен следующему2.4.фрагментуПреобразова ия цикловпрограммы:
X = A+1;
FOR (I=1; I<=100; I++); {
КонецK[I] примера= X; }.
Пример 83. Цикл
FOR (I=1; I<=100; I++); {
X = A+X;
не эквивалентенK[I] = X; следующему} фрагменту программы:
X = A+X;
FOR (I=1; I<=100; I++); {
КонецK[I] примера= X; }.
Пример 84. Цикл
FOR (I=1; I<=100; I++); {
K = K+1;
не эквивалентенX[K] = B; следующему} фрагменту программы:
X[K] = B;
FOR (I=1; I<=100; I++); {
КонецK = K+1;примера} .
Пример 85. Цикл
FOR (I=1; I<=100; I++); { IF (A[I]<B[I]);{
goto 33;}
X[K] = 1;
не33эквивалентенY[I] = 0; следующему} фрагменту программы:
X[K] = 1;
FOR (I=1; I<=100; I++); {
87
2. Преобразования программ
IF (A[I]<B[I]);{
goto 33;} 33 Y[I]Конец =примера0; } .
Пример 86. Цикл
FOR (I=1; I<=100; I++); {
X = A+X;
эквивалентенK = B[I]+7;следующему} фрагменту программы:
FOR (I=1; I<=100; I++); {
X = A+X; }
КонецK = B[100]+7;примера.
Пример 87. Цикл
FOR (I=1; I<=100; I++); {
X = A[I]+X;
эквивалентенK = B[I]+X;следующему} фрагменту программы:
FOR (I=1; I<=100; I++); {
X = A[I]+X; }
КонецK = B[100]+X;примера.
Пример 88. Цикл
FOR (I=1; I<=100; I++); {
K = B[I]+X;
не эквивалентенX = A[I]+X;следующему} фрагменту программы:
FOR (I=1; I<=100; I++); {
X = A[I]+X; }
КонецK = B[100]+X;примера.
88
Пример 89. Цикл
FOR (I=1; I<=N;
K = B+X;
не эквивалентенX = A[I]+X;следующему} фрагменту программы:
K = B+X;
FOR (I=1; I<=N; I++); {
посколькуX = A[I]+X;существует} дуга истинной зависимости от второго оператора к первому.
Конец примера.
Пример 90. Цикл
FOR (I=1; I<=N; I++); {
K = B+X;
не эквивалентенX = A[I]; следующему} фрагменту программы:
FOR (I=1; I<=N; I++); {
X = A[I]+X; }
посколькуK = B+X;существует дуга антизависимости от первого оператора ко второму.
Конец примера.
Пример 91. Цикл
FOR (I=1; I<=N; I++); {
K = B+X;
X = С*4;
эквивалентенT[I]= A[I]+X;следующему} фрагменту программы:
K = B+X;
X = С*4;
FOR (I=1; I<=N; I++); { КонецT[I]=примераA[I]+X;. }
89
2. Преобразования программ
2.4.17. Индуктивные и охватывающие переменные в цикле
Переменная называется индуктивной, если при выполнении цикла она принимает значения, образующие арифметическую прогрессию.
Любой из следующих двух случаев является достаточным для того, чтобы переменная была индуктивной:
1. В теле цикла лишь в одном операторе присваивания эта переменная встречается в качестве генератора, это вхождение в теле цикла встречается раньше использований, и в этом операторе данная переменная линейно выражается через счётчик цикла.
2. В теле цикла данная переменная рекуррентно перевычисляется, причём рекуррентная зависимость имеет вид A=A+Const, где A – индуктивная переменная, а Const – заранее известное число.
В рассматриваемом цикле переменные INC и I2 являютсяПримериндуктивными92. .
INC=N;
FOR (I=1; I<=N; I++); {
I2=2*I-1;
X[INC]=Y[I]+Z[I2];
INC=INC-1;
ЕслиT[INC]=A[I];индуктивные} переменные встречаются в индексных выражениях переменных, то они затрудняют вычисление информационных зависимостей. Для вычисления информационных зависимостей индуктивную переменную можно выразить через счётчик цикла и всюду по тексту заменить эту переменную её значением. Приведённый выше цикл преобразится к виду
FOR (I=1; I<=N; I++); {
X[N-I+1]=Y[I]+Z[2*I-1]; T(N-I)=0; }
INC=1;
КонецI2=2*Nпримера-1; .
90
