Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added 4_OptimalSpeedIterativeAlgorithm #228

Merged
merged 1 commit into from
Jun 23, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions Documentation/4_OptimalSpeedIterativeAlgorithm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

### Итерационный алгоритм с оптимальной скоростью работы после перенумерации блоков
#### Постановка задачи
Необходимо улучшить сходимость итерационного алгоритма, посещая узлы графа в соответствии с их упорядочением в глубину.
#### Команда
Д. Володин, Н. Моздоров
#### Зависимые и предшествующие задачи
Предшествующие:
- Алгоритм упорядочения в глубину
- Итерационный алгоритм в обобщённой структуре

Зависимые:
- Анализ активных переменных
- Анализ достигающих определений
- Анализ доступных выражений

#### Теоретическая часть
Максимальное количество итераций итеративного алгоритма равно высоте полурешетки, умноженной на количество узлов графа. Во многих анализах вычисления можно упорядочить так, что алгоритм будет сходиться за существенно меньшее количество итераций. В частности, если события распространяются вдоль некоторого ациклического пути и пути с циклами ничего не добавляют, то сходимость можно существенно улучшить.

Если информация распространяется только вдоль ациклических путей, то можно подобрать порядок посещения узлов (базовых блоков) так, чтобы после небольшого количества проходов алгоритм сходился. Для задач в прямом направлении необходимо посещать узлы в
соответствии с их упорядочением в глубину.

#### Практическая часть
Данная задача была выполнена следующим образом. В сигнатуру метода `Execute` обобщённого итерационного алгоритма был добавлен параметр `useRenumbering` типа `bool`, и если этот параметр равняется `true`, то в самом начале итеративного алгоритма базовые блоки сортируются по глубине в графе потока управления. Если алгоритм выполняется в обратном направлении, то блоки сортируются в обратном порядке.
```
if (useRenumbering)
{
blocks = Direction == Direction.Backward
? blocks.OrderByDescending(z => graph.DepthFirstNumeration[graph.VertexOf(z)])
: blocks.OrderBy(z => graph.DepthFirstNumeration[graph.VertexOf(z)]);
}
```

Также в класс обобщённого алгоритма было добавлено поле `Iterations` для оценки количества итераций, выполненных алгоритмом.

#### Место в общем проекте (Интеграция)
Данная оптимизация встроена в обобщённый итеративный алгоритм и используется по умолчанию (чтобы отказаться от обхода блоков графа с упорядочением по глубине, нужно явно указать параметр `useRenumbering = false`).

#### Тесты
В тестах проверяется, что для созданных ранее итерационных алгоритмов количество итераций, совершённое с упорядочением блоков, не превосходит количество итераций без упорядочения. Ниже представлен тест для алгоритма анализа достигающих определений.
```
public void ReachingDefinitionsTest()
{
var program = @"
var i, m, j, n, a, u1, u2, u3, k;
1: i = m - 1;
2: j = n;
3: a = u1;

for k = 0, 1
{
i = i + 1;
j = j - 1;

if i < j
a = u2;
i = u3;
}";
var graph = GenCFG(program);
var algorithm = new LiveVariableAnalysis();

algorithm.Execute(graph);
var iterationsFast = algorithm.Iterations;
algorithm.Execute(graph, false);
var iterationsSlow = algorithm.Iterations;

Assert.LessOrEqual(iterationsFast, iterationsSlow);
}
```