Уровень алгоритма

Участник:Error0x0/Алгоритм Ланцоша для арифметики с плавающей точкой с полной переортогонализацией: различия между версиями

Материал из Алговики
Перейти к навигации Перейти к поиску
 
(не показано 39 промежуточных версий 2 участников)
Строка 1: Строка 1:
  
  
= ЧАСТЬ. Свойства и структура алгоритмов =
+
{{algorithm
 +
| name              = Алгоритм Ланцоша для арифметики с плавающей точкой с полной переортогонализацией
 +
| serial_complexity = <math>O(k^2 n)</math>
 +
| pf_height        = <math>O(k \log k \log n)</math>
 +
| pf_width          = <math>O(kn)</math>
 +
| input_data        = <math>n^2</math>
 +
| output_data      = <math>n</math>
 +
}}
 +
Автор описания: [[Участник:Error0x0|В. А. Янушковский]]
 +
 
 +
= Свойства и структура алгоритма =
  
 
== Общее описание алгоритма ==
 
== Общее описание алгоритма ==
 
Алгоритм Ланцоша представляет собой итерационный алгоритм для вычисления собственных значений симметрической матрицы.  
 
Алгоритм Ланцоша представляет собой итерационный алгоритм для вычисления собственных значений симметрической матрицы.  
Идея алгоритма заключается в построении матрицы <math>Q_k = [q_1, ..., q_k]</math> из ортонормированных векторов Ланцоша и нахождении собственных значений трёхдиагональной матрицы <math>T_k = Q_k^T A Q_k</math>.
+
Идея алгоритма заключается в построении матрицы <math>Q_k = [q_1, ..., q_k]</math> из ортонормированных векторов Ланцоша и использовании собственных значений трёхдиагональной матрицы <math>T_k = Q_k^T A Q_k</math> (чисел Ритца) как приближения к искомым собственным числам матрицы<ref name="Деммель">Деммель&nbsp;Дж. Вычислительная линейная алгебра</ref>.
  
 
== Математическое описание алгоритма ==
 
== Математическое описание алгоритма ==
Строка 14: Строка 24:
 
# производится переортогонализация <math>z = z - \sum^{j-1}_{i=1} {(z^T q_i)q_i}</math>,
 
# производится переортогонализация <math>z = z - \sum^{j-1}_{i=1} {(z^T q_i)q_i}</math>,
 
# <math>\beta_j = ||z||_2</math>, если <math>\beta_j = 0</math>, алгоритм останавливается,
 
# <math>\beta_j = ||z||_2</math>, если <math>\beta_j = 0</math>, алгоритм останавливается,
# <math>q_j+1 = z/\beta_j</math>,
+
# <math>q_{j+1} = z/\beta_j</math>,
 
# вычисляются собственные значения и векторы матрицы <math>T_j = Q_j^T A Q_j</math>.
 
# вычисляются собственные значения и векторы матрицы <math>T_j = Q_j^T A Q_j</math>.
  
 
== Вычислительное ядро алгоритма ==
 
== Вычислительное ядро алгоритма ==
Основной вклад в сложность алгоритма даёт полная переортогонализация
+
Основной вклад в сложность алгоритма даёт полная переортогонализация внутри каждой итерации:
 +
 
 +
<math>z = z - \sum^{j-1}_{i=1} {(z^T q_i)q_i}</math>
  
 
== Макроструктура алгоритма ==
 
== Макроструктура алгоритма ==
Основные элементы алгоритма:
+
Алгоритм имеет следующую макроструктуру:
* Нахождение векторов Ланцоша
+
* Начальная инициализация (деление вектора на норму <math>q_1 = b/||b||_2</math>)
* Полная переортогонализация (Грамма-Шмидта)
+
* Далее <math>k</math> итераций, каждая из которых может быть разложена:
* Вычисление собственных значений и векторов матрицы <math>T_j</math> (числа Ритца)
+
** Умножение матрицы на вектор (<math>z = Aq_j</math>)
 +
** Переортогонализация <math>z = z - \sum^{j-1}_{i=1} {(z^T q_i)q_i}</math>
 +
** Нахождение следующего вектора <math>q_{j+1} = z/\beta_j</math>, где <math>\beta_j = ||z||_2</math>
 +
** Нахождение следующего собственного значения и вектора матрицы <math>T_j = Q_j^T A Q_j</math> (числа Ритца, используется метод "разделяй и властвуй")
  
 
== Схема реализации последовательного алгоритма ==
 
== Схема реализации последовательного алгоритма ==
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
q[1] = b / norm(b)
+
beta[0] = 0 # инициализация
beta[0] = 0
 
 
q[0] = 0
 
q[0] = 0
for j in [1 .. k]:
+
q[1] = b / norm(b) # вычисление первого столбца
     z = mul(A, q[j])
+
for j in [1 .. k]: # k итераций
     for i in [1 .. j - 1]:
+
     z = mul(A, q[j]) # вектор Ланцоша как произведение матрицы A на столбец q[j]
         z -= mul(scalar_mul(transpose(z),q[i]), q[i])
+
    alpha[j] = scalar_mul(q[j], z) # вычисление alpha[j]
     beta[j] = norm(z)
+
     for i in [1 .. j - 1]: # полная переортогонализация
     if beta[j] == 0:
+
         z -= scalar_mul(z, q[i]) * q[i]
 +
     beta[j] = norm(z) # вычисление нормы z
 +
     if beta[j] == 0: # останов, если норма z равна нулю
 
         break
 
         break
     result = ritz_numbers(mul(transpose(Q[j]), A, Q[j]))
+
     result.append(next_ritz_number(alpha, beta, j)) # вычисление следующего собственного значения и вектора матрицы Tj
 
return result
 
return result
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
== Последовательная сложность алгоритма ==
 
== Последовательная сложность алгоритма ==
Для метода с полной переортогонализацией сложность составляет <math>O(k^2 n)</math>, сложность по памяти -- <math>O(kn)</math>.
+
 
 +
Основной вклад в сложность даёт полная переортогонализация: на каждой из <math>k</math> итераций для всех <math>i \in [0...j-1]</math> выполняется <math>2n</math> умножений и <math>2n</math> сложений, итого <math>\frac{k(k-1)}{2} 4n \approx 2k^2 n</math>.
 +
Таким образом, для метода с полной переортогонализацией сложность составляет <math>O(k^2 n)</math>, сложность по памяти -- <math>O(kn)</math>.
  
 
== Информационный граф ==
 
== Информационный граф ==
 
+
На рисунке приведён информационный граф одной итерации алгоритма
 +
[[File:Lanczos graph.png|thumb|center|800px|Рисунок 1. Информационный граф итерации алгоритма]]
  
 
== Ресурс параллелизма алгоритма ==
 
== Ресурс параллелизма алгоритма ==
 
+
Для процесса переортогонализации возможна параллельная оптимизация в двух местах:
 +
* Итерации внутреннего цикла могут вычисляться параллельно, однако, требуется суммирование вычитаемых векторов, соответственно, сложность переортогонализации можно снизить с <math>O(kn)</math> до <math>O(n \log k)</math>
 +
* В каждой итерации внутреннего цикла возможно распараллеливание вычисления выражения справа (скалярное произведение и умножение вектора на число), что теоретически позволяет снизить сложность итерации с <math>O(n)</math> до <math>O(log(n))</math>
  
 
== Входные и выходные данные алгоритма ==
 
== Входные и выходные данные алгоритма ==
 
'''Входные данны'''е: квадратная симметрическая матрица <math>A</math> порядка <math>n</math>
 
'''Входные данны'''е: квадратная симметрическая матрица <math>A</math> порядка <math>n</math>
 +
 
'''Объём входных данных''': <math>n^2</math>
 
'''Объём входных данных''': <math>n^2</math>
 +
 
'''Выходные данные''': собственные числа матрицы
 
'''Выходные данные''': собственные числа матрицы
 +
 
'''Объём выходных данных''': <math>n</math>
 
'''Объём выходных данных''': <math>n</math>
  
Строка 61: Строка 85:
 
Однако, единственной проблемой, возникающей при отсутствии переортогонализации, является появление повторных копий чисел Ритца (собственных значений), что в случае, если не требуется установление кратностей собственных значений, допустимо.
 
Однако, единственной проблемой, возникающей при отсутствии переортогонализации, является появление повторных копий чисел Ритца (собственных значений), что в случае, если не требуется установление кратностей собственных значений, допустимо.
  
= ЧАСТЬ. Программная реализация алгоритма =
+
Вычислительная мощность алгоритма примерно равна <math>2k^2 / n</math>.
 +
 
 +
= Программная реализация алгоритма =
  
  
Строка 74: Строка 100:
 
== Масштабируемость алгоритма и его реализации ==
 
== Масштабируемость алгоритма и его реализации ==
  
 +
Исследование масштабируемости алгоритма проводилось на суперкомпьютере IBM Blue Gene/P ВМК МГУ.
 +
 +
Алгоритм тестировался на следующих параметрах:
 +
* размер входной матрицы: 2048-8192 с шагом 512
 +
* число узлов: 1-256   
 +
 +
Зависимость времени выполнения от параметров изображена на графике:
 +
 +
[[Файл:Lanczos full chart.png|center|border |800px]]
 +
Из рисунка видно, что алгоритм хорошо масштабируется, время выполнения на одном ядре растёт существенно быстрее чем на множестве ядер. При этом, для маленькой матрице на большом числе ядер прирост эффективности практически отсутствует.
 +
 +
[http://pastebin.com/u7KThy6D  Используемая реализация алгоритма на языке C++]
 +
 +
Пример компиляции и запуска:
 +
  $ mpixlcxx_r -o lanczos lanczos.cpp
 +
  $ mpisubmit.bg -n 256 -w 00:5:00 lanczos
  
 
== Динамические характеристики и эффективность реализации алгоритма ==
 
== Динамические характеристики и эффективность реализации алгоритма ==
Строка 81: Строка 123:
  
 
== Существующие реализации алгоритма ==
 
== Существующие реализации алгоритма ==
 +
Библиотека [http://www.nag.co.uk/numeric/fl/nagdoc_fl23/html/INDEXES/KWIC/lanczos.html NAG Library] содержит ряд процедур для решения СЛАУ и поиска собственных значений на основе алгоритма Ланцоша.
  
= Литература =
+
[http://www.mathworks.com/help/techdoc/ref/eigs.html MATLAB] и [https://www.gnu.org/software/octave/doc/interpreter/Sparse-Linear-Algebra.html#doc_002deigs GNU Octave] позволяют с помощью функции ''eigs()'' находить собственные значения на основе данного алгоритма.
[1] Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.
 
  
[2] Воеводин В.В., Воеводин Вад.В. Спасительная локальность суперкомпьютеров //Открытые системы. - 2013. - № 9. - С. 12-15.
+
Matlab-реализация доступна как часть [http://www.cs.cmu.edu/~bickson/gabp/#download Gaussian Belief Propagation Matlab Package]. [http://www.graphlab.ml.cmu.edu/pmf.html GraphLab] содержит несколько параллельных реализаций алгоритма на C++.
  
[3] Воеводин Вад.В., Швец П. Метод покрытий для оценки локальности использования данных в программах // Вестник УГАТУ. — 2014. — Т. 18, № 1(62). — С. 224–229.
+
= Литература =
 
 
[4] Антонов А.С., Теплов А.М. О практической сложности понятия масштабируемости параллельных программ// Высокопроизводительные параллельные вычисления на кластерных системах (HPC 2014): Материалы XIV Международной конференции -Пермь: Издательство ПНИПУ, 2014. С. 20-27.
 
 
 
[5] Никитенко Д.А. Комплексный анализ производительности суперкомпьютерных систем, основанный на данных системного мониторинга // Вычислительные методы и программирование. 2014. 15. 85–97.
 

Текущая версия на 20:34, 11 февраля 2017



Алгоритм Ланцоша для арифметики с плавающей точкой с полной переортогонализацией
Последовательный алгоритм
Последовательная сложность [math]O(k^2 n)[/math]
Объём входных данных [math]n^2[/math]
Объём выходных данных [math]n[/math]
Параллельный алгоритм
Высота ярусно-параллельной формы [math]O(k \log k \log n)[/math]
Ширина ярусно-параллельной формы [math]O(kn)[/math]

Автор описания: В. А. Янушковский

1 Свойства и структура алгоритма

1.1 Общее описание алгоритма

Алгоритм Ланцоша представляет собой итерационный алгоритм для вычисления собственных значений симметрической матрицы. Идея алгоритма заключается в построении матрицы [math]Q_k = [q_1, ..., q_k][/math] из ортонормированных векторов Ланцоша и использовании собственных значений трёхдиагональной матрицы [math]T_k = Q_k^T A Q_k[/math] (чисел Ритца) как приближения к искомым собственным числам матрицы[1].

1.2 Математическое описание алгоритма

Пусть дана матрица [math]A[/math]. Пусть [math]q_1 = b/||b||_2, \beta_0=0, q_0=0[/math] Алгоритм производит [math]k[/math] итераций на каждой из которых:

  1. вычисляется [math]z = Aq_j[/math],
  2. производится переортогонализация [math]z = z - \sum^{j-1}_{i=1} {(z^T q_i)q_i}[/math],
  3. [math]\beta_j = ||z||_2[/math], если [math]\beta_j = 0[/math], алгоритм останавливается,
  4. [math]q_{j+1} = z/\beta_j[/math],
  5. вычисляются собственные значения и векторы матрицы [math]T_j = Q_j^T A Q_j[/math].

1.3 Вычислительное ядро алгоритма

Основной вклад в сложность алгоритма даёт полная переортогонализация внутри каждой итерации:

[math]z = z - \sum^{j-1}_{i=1} {(z^T q_i)q_i}[/math]

1.4 Макроструктура алгоритма

Алгоритм имеет следующую макроструктуру:

  • Начальная инициализация (деление вектора на норму [math]q_1 = b/||b||_2[/math])
  • Далее [math]k[/math] итераций, каждая из которых может быть разложена:
    • Умножение матрицы на вектор ([math]z = Aq_j[/math])
    • Переортогонализация [math]z = z - \sum^{j-1}_{i=1} {(z^T q_i)q_i}[/math]
    • Нахождение следующего вектора [math]q_{j+1} = z/\beta_j[/math], где [math]\beta_j = ||z||_2[/math]
    • Нахождение следующего собственного значения и вектора матрицы [math]T_j = Q_j^T A Q_j[/math] (числа Ритца, используется метод "разделяй и властвуй")

1.5 Схема реализации последовательного алгоритма

beta[0] = 0 # инициализация
q[0] = 0
q[1] = b / norm(b) # вычисление первого столбца
for j in [1 .. k]: # k итераций
    z = mul(A, q[j]) # вектор Ланцоша как произведение матрицы A на столбец q[j]
    alpha[j] = scalar_mul(q[j], z) # вычисление alpha[j]
    for i in [1 .. j - 1]: # полная переортогонализация
        z -= scalar_mul(z, q[i]) * q[i]
    beta[j] = norm(z) # вычисление нормы z
    if beta[j] == 0: # останов, если норма z равна нулю
        break
    result.append(next_ritz_number(alpha, beta, j)) # вычисление следующего собственного значения и вектора матрицы Tj
return result

1.6 Последовательная сложность алгоритма

Основной вклад в сложность даёт полная переортогонализация: на каждой из [math]k[/math] итераций для всех [math]i \in [0...j-1][/math] выполняется [math]2n[/math] умножений и [math]2n[/math] сложений, итого [math]\frac{k(k-1)}{2} 4n \approx 2k^2 n[/math]. Таким образом, для метода с полной переортогонализацией сложность составляет [math]O(k^2 n)[/math], сложность по памяти -- [math]O(kn)[/math].

1.7 Информационный граф

На рисунке приведён информационный граф одной итерации алгоритма

Рисунок 1. Информационный граф итерации алгоритма

1.8 Ресурс параллелизма алгоритма

Для процесса переортогонализации возможна параллельная оптимизация в двух местах:

  • Итерации внутреннего цикла могут вычисляться параллельно, однако, требуется суммирование вычитаемых векторов, соответственно, сложность переортогонализации можно снизить с [math]O(kn)[/math] до [math]O(n \log k)[/math]
  • В каждой итерации внутреннего цикла возможно распараллеливание вычисления выражения справа (скалярное произведение и умножение вектора на число), что теоретически позволяет снизить сложность итерации с [math]O(n)[/math] до [math]O(log(n))[/math]

1.9 Входные и выходные данные алгоритма

Входные данные: квадратная симметрическая матрица [math]A[/math] порядка [math]n[/math]

Объём входных данных: [math]n^2[/math]

Выходные данные: собственные числа матрицы

Объём выходных данных: [math]n[/math]

1.10 Свойства алгоритма

Полная переортогонализация соответствует повторной процедуре ортогонализациии Грама-Шмидта для обеспечения ортогональности вектора [math]z[/math] векторам [math]q_1, ..., q_k[/math]. В случае идеально точной арифметики данная переортогонализация не требовалась бы, однако в реальных вычислениях ошибки округления приводят к потере ортогональности, в связи с чем требуется переортогонализация. Однако, единственной проблемой, возникающей при отсутствии переортогонализации, является появление повторных копий чисел Ритца (собственных значений), что в случае, если не требуется установление кратностей собственных значений, допустимо.

Вычислительная мощность алгоритма примерно равна [math]2k^2 / n[/math].

2 Программная реализация алгоритма

2.1 Особенности реализации последовательного алгоритма

2.2 Локальность данных и вычислений

2.3 Возможные способы и особенности параллельной реализации алгоритма

2.4 Масштабируемость алгоритма и его реализации

Исследование масштабируемости алгоритма проводилось на суперкомпьютере IBM Blue Gene/P ВМК МГУ.

Алгоритм тестировался на следующих параметрах:

  • размер входной матрицы: 2048-8192 с шагом 512
  • число узлов: 1-256

Зависимость времени выполнения от параметров изображена на графике:

Lanczos full chart.png

Из рисунка видно, что алгоритм хорошо масштабируется, время выполнения на одном ядре растёт существенно быстрее чем на множестве ядер. При этом, для маленькой матрице на большом числе ядер прирост эффективности практически отсутствует.

Используемая реализация алгоритма на языке C++

Пример компиляции и запуска:

 $ mpixlcxx_r -o lanczos lanczos.cpp
 $ mpisubmit.bg -n 256 -w 00:5:00 lanczos

2.5 Динамические характеристики и эффективность реализации алгоритма

2.6 Выводы для классов архитектур

2.7 Существующие реализации алгоритма

Библиотека NAG Library содержит ряд процедур для решения СЛАУ и поиска собственных значений на основе алгоритма Ланцоша.

MATLAB и GNU Octave позволяют с помощью функции eigs() находить собственные значения на основе данного алгоритма.

Matlab-реализация доступна как часть Gaussian Belief Propagation Matlab Package. GraphLab содержит несколько параллельных реализаций алгоритма на C++.

3 Литература

  1. Деммель Дж. Вычислительная линейная алгебра