Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Алгоритмы решения систем линейных уравнений с блочно-ленточными матрицами. Монография

.pdf
Скачиваний:
0
Добавлен:
06.09.2026
Размер:
2 Мб
Скачать
Алгоритмы решения СЛАУ с блочно-ленточными матрицами. Глава 5 101
Следовательно, вычисление рассматриваемой программы — это ре-
ализация итерационного процесса решения некоторой задачи линейной алгебры.
XXk = (I – A)–1*B* XX
k – 1
+ (I A)–1*E.
Таким образом, вычисление программы удалось свести к решению за-
дачи линейной алгебры.
В представленной моногорафии демонстрируется взаимная сводимость
задач решения СЛАУ с блочной двухдиагональной матрицей и вычисления рекуррентного программного цикла. Кроме того, демонстрируется взаимная сводимость вычисления гнезд циклов итерационного типа и итерационных алгоритмов некоторых задач линейной алгебры. Этим самым обозначено новое направление на стыке математики и информационных технологий: анализ и преобразования программ, выполняющих аффинные вычисления с данными. Суть этого раздела теории преобразования программ в том, что множество данных, с которыми работает программа, конечно, а всякие ли­нейные преобразования данных эквивалентны матричным преобразованиям; соответственно, аффинные преобразования данных — это матричные пре­образования с прибавлениями константных векторов (данных). Ранее встре­чались работы (авторов монографии), в которых, например, вычисление и анализ сходимости рекуррентного цикла сводились к решению и анализу СЛАУ с треугольной ленточной матрицей. В данной монографии этот при­ем обобщается до метода, позволяющего к анализу и преобразованиям про­грамм применять методы линейной алгебры, а к методам линейной алгебры применять соответствующие методы теории преобразования программ.
Будем рассматривать гнезда циклов программных итерационного типа,
подобные алгоритму Гаусса-Зейделя.
for (t = 0; t < Itera; t++) for (i
= 0; i1 < N1; i1++)
1
for (i2 = 0; i2 < N2; i2++) (15) ... for (in = 0; in < Nn; in++) LoopBoby;
Здесь Itera — количество итераций внешнего цикла, LoopBoby — сим-
волическая запись тела гнезда циклов. В теле гнезда циклов могут быть генераторы (левые части операторов присваивания) вида A[i
, i2–a2, …,
1–a1
in–an] (запись в память). Если есть в теле гнезда циклов в левой части опе­раторов присваиваний вхождение, A[i1–a1, i2–a2, …, in–an ], то в правой ча-
102 Б. Я. Штейнберг, О. Б. Штейнберг
сти могут быть вхождения этой же переменной с другими константами в индексных выражениях A[i1–b1, i2–b2, …, in–bn ] (чтение из памяти), В теле гнезда циклов могут быть и другие переменные и с другими индексными выражениями, но генераторами (вхождениями, которые соответствуют опе­рациям записи в память) могут быть только эти переменные. Одна и та же переменная может входить в тело цикла несколько раз.
Каждому гнезду циклов можно поставить в соответствие вектор счетчиков циклов (t, I1, I2, …, In) где имена счетчиков расположены в порядке вложенно­сти циклов. Множество значений этого вектора образует пространство итера­ций IS. Поскольку значения счетчиков циклов — целые числа, пространство итераций можно рассматривать как подмножество пространства Zn.
В монографии предлагается комбинация нескольких методов.
Ускорение алгоритмов такого итерационного типа на примере алгорит­ма Гаусса-Зейделя для двумерной задачи Дирихле на основе скошенного тайлинга и распараллеливания на общей памяти на 8-ядерном процессоре достигает 30 раз [18].
Приведем пример обобщенного алгоритма Гаусса-Зейделя для случая двумерной области.
Пример 39. Рекуррентно вычисляемое гнездо циклов, реализующее абстрактный обобщенный алгоритм Гаусса-Зейделя решения (дву­мерной) задачи Дирихле в области, имеющей форму прямоугольного параллелепипеда.
for (It = 0; It < maxIt; It++) { for (i1 = 1; i1<N; i1++) { for (i2 = 1; i2<N; i2++) { x[i1,i2] = a1[i1,i2]*x[i1–1, i2] + b1[i1,i2]*x[i1+1, i2] + c1[i1,i2]*x[i1,i2–1] + d1[i1,i2]*x[i1,i2+1] + e1[i1,i2]; y[i1,i2] = a2[i1,i2]*y[i1–1,i2] + b2[i1,i2]*y[i1+1,i2] + c2[i1,i2]*y[i1,i2–1] + d2[i1,i2]*y[i1,i2+1]+ e2[i1,i2]; }}}
Здесь a1[i1, i2], b1[i1, i2], c1[i1, i2], d1[i1, i2], e1[i1, i2]; a2[i1, i2], b2[i1, i2], c2[i1, i2], d2*[i1, i2], e2[i1, i2] — массивы, не меняющие своих значе-
ний при вычислении программы (входные не вычисляемые данные).
Конец примера.
Алгоритмы решения СЛАУ с блочно-ленточными матрицами. Глава 5 103
Формирование вычислительной задачи по тексту программного
цикла, не содержащего зависимости
Пример 40.
for (j = 1; j < N; j++) {
x[j] = expr1(a1[j],b1[j],...)
y[j] = expr2(a2[j],b2[j],...)
}
Здесь выражения правой части expr1(a1[j], b1[j], …), expr2(a2[j], b2[j], …) зависят только от входных данных программы и не зависят от вычис­ляемых переменных. Такой код не содержит информационных зави­симостей. Все операторы присваивания могут вычисляться незави­симо друг от друга (параллельно).
Неинтересный вырожденный случай. Задача соответствует реше­нию СЛАУ с единичной матрицей, правая часть которой вычисляется.
Конец примера.
Формирование вычислительной задачи по тексту программного
цикла, содержащего антизависимости
Пример 41.
for (j = 1; j < N; j++) {
x[j] = expr1(a1[j],b1[j],..., x[j+k1],y[j+k1])
y[j] = expr2(a2[j],b2[j],... , x[j+k3],y[j+k4])
...
}
Здесь k1, k2, k3, k4 — неотрицательные целые числа, выражения правой части expr1(a1[j], b1[j], …, x[j+k1], y[j+k2]), expr2(a2[j], b2[j], … , x[j+k3], y[j+k4]) зависят не только от входных данных программы, но и от вычисляемых переменных. Такой код содержит антизави­симости. Это означает, что при вычислении выходных переменных используются значения этих переменных, вычисленные ранее, или они являются еще и входными данными и получены при вводе ис­ходных данных.
Конец примера.
104 Б. Я. Штейнберг, О. Б. Штейнберг
Теорема 3. Если выражения правых частей цикла вида (из примера 40) линейно зависят от вычисляемых переменных, входящих в программу с антизависимостями, то вычисление цикла можно представить как задачу умножения верхнетреугольной матрицы на вектор.
Доказательство. Достаточно рассмотреть случай, в котором в правой ча­сти есть только одно вхождение вычисляемой переменной, создающее антиза­висимость с генератором этой переменной. Если же таких вхождений несколь­ко, с помощью преобразований «вынесение вычисления подвыражений» и «разбиение цикла» рассматриваемый цикл можно представить в виде последо­вательности цик лов, каждый из которых имеет только одну антизависимость.
Если в теле программного цикла только одна антизависимость, то утверждение теоремы доказывается методом математической индукции по количеству итераций цикла.
Пример 42. Программный цикл с несколькими антизависимостями
for (j = 1; j < N; j++) { x[j] = a[j]*x[j+k1] + b[j]*x[j+k2]) + ... }
можно представить как последовательность двух циклов, каждый из которых содержит меньше зависимостей:
for (j = 1; j < N; j++) { x[j] = a[j]*x[j+k1] } for (j = 1; j < N; j++) { x[j] = x[j] + b[j]*x[j+k2]) + ... }
Процесс можно продолжать по индукции, пока не будет получен код, представляющий последовательность циклов, каждый из которых содержит одну антизависимость.
Конец примера.
Пример 43. Вычисление следующего программного цикла с антизависимостями
for (j = 1; j < N; j++) { x[j] = a[j]*x[j+1] + b[j]*x[j+2]) + … + h[j]; }
равносильно умножению ленточной матрицы U на вектор x со ста­рыми значениями (известными до вычисления цикла) и прибавле­нию вектора h:
Алгоритмы решения СЛАУ с блочно-ленточными матрицами. Глава 5 105
x = U*x + h.
Здесь у ленточной матрицы U с единицами по главной диагонали по другим ненулевым диагоналям расположены элементы масси­вов программы
1 a[1] b[1] 1 a[2] b[2] 1 a[3] b[3] 1 a[4] b[4] 1 a[5] b[5] 1 a[6] b[6] …
а вектор h состоит из элементов массива h
h[1] h[2] h[3] h[4] h[5] h[6]
Конец примера.
Пример 44. Вычисление следующего программного цикла с истин-
ными зависимостями
for (j = 3; j < N; j++) {
x[j] = a[j]*x[j – 1] + b[j]*x[j – 2]) + … + h[j];
}
равносильно решению СЛАУ с нижнетреугольной ленточной матрицей.
1 h[1] 0 1 h[2]a[1] –b[1] 1 h[3]a[2] –b[2] 1 h[3+1] a[3] –b[3] 1 h[3+2] a[4] –b[4] 1 h[3+3] a[5] –b[5] 1 h[3+4] a[6] –b[6] 1 h[3+5]
Конец примера.
106 Б. Я. Штейнберг, О. Б. Штейнберг
Пример 45. Случай выходной зависимости
for (j = L; j < N; j++) { x[j] = expr1(a1[j],b1[j],…) x[j+k] = expr2(a2[j],b2[j],…) }
Здесь k — целое число, выражения правой части expr1(a1[j ], b1[j], …), expr2(a2[j], b2[j], …) зависят только от входных данных программы и
не зависят от вычисляемых переменных. Такой код содержит выход­ную зависимость. Это означает, что при вычислении выходных пере­менных иногда некоторые выходные значения вычисляются 2 раза: приобретают одно значение, которое затем перевычисляется. Конеч­но, интерес представляет только последний раз присвоенное пере­менной значение. Рассматриваемый цикл равносилен двум последо­вательно выполняемым циклам. В итоге, N +|k| элементов массива получают новые значения.
Если k > 0, то исходный цикл равносилен следующим двум:
for (j = L; j < L+k; j++) { x[j] = expr1(a1[j],b1[j],…) } for (j = L; j < N; j++) { x[j+k] = expr2(a2[j],b2[j],… }
Если k < 0, то исходный цикл равносилен следующим двум
for (j = L+k; j < L; j++) { x[j] = expr1(a1[j],b1[j],…) } for (j = L; j < N; j++) { x[j+k] = expr2(a2[j],b2[j],…) }
Конец примера.
Пример 46. Одновременное наличие истинной зависимости и анти­зависимости. Примером может служить код алгоритма Гаусса-Зейде­ля решения задачи Дирихле. В этом случае вычисление программы равносильно решению матричного уравнения
A*x = B*x + h.
Алгоритмы решения СЛАУ с блочно-ленточными матрицами. Глава 5 107
Здесь h — вектор входных данных, x — вектор неизвестных, B — верхнетреугольная матрица коэффициентов при вхождени-
ях неизвестных, от которых идут дуги антизависимости, A нижне­треугольная матрица коэффициентов при вхождениях неизвестных, к которым идут дуги истинной зависимости.
Конец примера.
5.4. Операторы сдвига, операторы умножения на функцию и соответствующие им матрицы
Будем рассматривать множество векторов с целыми координатами Zm. На этом множестве функций C(Zm ) будем рассматривать оператор сдвига Sk и оператор умножения на функцию Mf, которые определяются, как обычно, следующим образом:
Sk(φ)(t) = φ(t–k) t, k ϵ Z
Mf (φ)(t) = f(t)*φ(t) t, k ϵ Zm.
Обозначим прямоугольный параллелепипед в m-мерном целочисленном пространстве Z
m
D = {1, 2, ..., n1}x{1, 2, ..., n2}x … x{1, 2, ..., nm}; n1, n2, …, nm — положительные целые числа.
Как обычно, характеристическая функция множества D — это функция, которая равна 1 в точках множества D и равна нулю в точках, не принадле­жащих D. Пусть проектор P тор умножения на характеристическую функцию множества D. Тогда PD (φ) равна нулю за пределами прямоугольной двумерной области D. Произведе­ние сдвига и проектора удовлетворяют равенству
— это функция, равная нулю за пределами сдвинутого (целочисленного) прямоугольного параллелепипеда, а функция PD Sk PD (φ)(t) равна нулю за пределами пересечения прямоугольников (для случая m = 2).
m
в пространстве функций C(Zm) — это опера-
D
S
(φ)(t) = (PD φ)(t–k), t, k ϵ Z
k PD
m
108 Б. Я. Штейнберг, О. Б. Штейнберг
Пример 47.
for (i = 0; i < n1; i++) { for {j = 0; j++, j<n2) { (16) U[i,j] = X[i+1,j+3]; }}
Массив X будем рассматривать как функцию на множестве индек­сов D = {1, 2, ..., n сдвига S
P
D Sk PD
на величину (вектор) k = (1, 3). Тогда функция
k
(X)(t)
определена на области индексов {2, 3, ..., (n
Ленточная матрица с одной диагональю соответствует оператору
P
D*Sk*Mf
*PD (φ)(t) (17)
Конец примера.
} x {1, 2, ..., n2}, и будем рассматривать оператор
1
+1)} x {4, 5, ..., (n2 +3)}.
1
Нумерация узлов параллелепипеда
Разным нумерациям узлов прямоугольного параллелепипеда (области
определения функций C(D))
D = {1, 2, …, n
соответствуют разные матрицы операторов на конечномерном простран-
стве функций C(D).
Опишем каноническую нумерацию узлов параллелепипеда. Занумеруем точки области
D = {1, 2, …, n
следующим образом. Точке
a = (a
, a
1
поставим в соответствие номер
k = a1*n1 + a2*n2 +… + a
} x {1, 2, ..., n2 } x … x {1, 2, ..., nm}
1
} x {1, 2, …, n2} x … x {1, 2, …, nm}
1
…, am )
2 ,
m – 1*nm – 1
+ am.
Алгоритмы решения СЛАУ с блочно-ленточными матрицами. Глава 5 109
0000000000 0000000000 1111111110 1111111110 1111111110 1111111110 1111111110 1111111110 1111111110 0000000000 0000000000 0000000000
           

При такой нумерации операторам (17) соответствуют ленточные матри­цы. Размерность матриц равна произведению n1*n2*…*n
m – 1*nm
.
«Ненулевая диагональ» отстоит от главной на n1 позиций. Каждая стро­ка, номер которой делится на одно из чисел n2, … n
, nm, является ну-
m – 1
левой. Аналогично, каждый столбец, номер которого делится на одно из чисел n2, … n
, nm, является нулевым.
m – 1
При m > 1 матрица имеет иерархию блоков.
Всякая ленточная матрица может быть представлена в виде конечной суммы произведений операторов умножения на функцию и операторов сдвига (и проекторов):
P
*(Mf1*Sk1 + Mf2*Sk2 + … )*PD. (18)
D
Операторы сдвига являются образующими алгебры операторов свертки, а операторы вида (18) называют операторами обобщенной свертки или опе­раторами типа свертки.
5.5. Операторы сдвига
Рассмотрим матрицу A размером M x N с элементами a[i, j] в которой первые L и последние R столбцов полностью состоят из нулей. Помимо этого, U первых и D последних строк также состоят из нулей.
Пример 48. В примере показана матрица A размерности 10x12, в ко­торой все ненулевые элементы равны 1. При этом L = 0, R = 1, U = 2,
D = 3.
A
=
Конец примера.
.
110 Б. Я. Штейнберг, О. Б. Штейнберг
01111 01111 00000 00000
  
 
( )
' 01111011110000000000
Задача 1. Имея двумерный массив, определить значения L, R, U, D.
Решение: рассмотрим функцию, способную определить значение L.
functionL (A, N, M, L) { L = N; for (int i = 0; i < M; i++) { for (int j = 0; j < L; j++) { if (a[i][j]! = 0) { L = j; }}}}
Конец решения.
Подобным образом можно определить значения R, U, D.
Рассмотрим ситуацию, когда матрица A представлена одномерным мас-
сивом (т. е. последовательности строк).
Пример 49. В примере показана матрица A размерности 4x5, в которой все ненулевые элементы равны 1. При этом L = 1, R = 0, U = 0, D = 2.
A
=
Ее представление одномерным массивом будет иметь вид:
.
A =
Конец примера.
Задача 2. Имея одномерный массив, определить значения L, R, U, D.
Решение: рассмотрим функцию, способную определить значение L.
functionL (A, N, M, L) { L = N; for (int i = 0; i < M; i++) { for (int j = 0; j < L; j++) { if (a[i*N + j]! = 0) { L = j; }}}}
Конец решения.
Подобным образом можно определить значения R, U, D.
.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]