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

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

.pdf
Скачиваний:
0
Добавлен:
06.09.2026
Размер:
2 Мб
Скачать
Алгоритмы решения СЛАУ с блочно-ленточными матрицами. Глава 4 71
1 0 (0)
X
            
−−
 
− − −−

0 1 (0)
(1) (1) 1 0 (1)
AB C
(1) (1) 0 1 (1)
DE F
. . . . .. . . .. .
. . . . .. . . .. .
Конец примера.
Пример 27. Выполнение следующего цикла равносильно решению
СЛАУ с треугольной ленточной матрицей, которая может не являть-
ся блочной двухдиагональной.
(2) (2) 1 0 (2)
AB C
(2) (2) 0 1 (2)
DE F
( 1) ( 1) 1 0 ( 1)
AN BN C N
( 1) ( 1) 0 1 ( 1)
DN E N F N
Y
for (i = k; i < N + k; i++) {
X[i] = A0[i]*X[i]+A1[i]*X[i-1]+...+Ak[i]*X[i-k]+
+B0[i]*Y[i]+B1[i]*Y[i-1]+...+Bk[i]*Y[i-k]+C[i];
Y[i] = D0[i]*X[i]+D1[i]*X[i-1]+...+Dk[i]*X[i-k]+
+E0[i]*Y[i]+E1[i]*Y[i-1]+...+Ek[i]*Y[i-k]+F[i];
}
Конец примера.
Аналогичное утверждение можно сформулировать и для циклов с линей-
ной рекуррентностью с большим количеством операторов присваивания.
.
Пример 28. В следующем цикле рекуррентно вычисляются не мас-
сивы, а простые переменные.
for (i = 0; i < N; i++) {
X = A[i]*X+B[i]*Y+C[i];
Y = D[i]*X+E[i]*Y+F[i];
}
Такие переменные могут быть заменены массивами, после чего этот цикл становится равносильным следующему фрагменту программы:
XX[0] = X;
YY[0] = Y;
72 Б. Я. Штейнберг, О. Б. Штейнберг
for (i = 1; i < N+1; i++) { XX[i] = A[i]*XX[i-1]+B[i]*YY[i-1]+C[i]; YY[i] = D[i]*XX[i-1]+E[i]*YY[i-1]+F[i]; } X = XX[N]; Y = YY[N];
Таким образом получен цикл, идентичный (10).
Конец примера.
4.4. О циклах с нелинейной рекуррентной зависимостью
Некоторые циклы с нелинейной рекуррентной зависимостью иногда мо-
гут быть распараллелены.
Пусть f — нелинейная обратимая относительно суперпозиции функция одного переменного, т. е. f биективно отображает свою область определе­ния на область значений. Если такая функция вызывается в рекуррентном программном цикле, то рекуррентная зависимость такого цикла не линей­на. Но распараллеливание некоторых таких нелинейных циклов можно све­сти к распараллеливанию циклов с линейной рекуррентной зависимостью.
for (i = k; i < N+k; i++) { xi = f-1(A1(i)*f(x A0(i)) }
Рассмотрим вспомогательный массив Yi = f (xi), i = 0, 1, …, N – 1. Заме­тим, что элементы этого массива образуют последовательность с линейной рекуррентной зависимостью. Преобразуем написанный выше программ­ный цикл к следующему фрагменту программы:
for (i = 0; i < k; i++) { Y
= f(xi)
i
} for(i = k; i < N + k; i++) { Yi = A1(i)*Y
i-1+A2
} for(i = k; i < N+k; i++) { xi = f-1(Yi) }
)+A2(i)*f(x
i-1
(i)*Y
i-2
)+...+Ak(i)*f(x
i-2
+...+Ak(i)*Y
i-k+A0
(i)
i-k
) +
Алгоритмы решения СЛАУ с блочно-ленточными матрицами. Глава 4 73
Ниже приводятся примеры кода с конкретными функциями f.
Пример 29. Рекуррентный цикл
for(i = 2; i < N + 2; i++) {
xi = exp(A1(i)*ln(x
)+A2(i)*ln(x
i-1
)+A0(i))
i-2
}
равносилен следующему фрагменту программы:
Y0 = ln(x0)
Y1 = ln(x1)
for (i = 2; i < N + 2; i++) {
Yi = A1(i)*Y
i-1+A2
(i)*Y
i-2+A0
(i) } for (i = 2; i < N + 2; i++) { xi = exp(Yi) }
Конец примера.
Пример 30. Рекуррентный цикл
for (i = 2; i < N + 2; i++) { xi = 1/(A1(i)/x
i-1+A2
(i)/x
i-2+A0
(i))
}
равносилен следующему фрагменту программы:
Y0 = 1/x0; Y1 = 1/x1; for (i = 2; i < N + 2; i++) { Yi = A1(i)*Y
i-1+A2
(i)*Y
i-2+A0
(i); } for (i = 2; i < N+2; i++) { xi = 1/Yi; }
Конец примера.
74 Б. Я. Штейнберг, О. Б. Штейнберг
22
22
−−
= ++
i ii ii
x Ax Bx i
ii
xY
Пример 31. Рекуррентный цикл
for (i = 2; i < N + 2; i++) {
* * 1/
}
равносилен следующему фрагменту программы:
Y0 = x Y1 = x
2
;
0
2
;
1
for (i = 2; i < N+2; i++) { Yi = Ai*Y
i-1+Bi*Yi-2
+1/i; } for (i = 2; i < N+2; i++) {
=
}
Конец примера.
В формуле (9) вместо x
x
n –1
= f(x
n –2
, x
n –3
можно подставить
n – 1
, ..., x
), (11)
n k – 1
тогда получится
xn = f(f(x
n –2
, x
n –3
, ..., x
n – k – 1
), x
n –2
, ..., x
). (12)
n k
Теперь, используя обе формулы (12) и (11), можно одновременно вычис-
и x
лять x
. Казалось бы, этим самым процесс вычисления рекуррентной
n
n – 1
последовательности ускоряется вдвое. Но такое ускорение возможно лишь тогда, когда время вычисления функции (12) такое же, как и (11). Непосред­ственное вычисление (12) ровно вдвое дольше вычисления (11) и сводит подстановку на нет. Если в (12) можно провести преобразования и полу­чить в правой части функцию вида (11), как это происходит для линейных рекуррентных зависимостей, то желаемое ускорение было бы достигнуто, исключая затраты на преобразования (12) к виду (11). Это возможно, на­пример, для линейных и описанных выше дробно-линейных функций.
Пример 32. Следующий рекуррентный цикл нельзя эффективно распараллелить (если функцию sin(x) не заменить более удобной интерполирующей функцией):
for (i = 1; i < N + 1; i++) { xi = sin(x }
Конец примера.
i-1
)
Алгоритмы решения СЛАУ с блочно-ленточными матрицами. Глава 4 75
В [66] исследуется распараллеливание рекуррентных циклов, содер­жащих условный оператор. Показано, что, если логическое выражение условного оператора рекуррентно перевычисляется в цикле, то для распа­раллеливания такого цикла должны выполняться такие жесткие условия, которым не удовлетворяют практически значимые циклы, кроме вычисле­ния минимума или максимума элементов массива.
4.5. Распараллеливание циклов с рекуррентной зависимостью на общей памяти
Обозначим через P количество вычислительных устройств (ВУ). Задача состоит в том, чтобы за как можно меньшее время вычислить последова­тельность Xi (i = 1, 2, ..., N) через отображения Gi по рекуррентной формуле
Xi = Gi(X
честве распараллеливаемого будет рассматриваться программный цикл вида:
Далее будем считать, что P > 1. Исходя из постановки задачи, X вычислить, не зная X вычислять различные элементы искомого массива, если не выполнить ка­ких-нибудь дополнительных действий. Как раз такими действиями может являться вычисление суперпозиций Gi◦G стрирующий то, каким образом предварительно вычисленные суперпози­ции способны помочь распараллеливанию.
), при условии, что в наличии имеется P ВУ. Таким образом, в ка-
i −1
for (i = 1; i < N+1; i++) { x
= Gi(x
i
i-1
);
}
, а значит, несколько ВУ не смогут одновременно
i −1
. Рассмотрим пример, демон-
i +1
нельзя
i
Пример 33. Цикл, содержащий аффинную рекуррентную зависимость:
for (i = 1; i < N+1; i++) { X[i] = A[i]*X[i-1]+B[i]; }
Конец примера.
В этом цикле никакие две итерации нельзя вычислить одновременно. Заметим что X1 = G1(X0) = A1∗ X0+ B1, а X2 = G2(X1) = A2∗ X1+ B2. Следова­тельно, X2 = G2(G1(X0)) = A2∗ (A1∗ X0+ B1)+B2 = A2∗ A1∗ X0+A2∗ B1+ B2. Та­ким образом, если предварительно вычислить AA1 = A2∗ A1 и BB1 = A2∗ B1, то можно будет одновременно получить X1 = A1∗ X0+ B1 и X2 = AA1∗ X0+ BB1.
76 Б. Я. Штейнберг, О. Б. Штейнберг
Идея алгоритма
Идея алгоритма состоит в том, чтобы параллельно вычислять все элемен­ты рекуррентной последовательности, предварительно вычислив несколько ее элементов с помощью заранее полученных суперпозиций. Рассмотрим идею алгоритма на простом примере. Предположим, что необходимо вычис­лить 100 элементов массива X (значит N = 100), и для вычисления исполь­зуется два ВУ (P = 2). Изначально дано X0. Исходя из постановки задачи, на первом шаге можно вычислить X1 = G1(X0), вторым шагом можно вычислить
X2 = G2(X1) и т. д. Теперь предположим, что изначально имелось бы не только X0, а еще и X50. В таком случае, на первом шаге вторым ВУ можно было бы
вычислять X51 одновременно с X1, на втором шаге X52 параллельно с X2 и т. д. Идея алгоритма состоит в том, чтобы предварительно вычислить элемент X50 при помощи суперпозиции отображений G1, G2, ..., G50.
Описание алгоритма
Алгоритм состоит из трех этапов:
1. Вычисление (P − 1)-ого отображения Qi = G 2, ..., P − 1; j = ((i − 1)N/P) + 1) через суперпозиции N/P исходных отобра­жений (рисунок 18).
j −1+N / P
◦···◦G
j +1Gj
(где i = 1,
Рисунок 18. Коммуникационная сеть «звезда».
Псевдокод, соответствующий первому этапу алгоритма:
for (i = 0; i < P-1; i++) { k = ((i+1)*N)/P; Q[i] = G[k]; for(j = 1; j < N/P; j++) Q[i] = Superposition(Q[i], G[k-j]); }
2. Вычисление элементов X
N/ P
, X
2 N/ P
, ..., X
(P − 1) N/P
зиций, вычисленных на первом этапе (рисунок 19).
посредством суперпо-
Алгоритмы решения СЛАУ с блочно-ленточными матрицами. Глава 4 77
Рисунок 19. Коммуникационная сеть «звезда».
Псевдокод, соответствующий второму этапу алгоритма:
for(i = 0; i < P-1; i++) { X[((i+1)*N)/P] = Q[i](X[(i*N)/P]); }
3. Вычисление элементов X
всеми P ВУ, начиная с X0 и элементов, вы-
i
численных на втором этапе алгоритма (рисунок 20). Псевдокод, соответ­ствующий третьему этапу алгоритма:
for(i = 0; i < P; i++) { for(j = 0; j < N/P — 1; j++) { X[(i*N)/P + j+1] = G
(X[(i*N)/P + j])
j
}}
Заметим, что внешний цикл допускает параллельное выполнение.
Рисунок 20. Коммуникационная сеть «звезда».
Рассмотрим применение алгоритма к циклу с аффинной рекуррентной
зависимостью при условии, что распараллеливание ведется на два ВУ.
Пример 34. Применим алгоритм к циклу с аффинной рекуррентной зависимостью (см. пример 33). На первом этапе будет получена су­перпозиция, позволяющая вычислить элемент X
AA = A[N/2]*A[N/2-1]; BB = A[N/2]*B[N/2-1]+B[N/2]; for (j = N/2-2; 0 < j; j--) { BB = AA*B[j]+BB; AA = AA*A[j]; }
Вторым этапом, с помощью суперпозиции, полученной на первом этапе, вычисляется элемент X
X[N/2] = AA*X[0]+BB;
N/2
:
через X0:
N/2
78 Б. Я. Штейнберг, О. Б. Штейнберг
На третьем этапе оба ВУ ведут вычисления своей половины эле­ментов Xi:
for (j = 1; j < N/2; j++)
// вычисления для первого ВУ
X[j] = A[j]*X[j-1]+B[j]; for (j = N/2+1; j <= N; j++) // вычисления для второго ВУ X[j] = A[j]*X[j-1]+B[j];
Конец примера.
Стоит отметить, что вычислять суперпозиции на первом этапе можно,
используя принцип сдваивания [66].
Пример 35. Ассоциативность операции суперпозиция позво­ляет производить вычисления суперпозиций в выражении
G8◦G7◦G6◦G5◦G4◦G3◦G2◦G1 различными способами.
Вычисления можно производить последовательно
◦(G7◦(G6◦(G5◦(G4◦(G3◦(G2◦G1))))))
1) G
8
а можно использовать принцип сдваивания
2) (((G
Хотя от порядка выполняемых операций их количество не зависит (их в обоих случаях 7), зато у каждого из способов есть свои особенно­сти. В частности, при использовании принципа сдваивания некоторые операции можно вычислять параллельно (например, суперпозицию отображений G цией отображений G6 и G5). В качестве недостатка применения прин­ципа сдваивания можно выделить необходимость хранения данных, описывающих результаты промежуточных вычислений. При последо­вательном вычислении результат очередных вычислений будет запи­сываться вместо предыдущего результата.
)◦(G6◦G5))◦((G4◦G3)◦(G2◦G1)))
8◦G7
и G7 можно вычислять одновременно с суперпози-
8
Конец примера.
Оценка сложности
Рассмотрим оценку сложности алгоритма, содержащую параметры, за­висящие от используемого «железа». Оценка будет построена для случаев, когда Gi принадлежат одному классу рекуррентно замкнутых отображений.
Ввиду замкнутости отображений этого класса, относительно операции суперпозиция, можно говорить о следующих константах:
T
superposition
T
function
ности с помощью отображения;
T
read
— время вычисления суперпозиции;
— время, затрачиваемое на вычисление элемента последователь-
— время, затрачиваемое на чтение из одной ячейки памяти;
Алгоритмы решения СЛАУ с блочно-ленточными матрицами. Глава 4 79
T
— время, затрачиваемое на запись в одну ячейку памяти;
write
Data — количество данных, используемых для описания отображения.
Заметим, что отображение, описывающее аффинную рекуррентную
зависимость примера 1, состоит из двух коэффициентов A и B, что дает Data = 2, а дробно-аффинную примера 5 дает Data = 4. Сложность алгорит- ма рассматривается с точки зрения вычислений и с точки зрения обраще­ний к памяти.
Последовательное выполнение. При последовательном выполнении
цикла вычисляется N элементов массива X с использованием отображе-
. Таким образом, вычислительная сложность алгоритма составляет
ний G
i
N T
. Сложность по обращениям к памяти последовательного алгорит-
function
ма состоит из записи N элементов X и чтения данных, используемых при вычислениях. Итого сложность алгоритма по обращениям к памяти равна
N T
равна N T
+ N Data T
write
function
+ N T
. Из вышесказанного общая сложность алгоритма
read
+ N Data T
write
read
.
Параллельное выполнение с использованием описанного алгорит-
ма. На первом этапе находится P − 1 отображение Qi (где i = 1, 2, ..., P − 1).
При вычислении каждого отображения применяется N/P − 1 суперпози­ция, т. е. ((N /P − 1) (P − 1)) T
superposition
. Все суперпозиции можно вычис­лять на P − 1 ВУ параллельно. Итого время выполнения получается равным (N / P − 1) T
superposition
сива X. Эти элементы вычисляются за время (P − 1) T
. На втором этапе вычисляется всего P − 1 элемент мас-
. Отметим, что
function
вычисление этих же элементов последовательным алгоритмом занимает та­кое же время. Третий этап алгоритма состоит в параллельном вычислении оставшихся элементов массива X. Это занимает ((N −(P − 1))/P) T В итоге вычислительная сложность составляет (N/ P − 1) T
* T
+ ((N −(P − 1))/P) T
function
. Рассмотрим сложность алго рит ма по
function
superposition
function
(P − 1)
обращениям к памяти. На первом этапе алгоритма считываются данные, необходимые для вычисления суперпозиций. Это занимает (P − 1) (N/P)
* Data T
. Если суперпозиции вычислять последовательно, то данные,
read
относящиеся к промежуточным суперпозициям (или промежуточные су­перпозиции) могут быть перезаписаны. Откуда получается, что в ито­ге первого этапа потребуется записать лишь данные, соответствующие (P − 1)-ому отображению Qi (где i = 1, 2, ..., P − 1) , т. е. (P − 1) Data T
write
На втором и третьем этапе производятся вычисления, аналогичные после­довательному вычислению цикла; соответственно, сложность по обраще­ниям к памяти совпадает со сложностью при последовательном выпол-
.
.
80 Б. Я. Штейнберг, О. Б. Штейнберг
нении N T (P − 1) (N/P) Data T
+ N Data T
write
. Итого время выполнения алгоритма равно
read
+(P − 1) Data T
read
write
+ N T
+ N Data T
write
read
.
Заметим, что оценка времени написана для общего случая и должна уточ­няться исходя из конкретной вычислительной архитектуры. Так, например, если вычисления производятся на архитектуре с кэш-памятью, то данные, счи­тываемые для вычисления суперпозиций на первом этапе, будут храниться в кэш-памяти и не будут повторно считываться из медленной оперативной памя­ти на третьем этапе. Кроме того, элементы могут считываться не по одному, а целыми кэш-линейками, да притом еще и несколькими каналами чтения.
Численные эксперименты
Тестирование быстродействия алгоритма проводилось на трех компьютерах:
1. Процессор Intel CoreTM i3–3227U 1.9GHz, оперативная память 4GB
DDR3.
2. Процессор Intel Core i7–3820 3.60GHz, оперативная память 8GB
DDR3.
3. Процессор Intel(R) Xeon(R) Gold 6242 2.80GHz, оперативная память
384GB DDR4.
Алгоритм применялся к циклу с аффинной рекуррентной зависимо­стью, вычисляющему 67 108 864 элемента. Распараллеливания проводи­лось с использованием OpenMP 4.0. Результаты тестирования приведены в таблицах 1, 2, 3.
Таблица 1. Результаты тестирования быстродействия алгоритма
в случае аффинной рекуррентной зависимости
Процессор Последовательное
выполнение (сек.)
Intel i3 0.484124 0.262585 1.8436 Intel i7 0.383944 0.210152 1.8269
Выполнение 4-мя
потоками (сек.)
Ускорение
Таблица 2. Результаты тестирования быстродействия алгоритма
в случае дробно-линейной рекуррентной зависимости
Процессор Последовательное
выполнение (сек.)
Intel i3 1.23998 0.661197 1.8753 Intel i7 0.630645 0.314366 2.006
Выполнение 4-мя
потоками (сек.)
Ускорение
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]