Algorithm level

Difference between revisions of "Bellman-Ford algorithm"

From Algowiki
Jump to navigation Jump to search
[quality revision][quality revision]
(52 intermediate revisions by one other user not shown)
Line 1: Line 1:
 
{{algorithm
 
{{algorithm
| name              = Алгоритм Беллмана-Форда
+
| name              = Bellman-Ford algorithm
 
| serial_complexity = <math>O(|V||E|)</math>
 
| serial_complexity = <math>O(|V||E|)</math>
 
| pf_height        = <math>N/A, max O(|V|) </math>
 
| pf_height        = <math>N/A, max O(|V|) </math>
Line 12: Line 12:
 
=== General description of the algorithm ===
 
=== General description of the algorithm ===
  
'''Алгоритм Беллмана-Форда'''<ref>Bellman, Richard. “On a Routing Problem.” Quarterly of Applied Mathematics 16 (1958): 87–90.</ref><ref>Ford, L R. Network Flow Theory. Rand.org, RAND Corporation, 1958.</ref><ref>Moore, Edward F. “The Shortest Path Through a Maze,” International Symposium on the Theory of Switching, 285–92, 1959.</ref> предназначен для решения [[Поиск кратчайшего пути от одной вершины (SSSP)|задачи поиска кратчайшего пути на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния от выделенной вершины-источника до всех остальных вершин графа. Алгоритм Беллмана-Форда масштабируется хуже других алгоритмов решения указанной задачи (сложность <math>O(|V||E|)</math> против <math>O(|E| + |V|\ln(|V|))</math> у [[Алгоритм Дейкстры|алгоритма Дейкстры]]), однако его отличительной особенностью является применимость к графам с произвольными, в том числе отрицательными, весами.
+
The '''Bellman-Ford algorithm'''<ref>Bellman, Richard. “On a Routing Problem.” Quarterly of Applied Mathematics 16 (1958): 87–90.</ref><ref>Ford, L R. Network Flow Theory. Rand.org, RAND Corporation, 1958.</ref><ref>Moore, Edward F. “The Shortest Path Through a Maze,” International Symposium on the Theory of Switching, 285–92, 1959.</ref> was designed for [[Поиск кратчайшего пути от одной вершины (SSSP)|finding the shortest paths between nodes in a graph]]. For a given weighted digraph, the algorithm finds the shortest paths between a singled-out source node and the other nodes of the graph. The Bellman-Ford algorithm scales worse than other algorithms for solving this problem (the complexity is <math>O(|V||E|)</math> against <math>O(|E| + |V|\ln(|V|))</math> for [[Алгоритм Дейкстры|Dijkstra's algorithm]]). However, its distinguishing feature is the applicability to graphs with arbitrary (including negative) weights.
  
 
=== Mathematical description of the algorithm ===
 
=== Mathematical description of the algorithm ===
  
Пусть задан граф <math>G = (V, E)</math> с весами рёбер <math>f(e)</math> и выделенной вершиной-источником <math>u</math>. Обозначим через <math>d(v)</math> кратчайшее расстояние от источника <math>u</math> до вершины <math>v</math>.
+
Let <math>G = (V, E)</math> be a given graph with arc weights <math>f(e)</math>  
 +
f(e) and the single-out source node <math>u</math>. Denote by <math>d(v)</math> the shortest distance between the source node <math>u</math> and the node <math>v</math>.
  
Алгоритм Беллмана-Форда ищет функцию <math>d(v)</math> как единственное решение уравнения
+
The Bellman-Ford algorithm finds the value <math>d(v)</math> as the unique solution to the equation
 
:<math>
 
:<math>
 
         d(v) = \min \{ d(w) + f(e) \mid e = (w, v) \in E \}, \quad \forall v \ne u,
 
         d(v) = \min \{ d(w) + f(e) \mid e = (w, v) \in E \}, \quad \forall v \ne u,
 
</math>
 
</math>
с начальным условием <math>d(u) = 0</math>.
+
with the initial condition <math>d(u) = 0</math>.
  
 
=== Computational kernel of the algorithm ===
 
=== Computational kernel of the algorithm ===
  
Основной операцией алгоритма является релаксация ребра: если <math>e = (w, v) \in E</math> и <math>d(v) > d(w) + f(e)</math>, то производится присваивание <math>d(v) \leftarrow d(w) + f(e)</math>.
+
The algorithm is based on the principle of arc relaxation: if <math>e = (w, v) \in E</math> and <math>d(v) > d(w) + f(e)</math>, then the assignment <math>d(v) \leftarrow d(w) + f(e)</math> is performed.
  
 
=== Macro structure of the algorithm ===
 
=== Macro structure of the algorithm ===
  
Алгоритм последовательно уточняет значения функции <math>d(v)</math>.
+
The algorithm successively refines the values of the function <math>d(v)</math>.
* В самом начале производится присваивание <math>d(u) = 0</math>, <math>d(v) = \infty</math>, <math>\forall v \ne u</math>.
+
* At the very start, the assignment <math>d(u) = 0</math>, <math>d(v) = \infty</math>, <math>\forall v \ne u</math> is performed.  
* Далее происходит <math>|V|-1</math> итерация, в ходе каждой из которых производится релаксация всех рёбер графа.
+
* Then <math>|V|-1</math> iteration steps are executed. At each step, all the arcs of the graph undergo the relaxation.
  
Структуру можно описать следующим образом:
+
The structure of the algorithm can be described as follows:
  
1. Инициализация: всем вершинам присваивается предполагаемое расстояние <math>t(v)=\infty</math>, кроме вершины-источника, для которой <math>t(u)=0</math> .
+
1. Initialization: all the nodes are assigned the expected distance <math>t(v)=\infty</math>. The only exception is the source node for which <math>t(u)=0</math> .
  
2. Релаксация множества рёбер <math>E</math>
+
2. Relaxation of the set of arcs <math>E</math>:
  
а) Для каждого ребра <math>e=(v,z) \in E</math> вычисляется новое предполагаемое расстояние <math>t^' (z)=t(v)+ w(e)</math>.
+
(a) For each arc <math>e=(v,z) \in E</math>, the new expected distance is calculated: <math>t^' (z)=t(v)+ w(e)</math>.
  
б) Если <math>t^' (z)< t(z)</math>, то происходит присваивание <math>t(z) := t' (z)</math> (релаксация ребра <math>e</math> ).
+
(b) If <math>t^' (z)< t(z)</math>, then the assignment <math>t(z) := t' (z)</math> (relaxation of the arc <math>e</math>) is performed.  
  
3. Алгоритм производит релаксацию всех рёбер графа до тех пор, пока на очередной итерации происходит релаксация хотя бы одного ребра.
+
3. The algorithm continues to work as long as at least one arc undergoes relaxation.
  
Если на <math>|V|</math>-й итерации всё ещё производилась релаксацию рёбер, то в графе присутствует цикл отрицательной длины. Ребро <math>e=(v,z)</math>, лежащее на таком цикле, может быть найдено проверкой следующего условия (проверяется для всех рёбер за линейное время): <math>t(v)+w(e)<d(z)</math>
+
Suppose that the relaxation of some arcs was still performed at the <math>|V|</math>-th iteration step. Then the graph contains a cycle of negative length. An arc <math>e=(v,z)</math> lying on such cycle can be found by testing the condition <math>t(v)+w(e)<d(z)</math> (this condition can be verified for all the arcs in linear time).
  
 
=== Implementation scheme of the serial algorithm ===
 
=== Implementation scheme of the serial algorithm ===
  
Последовательный алгоритм реализуется следующим псевдокодом:
+
The serial algorithm is implemented by the following pseudo-code:
  
  '''Входные данные''':
+
  '''Input data''':
   граф с вершинами ''V'', рёбрами ''E'' с весами ''f''(''e'');
+
   graph with nodes ''V'' and arcs ''E'' with weights ''f''(''e'');
   вершина-источник ''u''.
+
   source node ''u''.
  '''Выходные данные''': расстояния ''d''(''v'') до каждой вершины ''v'' ''V'' от вершины ''u''.
+
  '''Output data''': distances ''d''(''v'') from the source node ''u'' to each node  ''v'' ''V''.
 
   
 
   
 
  '''for each''' ''v'' ∈ ''V'' '''do''' ''d''(''v'') := ∞
 
  '''for each''' ''v'' ∈ ''V'' '''do''' ''d''(''v'') := ∞
Line 67: Line 68:
 
=== Serial complexity of the algorithm ===
 
=== Serial complexity of the algorithm ===
  
Алгоритм выполняет <math>|V|-1</math> итерацию, на каждой из которых происходит релаксация <math>|E|</math> рёбер. Таким образом, общий объём работы составляет <math>O(|V||E|)</math> операций.
+
The algorithm performs <math>|V|-1</math> iteration steps; at each step, <math>|E|</math> arcs are relaxed. Thus, the total work is <math>O(|V||E|)</math> operations.
  
Константа в оценке сложности может быть уменьшена за счёт использования следующих двух стандартных приёмов.
+
The constant in the complexity estimate can be reduced by using the following two conventional techniques:
  
# Если на очередной итерации не произошло ни одной успешной релаксации, то алгоритм завершает работу.
+
# Algorithm terminates if no successful relaxation occurred at the current iteration step.  
# На очередной итерации рассматриваются не все рёбра, а только выходящие из вершин, для которых на прошлой итерации была выполнена успешная релаксация (на первой итерации – только рёбра, выходящие из источника).
+
 
 +
# At the current step, not all the arcs are inspected but only the arcs outgoing from nodes that were involved in successful relaxations at the preceding step. (At the first step, only the arcs outgoing from the source node are examined.)
  
 
=== Information graph ===
 
=== Information graph ===
  
На рисунке 1 представлен информационный граф алгоритма, демонстрирующий описанные уровни параллелизма.
+
The information graph of the Bellman-Ford algorithm is shown in figure 1. It demonstrates the levels of parallelism in this algorithm.
  
[[file:APSP.png|thumb|center|700px|Рисунок 1. Информационный граф обобщенного алгоритма Беллмана-Форда.]]
+
[[file:APSP.png|thumb|center|700px|Figure 1. Information graph of the generalized Bellman-Ford algorithm.]]
  
На приведенном далее информационном графе нижний уровень параллелизма обозначен в горизонтальных плоскостях. Множество всех плоскостей представляет собой верхний уровень параллелизма (операции в каждой плоскости могут выполняться параллельно).
+
The lower level of parallelism refers to operations executed within each horizontal plane. The set of all planes represents the upper level of parallelism (because operations in different planes can be carried out concurrently).  
  
Нижний уровень параллелизма на графе алгоритма расположен на уровнях [2] и [3], соответствующим операциям инициализации массива дистанций [2] и обновления массива c использованием данных массива ребер [3]. Операция [4] - проверка того, были ли изменения на последней итерации и выход из цикла, если таковых не было.
+
The lower level of parallelism in the algorithm graph corresponds to levels [2] and [3], which represent the operations of initialization of the distance array ([2]) and updating of this array based on the data in arcs array ([3]). Operation [4] refers to the test whether any changes occurred at the current iteration and the loop termination if no changes were done.
  
Верхний уровень параллелизма, как уже говорилось, заключается в параллельном подсчете дистанций для различных вершин-источников, и на рисунке отмечен разными плоскостями.
+
As already said, the upper level of parallelism consists in the parallel calculation of distances for different source nodes. In the figure, it is illustrated by the set of distinct planes.
  
 
=== Parallelization resource of the algorithm ===
 
=== Parallelization resource of the algorithm ===
  
Алгоритм обладает значительным ресурсом параллелизма. Во-первых, поиск кратчайших путей от различных вершин может производиться независимо для каждой из вершин (параллельные вертикальные плоскости на рисунке 1). Во-вторых, поиск кратчайших путей от фиксированной вершины <math>u</math> так же может выполняться параллельно: инициализация начальных путей [2] требует <math>|V|</math> параллельных операции, реаллаксация каждого ребра требует <math>O(|E|)</math> параллельных операции.  
+
The Bellman-Ford algorithm has a considerable parallelization resource. First, the search for shortest paths can be independently performed for all the nodes (parallel vertical planes in figure 1). Second, the search for shortest paths beginning in a fixed node  <math>u</math> can also be made in parallel: the initialization of the original paths ([2]) requires <math>|V|</math> parallel operations, and the relaxation of all arcs costs <math>O(|E|)</math> parallel operations.  
  
Таким образом, при наличии <math>O(|E|)</math> процессоров алгоритм завершит работу максимум за <math>|V|</math> шагов. В реальности, шагов обычно требуется меньше, а именно <math>O(r)</math> - максимальной длине среди всех кратчайших путей от выбранной вершины-источника <math>u</math>.
+
Thus, if <math>O(|E|)</math> processors are available, then the algorithm terminates after at most <math>|V|</math> steps. Actually, a smaller number of steps are usually required, namely, <math>O(r)</math> steps. (This number is the maximum length of the shortest paths outgoing from the chosen source node  <math>u</math>).
  
Таким образом, ширина ярусно-параллельной формы алгоритма равна <math>O(|E|)</math>, высота ЯПФ - <math>O(r) | r < |V|</math>.
+
It follows that the width of the parallel form of the Bellman-Ford algorithm is <math>O(|E|)</math>, while its height is <math>O(r) | r < |V|</math>.
  
[[Алгоритм Δ-шагания]] может рассматриваться как параллельная версия алгоритма Беллмана-Форда.
+
The [[algorithm of Δ-stepping]] can be regarded as a parallel version of the Bellman-Ford algorithm.
  
 
=== Input and output data of the algorithm ===
 
=== Input and output data of the algorithm ===
  
'''Входные данные''': взвешенный граф <math>(V, E, W)</math> (<math>|V|</math> вершин <math>v_i</math> и <math>|E|</math> рёбер <math>e_j = (v^{(1)}_{j}, v^{(2)}_{j})</math> с весами <math>f_j</math>), вершина-источник <math>u</math>.
+
'''Input data''': weighted graph <math>(V, E, W)</math> (<math>|V|</math> nodes <math>v_i</math> and <math>|E|</math> arcs <math>e_j = (v^{(1)}_{j}, v^{(2)}_{j})</math> with weights <math>f_j</math>), source node <math>u</math>.
 +
 
 +
'''Size of input data''': <math>O(|V| + |E|)</math>.
  
'''Объём входных данных''': <math>O(|V| + |E|)</math>.
+
'''Output data''' (possible variants):
  
'''Выходные данные''' (возможные варианты):
+
# for each node <math>v</math> of the original graph, the last arc <math>e^*_v = (w, v)</math> lying on the shortest path from <math>u</math> to <math>v</math> or the corresponding node <math>w</math>;
# для каждой вершины <math>v</math> исходного графа – последнее ребро <math>e^*_v = (w, v)</math>, лежащее на кратчайшем пути от вершины <math>u</math> к <math>v</math>, или соответствующая вершина <math>w</math>;
+
# for each node <math>v</math> of the original graph, the summarized weight <math>f^*(v)</math> of the shortest path from <math>u</math> to <math>v</math>.
# для каждой вершины <math>v</math> исходного графа – суммарный вес <math>f^*(v)</math> кратчайшего пути от от вершины <math>u</math> к <math>v</math>.
 
 
 
'''Объём выходных данных''': <math>O(|V|)</math>.
+
'''Size of output data''': <math>O(|V|)</math>.
  
 
=== Properties of the algorithm ===
 
=== Properties of the algorithm ===
  
Алгоритм может распознавать наличие отрицательных циклов в графе. Ребро <math>e = (v, w)</math> лежит на таком цикле, если вычисленные алгоритмом кратчайшие расстояния <math>d(v)</math> удовлетворяют условию
+
The Bellman-Ford algorithm is able to identify cycles of negative length in a graph. An arc <math>e = (v, w)</math> lies on such a cycle if the shortest distances <math>d(v) </math> calculated by the algorithm satisfy the condition
 
:<math>
 
:<math>
 
         d(v) + f(e) < d(w),
 
         d(v) + f(e) < d(w),
 
</math>
 
</math>
где <math>f(e)</math> – вес ребра <math>e</math>. Условие может быть проверено для всех рёбер графа за время <math>O(|E|)</math>.
+
where <math>f(e)</math> is the weight of the arc <math>e</math>. This condition can be verified for all the arcs of the graph in time <math>O(|E|)</math>.
  
 
== Software implementation of the algorithm ==
 
== Software implementation of the algorithm ==
Line 124: Line 127:
 
===== Structure of memory access and a qualitative estimation of locality =====
 
===== Structure of memory access and a qualitative estimation of locality =====
  
[[file:bellman_ford_1.png|thumb|center|700px|Рисунок 2. Алгоритм Беллмана-Форда. Общий профиль обращений в память]]
+
[[file:bellman_ford_1.png|thumb|center|700px|Figure 2. Implementation of the Bellman-Ford algorithm. Overall memory access profile]]
  
На рис. 2 представлен профиль обращений в память для реализации алгоритма Беллмана-Форда. Первое, что сразу стоит отметить – число обращений в память гораздо больше числа задействованных данных. Это говорит о частом повторном использовании одних и тех же данных, что обычно приводит к высокой временной локальности. Далее, видна явная регулярная структура производимых обращений в память, видны повторяющиеся итерации работы алгоритма. Практически все обращения образуют фрагменты, похожие на последовательный перебор, кроме самой верхней части, где наблюдается более сложная структура.
+
Fig.2 shows the memory access profile for an implementation of the Bellman-Ford algorithm. The first thing that should be noted is that the number of memory accesses is much greater than the number of involved data. This says that the data are often used repeatedly, which usually implies high temporal locality. Furthermore, it is evident that the memory accesses have an explicit regular structure; one can also see repeated iterations in the work of the algorithm. Practically all the accesses form fragments similar to a successive search. The upper part of the figure, where the structure is more complicated, is an exception.
  
Рассмотрим более детально отдельные фрагменты общего профиля, чтобы лучше разобраться в его структуре. На рис. 3 представлен фрагмент 1 (выделен на рис. 2), на котором показаны первые 500 обращений в память (отметим, что другой наклон двух последовательных переборов связан с измененным отношением сторон в рассматриваемой области). Данный рисунок показывает, что выделенные желтым части 1 и 2 являются практические идентичными последовательными переборами; отличие между ними только в том, что в части 1 обращения выполняются в два раза чаще, поэтому на рис. 3 эта часть представлена большим числом точек. Как мы знаем, подобные профили характеризуются высокой пространственной и низкой временной локальностью.
+
In order to better understand the structure of the overall profile, let us consider more closely its individual areas. Figure 3 shows fragment 1 (selected in fig.2); here, one can see the first 500 memory accesses (note that different slopes of two successive searches are caused by different ratios of sides in the corresponding areas). This figure shows that parts 1 and 2 (selected in yellow) are practically identical successive searches. They only differ in that the accesses in part 1 are performed twice as often compared to part 2; for this reason, the former is represented by a greater number of points. As is known, such profiles are characterized by high spatial and low temporal locality.
  
[[file:bellman_ford_2.png|thumb|center|700px|Рисунок 3. Профиль обращений, фрагмент 1]]
+
[[file:bellman_ford_2.png|thumb|center|700px|Figure 3. Memory access profile, fragment 1]]
  
Далее рассмотрим более интересный фрагмент 2, отмеченный на рис. 2 (см. рис. 4). Здесь можно снова увидеть подтверждение регулярности обращений в нижней области профиля, однако верхняя область явно устроена гораздо сложнее; хотя и здесь просматривается регулярность. В частности, также видны те же самые итерации, в которых здесь можно выделить большие последовательности обращений к одним и тем же данным. Пример такого поведения, оптимального с точки зрения локальности, выделен на рисунке желтым.  
+
Now, we consider the more interesting fragment 2 of fig.2 (see fig.4). In the lower area of this profile, one can again see a confirmation of the regularity of accesses. However, its upper area is clearly structured in a more complex way, although the regularity is seen here as well. In particular, the same repeated iterations are present here; in them, one can distinguish long sequences of accesses to the same data. An example of such a behavior, which is optimal in terms of locality, is set out in yellow.  
  
[[file:bellman_ford_3.png|thumb|center|700px|Рисунок 4. Профиль обращений, фрагмент 2]]
+
[[file:bellman_ford_3.png|thumb|center|700px|Figure 4. Memory access profile, fragment 2]]
  
Чтобы понять структуру обращений в память в верхней части, можно рассмотреть ее еще подробнее. Приведем визуализацию небольшой области фрагмента 1, выделенную на рис. 4 зеленым. Однако в данном случае дальнейшее приближение (рис. 5) не привносит большей ясности: видна нерегулярная структура внутри итерации, характер которой достаточно сложно описать. Но в данном случае этого и не требуется – можно заметить, что по вертикали отложено всего 15 элементов, при этом обращений к ним выполняется гораздо больше. Независимо от структуры обращений, такой профиль обладает очень высокой как пространственной, так и временной локальностью.
+
In order to understand the structure of memory accesses in the upper area, let us examine this area even more closely. Consider the visualization of the small portion of fragment 2 shown in green in fig.4. In this case, the closer examination (see fig.5) does not make the picture more clear: one can see an irregular structure within an iteration, but the nature of this irregularity is fairly difficult to describe. However, such a description is not required here. Indeed, one can notice that only 15 elements are located along the vertical, whereas the number of accesses to these elements is much greater. Such a profile has a very high locality (both spatial and temporal) regardless of the structure of accesses.  
  
[[file:bellman_ford_4.png|thumb|center|700px|Рисунок 5. Небольшая часть фрагмента 1]]
+
[[file:bellman_ford_4.png|thumb|center|700px|Figure 5. A small portion of fragment 2]]
  
А так как основная масса обращений приходится именно на фрагмент 2, можно утверждать, что и весь общий профиль обладает высокой пространственной и временной локальностью.
+
The majority of accesses are performed exactly to fragment 2. Consequently, one can state that the overall profile also has a high spatial and temporal locality.
  
 
===== Quantitative estimation of locality =====
 
===== Quantitative estimation of locality =====
  
Оценка выполняется на основе характеристики daps, которая оценивает число выполненных обращений (чтений и записей) в память в секунду. Данная характеристика является аналогом оценки flops применительно к работе с памятью и является в большей степени оценкой производительности взаимодействия с памятью, чем оценкой локальности. Однако она служит хорошим источником информации, в том числе для сравнения с результатами по следующей характеристике cvg.
+
Our estimate is based on daps, which assesses the number of memory accesses (reads and writes) per second. Similarly to flops, daps is used to evaluate memory access performance rather than locality. Yet, it is a good source of information, particularly for comparison with the results provided by the estimate cvg.  
  
На рисунке 6 приведены значения daps для реализаций распространенных алгоритмов, отсортированные по возрастанию (чем больше daps, тем в общем случае выше производительность). Можно увидеть, что по производительности работы с памятью данная реализация алгоритма показывает очень хорошие результаты. В частности, значение daps сравнимо с оценкой для теста Linpack, который известен высокой эффективностью взаимодействия с подсистемой памяти.  
+
Fig.6 shows daps values for implementations of popular algorithms, sorted in ascending order (the higher the daps, the better the performance in general). One can see that the memory access performance of this implementation is fairly good. In particular, its daps value is comparable with that for the Linpack benchmark. The latter is known for its high efficiency of memory interaction.  
  
[[file:bellman_ford_daps.png|thumb|center|700px|Рисунок 6. Сравнение значений оценки daps]]
+
[[file:bellman_ford_daps.png|thumb|center|700px|Figure 6. Comparison of daps values]]
  
 
=== Possible methods and considerations for parallel implementation of the algorithm ===
 
=== Possible methods and considerations for parallel implementation of the algorithm ===
  
Программа, реализующая алгоритм поиска кратчайших путей, состоит из двух частей: части, отвечающей за общую координацию вычислений, а так же параллельные вычисления на многоядерных CPU, и GPU части, отвечающей только за вычисления на графическом ускорителе.
+
A program implementing the algorithm for finding shortest paths consists of two parts. One part is responsible for the general coordination of computations, as well as parallel computations on a multi-core CPU.  The other, GPU part is only responsible for computations on a graphic accelerator.
  
 
=== Scalability of the algorithm and its implementations ===
 
=== Scalability of the algorithm and its implementations ===
 
==== Scalability of the algorithm ====
 
==== Scalability of the algorithm ====
  
Алгоритм обладает значительным потенциалом масштабируемости, так как каждое ребро обрабатывается независимо и можно поручить каждому вычислительному процессу свою часть рёбер графа. Узким местом является доступ к разделяемому всеми процессами массиву расстояний. Алгоритм позволяет ослабить требования к синхронизации данных этого массива между процессами (когда один процесс может не сразу увидеть новое значение расстояния, записанное другим процессом), за счёт, может быть, большего количества глобальных итераций.
+
The Bellman-Ford algorithm has a considerable scalability potential because each arc is processed independently of the others, and each computational process can be assigned its own portion of graph arcs. The bottleneck is the access to the distance array shared by all the processes. The algorithm permits to relax requirements to the synchronization of the data in this array between the processes (a process may not immediately see the new value of a distance written by some other process). This possibly can be achieved by performing a greater number of global iterations.
  
==== Scalability of of the algorithm implementation ====  
+
==== Scalability of the algorithm implementation ====  
  
Проведём исследование масштабируемости параллельной реализации алгоритма Беллмана-Форда согласно [[Scalability methodology|методике]]. Исследование проводилось на суперкомпьютере "Ломоносов-2 [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета].
+
Let us study scalability for the parallel implementation of the Bellman-Ford algorithm in accordance with [[Scalability methodology|Scalability methodology]]. This study was conducted using the Lomonosov-2 supercomputer of the [http://parallel.ru/cluster Moscow University Supercomputing Center].
  
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма:  
+
Variable parameters for the [[Глоссарий#|start-up]] of the algorithm implementation and the limits of parameter variations:
  
* число процессоров [1 : 28] с шагом 1;
+
* number of processors [1 : 28] with the step 1;
* размер графа [2^20 : 2^27].
+
* graph size [2^20 : 2^27].
  
Проведем отдельные исследования сильной масштабируемости вширь реализации алгоритма Беллмана-Форда.
+
We carry out a separate analysis of the strong scaling-out of the Bellman-Ford algorithm .
  
Производительность определена как TEPS (от англ. Traversed Edges Per Second), то есть число ребер графа, который алгоритм обрабатывает в секунду. С помощью данной метрики можно сравнивать производительность для различных размеров графа, оценивая, насколько понижается эффективность обработки графа при увеличении его размера.
+
The performance is defined as TEPS (an abbreviation for Traversed Edges Per Second), that is, the number of graph arcs processed by the algorithm in a second. Using this characteristic, one can compare the performance for graphs of different sizes and estimate how the performance gets worse when the graph size increases.
  
[[file:Сильная_масштабируемость_вширь_алгоритма_Беллмана-Форда.png|thumb|center|700px|Рисунок 7. Параллельная реализация алгоритма Беллмана-Форда масштабируемость различных версий реализации алгоритма: производительность в зависимости от размера графа]]
+
[[file:Сильная_масштабируемость_вширь_алгоритма_Беллмана-Форда.png|thumb|center|700px|Figure 7. Parallel implementation of the Bellman-Ford algorithm: scalability of different implementations of the algorithm: performance as a function of the graph size]]
  
 
=== Dynamic characteristics and efficiency of the algorithm implementation ===
 
=== Dynamic characteristics and efficiency of the algorithm implementation ===
  
Для проведения экспериментов использовалась реализация алгоритма Беллмана-Форда, реализованная для CPU. Все результаты получены на суперкомпьютере «Ломоносов-2». Использовались процессоры Intel Xeon E5-2697v3, задача решалась для графа большого размера на одном узле.  
+
The experiments were conducted with the Bellman-Ford algorithm implemented for CPU. All the results were obtained with the «Lomonosov-2» supercomputer. We used Intel Xeon E5-2697v3 processors. The problem was solved for a large graph (of size 2^27) on a single node. Only one iteration was performed. The figures below illustrate the efficiency of this implementation.
На рисунках показана эффективность реализации алгоритма Беллмана-Форда, запуск проводился на 1 узле для графа 2^27, выполнялась 1 итерация.
 
[[file:Bellman-Ford cpu.png|thumb|center|700px|Рисунок 8. График загрузки CPU при выполнении алгоритма Беллмана-Форда]]
 
  
На графике загрузки процессора видно, что почти все время работы программы не загружены и средний уровень загрузки составляет около 5%. Это достаточно неэффективная картина даже для программ, запущенных c использованием одного ядра в реализации.  
+
[[file:Bellman-Ford cpu.png|thumb|center|700px|Figure 8. Graph of CPU loading while executing the Bellman-Ford algorithm]]
  
[[file:Bellman-Ford LoadAvg.png|thumb|center|700px|Рисунок 9. График числа процессов, ожидающих вхождения в стадию счета (Loadavg), при работе алгоритма Беллмана-Форда]]
+
The graph of CPU loading shows that the processor is idle almost all the time: the average level of loading is about 5 percent. This is a fairly inefficient result even for programs started with the use of only one core.  
  
На графике числа процессов, ожидающих вхождения в стадию счета (Loadavg), видно, что на протяжении всей работы программы значение этого параметра постоянно на уровне 1. Это указывает на постоянную загрузку аппаратных ресурсов не более чем 1 процессом, однако их число для узла слишком мало, что с одной стороны может указывать на не очень рациональные использование ресурсов.
+
[[file:Bellman-Ford LoadAvg.png|thumb|center|700px|Figure 9. Graph of the number of processes expecting the beginning of the calculation stage (Loadavg) while executing the Bellman-Ford algorithm]]The graph of the number of processes expecting the beginning of the calculation stage (Loadavg) shows that the value of this parameter in the course of the program execution is the constant 1. This indicates that the hardware resources are all the time loaded by at most one process. Such a small number points to a not very reasonable use of resources.
  
  [[file:Bellman-Ford L1.png|thumb|center|700px|Рисунок 10. График кэш-промахов L1 в секунду при работе алгоритма Беллмана-Форда]]
+
  [[file:Bellman-Ford L1.png|thumb|center|700px|Figure 10. Graph of L1 cache misses per second while executing the Bellman-Ford algorithm]]
 
   
 
   
На графике кэш-промахов первого уровня видно, что число промахов очень высокое и находится на уровне 140 млн/сек это очень высокий показатель, показывающие потенциальную причину неэффективности.
+
The graph of L1 cache misses shows that the number of misses is very large. It is on the level of 140 millions per second, which is a very high value indicating a potential cause of inefficiency.  
  
  [[file:Bellman-Ford L2.png|thumb|center|700px|Рисунок 11. График кэш-промахов L1 в секунду при работе алгоритма Беллмана-Форда]]
+
  [[file:Bellman-Ford L2.png|thumb|center|700px|Figure 11. Graph of L2 cache misses per second while executing the Bellman-Ford algorithm]]
 
   
 
   
На графике кэш-промахов второго уровня видно, что число промахов достаточно тоже крайне высокое и находится на уровне 140 млн/сек, что указывает на крайне неэффективную работу с памятью.
+
The graph of L2 cache misses shows that the number of such misses is also very large. It is on the level of 140 millions per second, which indicates an extremely inefficient memory interaction.
  
  [[file:Bellman-Ford-L3.png|thumb|center|700px|Рисунок 12. График кэш-промахов L3 в секунду при работе алгоритма Беллмана-Форда]]
+
  [[file:Bellman-Ford-L3.png|thumb|center|700px|Figure 12. Graph of L3 cache misses per second while executing the Bellman-Ford algorithm]]
  
На графике кэш-промахов последнего уровня видно, что число промахов тоже достаточно большое и составляет около 30 млн/сек по всем узлам. Это указывает на то, что задача очень плохо укладывается в кэш-память, и программа постоянно работает с оперативной памятью, что объясняется очень большим размером использованного графа.
+
The graph of L3 cache misses shows that the number of these misses is again large; it is about 30 millions per second. This indicates that the problem fits very badly into cache memory, and the program is compelled to work all the time with RAM, which is explained by the very large size of the input graph.  
  
[[file:Bellman-Ford Inf Data.png|thumb|center|700px|Рисунок 13. График скорости передачи по сети Infiniband в байт/сек при работе алгоритма Беллмана-Форда]]
+
[[file:Bellman-Ford Inf Data.png|thumb|center|700px|Figure 13. Graph of the data rate through Infiniband network (in bytes per second) while executing the Bellman-Ford algorithm]]
  
На графике скорости передачи данных по сети Infiniband наблюдается достаточно высокая интенсивность использования сети на кпервом этапе. Это объясняется программной логикой, которая предполагает чтение графа из файла с диска, коммуникации с которым происходят на Ломоносов-2 через выделенную для этих задач сеть Infiniband.
+
The graph of the data rate through Infiniband network shows a fairly high intensity of using this network at the first stage. This is explained by the program logic, which assumes the reading of the graph from a disc file. On Lomonosov-2, communications with this disc are performed through a dedicated Infiniband network.
  
  [[file:Bellman-Ford Inf Pckts.png|thumb|center|700px|Рисунок 14. График скорости передачи по сети Infiniband в пакетах/сек при работе алгоритма Беллмана-Форда]]
+
  [[file:Bellman-Ford Inf Pckts.png|thumb|center|700px|Figure 14. Graph of the data rate through Infiniband network (in packets per second) while executing the Bellman-Ford algorithm]]
  
На графике скорости передачи данных в пакетах в секунду наблюдается аналогичная картина очень высокой интенсивности на первом этапе выполнения задачи. Далее сеть почти не используется.
+
The graph of the data rate measured in packets per second demonstrates a similar picture of very high intensity at the first stage of executing the problem. Later on, the network is almost not used.  
 
   
 
   
В целом, по данным системного мониторинга работы программы можно сделать вывод о том, что программа работала стабильно интенсивно,  однако очень неэффективно использовала память из-за очень большого размера графа.
+
On the whole, the data of system monitoring make it possible to conclude that the program worked with a stable intensity. However, it used the memory very inefficiently due to the extremely large size of the graph.
  
 
=== Conclusions for different classes of computer architecture ===
 
=== Conclusions for different classes of computer architecture ===
 
=== Existing implementations of the algorithm ===
 
=== Existing implementations of the algorithm ===
  
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция <code>[http://www.boost.org/libs/graph/doc/bellman_ford_shortest.html bellman_ford_shortest]</code>).
+
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (function <code>[http://www.boost.org/libs/graph/doc/bellman_ford_shortest.html bellman_ford_shortest]</code>).
* Python: [https://networkx.github.io NetworkX] (функция <code>[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.weighted.bellman_ford.html bellman_ford]</code>).
+
* Python: [https://networkx.github.io NetworkX] (function <code>[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.weighted.bellman_ford.html bellman_ford]</code>).
* Java: [http://jgrapht.org JGraphT] (класс <code>[http://jgrapht.org/javadoc/org/jgrapht/alg/BellmanFordShortestPath.html BellmanFordShortestPath]</code>).
+
* Java: [http://jgrapht.org JGraphT] (class <code>[http://jgrapht.org/javadoc/org/jgrapht/alg/BellmanFordShortestPath.html BellmanFordShortestPath]</code>).
  
 
== References ==
 
== References ==

Revision as of 14:53, 5 February 2018


Bellman-Ford algorithm
Sequential algorithm
Serial complexity [math]O(|V||E|)[/math]
Input data [math]O(|V| + |E|)[/math]
Output data [math]O(|V|^2)[/math]
Parallel algorithm
Parallel form height [math]N/A, max O(|V|) [/math]
Parallel form width [math]O(|E|)[/math]


1 Properties and structure of the algorithm

1.1 General description of the algorithm

The Bellman-Ford algorithm[1][2][3] was designed for finding the shortest paths between nodes in a graph. For a given weighted digraph, the algorithm finds the shortest paths between a singled-out source node and the other nodes of the graph. The Bellman-Ford algorithm scales worse than other algorithms for solving this problem (the complexity is [math]O(|V||E|)[/math] against [math]O(|E| + |V|\ln(|V|))[/math] for Dijkstra's algorithm). However, its distinguishing feature is the applicability to graphs with arbitrary (including negative) weights.

1.2 Mathematical description of the algorithm

Let [math]G = (V, E)[/math] be a given graph with arc weights [math]f(e)[/math] f(e) and the single-out source node [math]u[/math]. Denote by [math]d(v)[/math] the shortest distance between the source node [math]u[/math] and the node [math]v[/math].

The Bellman-Ford algorithm finds the value [math]d(v)[/math] as the unique solution to the equation

[math] d(v) = \min \{ d(w) + f(e) \mid e = (w, v) \in E \}, \quad \forall v \ne u, [/math]

with the initial condition [math]d(u) = 0[/math].

1.3 Computational kernel of the algorithm

The algorithm is based on the principle of arc relaxation: if [math]e = (w, v) \in E[/math] and [math]d(v) \gt d(w) + f(e)[/math], then the assignment [math]d(v) \leftarrow d(w) + f(e)[/math] is performed.

1.4 Macro structure of the algorithm

The algorithm successively refines the values of the function [math]d(v)[/math].

  • At the very start, the assignment [math]d(u) = 0[/math], [math]d(v) = \infty[/math], [math]\forall v \ne u[/math] is performed.
  • Then [math]|V|-1[/math] iteration steps are executed. At each step, all the arcs of the graph undergo the relaxation.

The structure of the algorithm can be described as follows:

1. Initialization: all the nodes are assigned the expected distance [math]t(v)=\infty[/math]. The only exception is the source node for which [math]t(u)=0[/math] .

2. Relaxation of the set of arcs [math]E[/math]:

(a) For each arc [math]e=(v,z) \in E[/math], the new expected distance is calculated: [math]t^' (z)=t(v)+ w(e)[/math].

(b) If [math]t^' (z)\lt t(z)[/math], then the assignment [math]t(z) := t' (z)[/math] (relaxation of the arc [math]e[/math]) is performed.

3. The algorithm continues to work as long as at least one arc undergoes relaxation.

Suppose that the relaxation of some arcs was still performed at the [math]|V|[/math]-th iteration step. Then the graph contains a cycle of negative length. An arc [math]e=(v,z)[/math] lying on such cycle can be found by testing the condition [math]t(v)+w(e)\lt d(z)[/math] (this condition can be verified for all the arcs in linear time).

1.5 Implementation scheme of the serial algorithm

The serial algorithm is implemented by the following pseudo-code:

Input data:
  graph with nodes V and arcs E with weights f(e);
  source node u.
Output data: distances d(v) from the source node u to each node  vV.

for each vV do d(v) := ∞
d(u) = 0

for i from 1 to |V| - 1:
    for each e = (w, v) ∈ E:
        if d(v) > d(w) + f(e):
            d(v) := d(w) + f(e)

1.6 Serial complexity of the algorithm

The algorithm performs [math]|V|-1[/math] iteration steps; at each step, [math]|E|[/math] arcs are relaxed. Thus, the total work is [math]O(|V||E|)[/math] operations.

The constant in the complexity estimate can be reduced by using the following two conventional techniques:

  1. Algorithm terminates if no successful relaxation occurred at the current iteration step.
  1. At the current step, not all the arcs are inspected but only the arcs outgoing from nodes that were involved in successful relaxations at the preceding step. (At the first step, only the arcs outgoing from the source node are examined.)

1.7 Information graph

The information graph of the Bellman-Ford algorithm is shown in figure 1. It demonstrates the levels of parallelism in this algorithm.

Figure 1. Information graph of the generalized Bellman-Ford algorithm.

The lower level of parallelism refers to operations executed within each horizontal plane. The set of all planes represents the upper level of parallelism (because operations in different planes can be carried out concurrently).

The lower level of parallelism in the algorithm graph corresponds to levels [2] and [3], which represent the operations of initialization of the distance array ([2]) and updating of this array based on the data in arcs array ([3]). Operation [4] refers to the test whether any changes occurred at the current iteration and the loop termination if no changes were done.

As already said, the upper level of parallelism consists in the parallel calculation of distances for different source nodes. In the figure, it is illustrated by the set of distinct planes.

1.8 Parallelization resource of the algorithm

The Bellman-Ford algorithm has a considerable parallelization resource. First, the search for shortest paths can be independently performed for all the nodes (parallel vertical planes in figure 1). Second, the search for shortest paths beginning in a fixed node [math]u[/math] can also be made in parallel: the initialization of the original paths ([2]) requires [math]|V|[/math] parallel operations, and the relaxation of all arcs costs [math]O(|E|)[/math] parallel operations.

Thus, if [math]O(|E|)[/math] processors are available, then the algorithm terminates after at most [math]|V|[/math] steps. Actually, a smaller number of steps are usually required, namely, [math]O(r)[/math] steps. (This number is the maximum length of the shortest paths outgoing from the chosen source node [math]u[/math]).

It follows that the width of the parallel form of the Bellman-Ford algorithm is [math]O(|E|)[/math], while its height is [math]O(r) | r \lt |V|[/math].

The algorithm of Δ-stepping can be regarded as a parallel version of the Bellman-Ford algorithm.

1.9 Input and output data of the algorithm

Input data: weighted graph [math](V, E, W)[/math] ([math]|V|[/math] nodes [math]v_i[/math] and [math]|E|[/math] arcs [math]e_j = (v^{(1)}_{j}, v^{(2)}_{j})[/math] with weights [math]f_j[/math]), source node [math]u[/math].

Size of input data: [math]O(|V| + |E|)[/math].

Output data (possible variants):

  1. for each node [math]v[/math] of the original graph, the last arc [math]e^*_v = (w, v)[/math] lying on the shortest path from [math]u[/math] to [math]v[/math] or the corresponding node [math]w[/math];
  2. for each node [math]v[/math] of the original graph, the summarized weight [math]f^*(v)[/math] of the shortest path from [math]u[/math] to [math]v[/math].

Size of output data: [math]O(|V|)[/math].

1.10 Properties of the algorithm

The Bellman-Ford algorithm is able to identify cycles of negative length in a graph. An arc [math]e = (v, w)[/math] lies on such a cycle if the shortest distances [math]d(v) [/math] calculated by the algorithm satisfy the condition

[math] d(v) + f(e) \lt d(w), [/math]

where [math]f(e)[/math] is the weight of the arc [math]e[/math]. This condition can be verified for all the arcs of the graph in time [math]O(|E|)[/math].

2 Software implementation of the algorithm

2.1 Implementation peculiarities of the serial algorithm

2.2 Locality of data and computations

2.2.1 Locality of implementation

2.2.1.1 Structure of memory access and a qualitative estimation of locality
Figure 2. Implementation of the Bellman-Ford algorithm. Overall memory access profile

Fig.2 shows the memory access profile for an implementation of the Bellman-Ford algorithm. The first thing that should be noted is that the number of memory accesses is much greater than the number of involved data. This says that the data are often used repeatedly, which usually implies high temporal locality. Furthermore, it is evident that the memory accesses have an explicit regular structure; one can also see repeated iterations in the work of the algorithm. Practically all the accesses form fragments similar to a successive search. The upper part of the figure, where the structure is more complicated, is an exception.

In order to better understand the structure of the overall profile, let us consider more closely its individual areas. Figure 3 shows fragment 1 (selected in fig.2); here, one can see the first 500 memory accesses (note that different slopes of two successive searches are caused by different ratios of sides in the corresponding areas). This figure shows that parts 1 and 2 (selected in yellow) are practically identical successive searches. They only differ in that the accesses in part 1 are performed twice as often compared to part 2; for this reason, the former is represented by a greater number of points. As is known, such profiles are characterized by high spatial and low temporal locality.

Figure 3. Memory access profile, fragment 1

Now, we consider the more interesting fragment 2 of fig.2 (see fig.4). In the lower area of this profile, one can again see a confirmation of the regularity of accesses. However, its upper area is clearly structured in a more complex way, although the regularity is seen here as well. In particular, the same repeated iterations are present here; in them, one can distinguish long sequences of accesses to the same data. An example of such a behavior, which is optimal in terms of locality, is set out in yellow.

Figure 4. Memory access profile, fragment 2

In order to understand the structure of memory accesses in the upper area, let us examine this area even more closely. Consider the visualization of the small portion of fragment 2 shown in green in fig.4. In this case, the closer examination (see fig.5) does not make the picture more clear: one can see an irregular structure within an iteration, but the nature of this irregularity is fairly difficult to describe. However, such a description is not required here. Indeed, one can notice that only 15 elements are located along the vertical, whereas the number of accesses to these elements is much greater. Such a profile has a very high locality (both spatial and temporal) regardless of the structure of accesses.

Figure 5. A small portion of fragment 2

The majority of accesses are performed exactly to fragment 2. Consequently, one can state that the overall profile also has a high spatial and temporal locality.

2.2.1.2 Quantitative estimation of locality

Our estimate is based on daps, which assesses the number of memory accesses (reads and writes) per second. Similarly to flops, daps is used to evaluate memory access performance rather than locality. Yet, it is a good source of information, particularly for comparison with the results provided by the estimate cvg.

Fig.6 shows daps values for implementations of popular algorithms, sorted in ascending order (the higher the daps, the better the performance in general). One can see that the memory access performance of this implementation is fairly good. In particular, its daps value is comparable with that for the Linpack benchmark. The latter is known for its high efficiency of memory interaction.

Figure 6. Comparison of daps values

2.3 Possible methods and considerations for parallel implementation of the algorithm

A program implementing the algorithm for finding shortest paths consists of two parts. One part is responsible for the general coordination of computations, as well as parallel computations on a multi-core CPU. The other, GPU part is only responsible for computations on a graphic accelerator.

2.4 Scalability of the algorithm and its implementations

2.4.1 Scalability of the algorithm

The Bellman-Ford algorithm has a considerable scalability potential because each arc is processed independently of the others, and each computational process can be assigned its own portion of graph arcs. The bottleneck is the access to the distance array shared by all the processes. The algorithm permits to relax requirements to the synchronization of the data in this array between the processes (a process may not immediately see the new value of a distance written by some other process). This possibly can be achieved by performing a greater number of global iterations.

2.4.2 Scalability of the algorithm implementation

Let us study scalability for the parallel implementation of the Bellman-Ford algorithm in accordance with Scalability methodology. This study was conducted using the Lomonosov-2 supercomputer of the Moscow University Supercomputing Center.

Variable parameters for the start-up of the algorithm implementation and the limits of parameter variations:

  • number of processors [1 : 28] with the step 1;
  • graph size [2^20 : 2^27].

We carry out a separate analysis of the strong scaling-out of the Bellman-Ford algorithm .

The performance is defined as TEPS (an abbreviation for Traversed Edges Per Second), that is, the number of graph arcs processed by the algorithm in a second. Using this characteristic, one can compare the performance for graphs of different sizes and estimate how the performance gets worse when the graph size increases.

Figure 7. Parallel implementation of the Bellman-Ford algorithm: scalability of different implementations of the algorithm: performance as a function of the graph size

2.5 Dynamic characteristics and efficiency of the algorithm implementation

The experiments were conducted with the Bellman-Ford algorithm implemented for CPU. All the results were obtained with the «Lomonosov-2» supercomputer. We used Intel Xeon E5-2697v3 processors. The problem was solved for a large graph (of size 2^27) on a single node. Only one iteration was performed. The figures below illustrate the efficiency of this implementation.

Figure 8. Graph of CPU loading while executing the Bellman-Ford algorithm

The graph of CPU loading shows that the processor is idle almost all the time: the average level of loading is about 5 percent. This is a fairly inefficient result even for programs started with the use of only one core.

Figure 9. Graph of the number of processes expecting the beginning of the calculation stage (Loadavg) while executing the Bellman-Ford algorithm

The graph of the number of processes expecting the beginning of the calculation stage (Loadavg) shows that the value of this parameter in the course of the program execution is the constant 1. This indicates that the hardware resources are all the time loaded by at most one process. Such a small number points to a not very reasonable use of resources.

Figure 10. Graph of L1 cache misses per second while executing the Bellman-Ford algorithm

The graph of L1 cache misses shows that the number of misses is very large. It is on the level of 140 millions per second, which is a very high value indicating a potential cause of inefficiency.

Figure 11. Graph of L2 cache misses per second while executing the Bellman-Ford algorithm

The graph of L2 cache misses shows that the number of such misses is also very large. It is on the level of 140 millions per second, which indicates an extremely inefficient memory interaction.

Figure 12. Graph of L3 cache misses per second while executing the Bellman-Ford algorithm

The graph of L3 cache misses shows that the number of these misses is again large; it is about 30 millions per second. This indicates that the problem fits very badly into cache memory, and the program is compelled to work all the time with RAM, which is explained by the very large size of the input graph.

Figure 13. Graph of the data rate through Infiniband network (in bytes per second) while executing the Bellman-Ford algorithm

The graph of the data rate through Infiniband network shows a fairly high intensity of using this network at the first stage. This is explained by the program logic, which assumes the reading of the graph from a disc file. On Lomonosov-2, communications with this disc are performed through a dedicated Infiniband network.

Figure 14. Graph of the data rate through Infiniband network (in packets per second) while executing the Bellman-Ford algorithm

The graph of the data rate measured in packets per second demonstrates a similar picture of very high intensity at the first stage of executing the problem. Later on, the network is almost not used.

On the whole, the data of system monitoring make it possible to conclude that the program worked with a stable intensity. However, it used the memory very inefficiently due to the extremely large size of the graph.

2.6 Conclusions for different classes of computer architecture

2.7 Existing implementations of the algorithm

3 References

  1. Bellman, Richard. “On a Routing Problem.” Quarterly of Applied Mathematics 16 (1958): 87–90.
  2. Ford, L R. Network Flow Theory. Rand.org, RAND Corporation, 1958.
  3. Moore, Edward F. “The Shortest Path Through a Maze,” International Symposium on the Theory of Switching, 285–92, 1959.