Распараллеливание схемы Горнера
Постановка задачи и суть проблемы
Классический пример рекурсии в алгоритме - схема Горнера для вычисления частного от деления многочлена n-й степени одной переменной Pn(x) = a0xn + a1xn-1 + ... + an-1x + a на двучлен x - c, с получением многочлена n-1-й степени Qn-1(x) = b0xn-1 + b1xn-2 + ... + bn-2x + bn-1 и остатка от деления bn (равного Pn(с)). При этом у нас искомые коэффициенты и остаток вычисляются по рекуррентной формуле: bi = c bi-1 + ai.
Казалось бы, нам ничего не поделать с последовательным характером алгоритма. Однако в том случае, если нам можно воспользоваться ассоциативностью и дистрибутивностью сложения и умножения, то мы можем распараллелить схему Горнера, воспользовавшись обычной схемой сдваивания.
Схема сдваивания
Пусть нам нужно вычислить все частичные суммы элементов yi от 1 до k, где 1 ≤ k ≤ n. Оказывается, что это возможно сделать по схеме сдваивания примерно за log2n шагов, выполняя на каждом шаге примерно по n/2 сложений. Приведём пример вычисления всех частных сумм для n=8 за 3 шага.
1-й шаг: вычисляем y1 +
y2,
y3 +
y4, y5
+ y6, y7
+ y8.
2-й шаг: вычисляем (y1 + y2)
+ y3 ,
(y1 + y2)
+ (y3
+ y4), (y5 + y6)
+ y7,
(y5 + y6)
+ (y7
+ y8).
3-й шаг: вычисляем (y1
+ y2 + y3 + y4)
+ y5,
(y1
+ y2 + y3 + y4)
+ (y5
+ y6), (y1
+ y2 + y3 + y4)
+ (y5
+ y6 + y7), (y1
+ y2 + y3 + y4)
+ (y5
+ y6 + y7 + y8)
Как видим, все частные суммы вычислены. Отмечаем про себя то, что
- мы воспользовались ассоциативностью сложения и что
- общее количество операций возросло (чего не было бы, если б нам была нужна только полная сумма, но не нужны частичные).
Распараллеливание схемы Горнера
Перепишем схему Горнера в векторной формулировке. Введём последовательность векторов zi = ( bi, 1)T. Тогда рекуррентные формулы схемы Горнера примут вид: zi = Aizi-1, где Ai - треугольная матрица вида ( (c, 0)T, (ai, 1)T). После подстановки всех формул мы видим, что zi = AiAi-1...A1z0, то есть нам нужно вычислить все частные матричные произведения AiAi-1...A1, после чего умножить их на вектор z0. Но матричное умножение ассоциативно, и к вычислениям частных произведений мы можем применить схему сдваивания, причём с упрощениями - ведь
- нижние строки матриц нам вычислять не нужно - они все равны (0, 1);
- в верхней строке матрицы первый элемент вычисляется за 1 умножение (второе слагаемое равно 0);
- второй элемент первой строки вычисляется за 1 умножение и 1 сложение (второе умножение - на 1 - выполнять не нужно).