Late submission policy: Submission can be at the most 2
days late. There will be a 10% penalty for each day
after the due date (cumulative).
In this assignment, you will implement both sequential and parallel versions of the Bellman-Ford algorithm in C++. You may use classes from the C++ STL and boost libraries if you wish. You may also use either pthreads or C++ threads.
Recall that the Bellman-Ford algorithm solves the single-source shortest path problem. It is a topology-driven algorithm, so it makes sweeps over all the nodes of the graph, terminating sweeps when node labels do not change in a sweep. In each sweep, it visits all the nodes of the graph, and at each node, it applies a push-style relaxation operator to update the labels of neighboring nodes.
One way to assign work to threads is to divide the nodes in the graph uniformly between threads. This will give good load balance for uniform-degree graphs but not for power-law graphs, but it is a start. Each thread should relax the edges of all nodes assigned to it. Decide if any thread updated any node and if so, continue iterating over the graph. Use a barrier to ensure that all threads have finished relaxation before deciding whether to perform another iteration.
Part 1 (Sequential BF): Implement a sequential program for Bellman-Ford and measure its running time on the input graphs given to you (see below). These times will be the baseline for computing parallel speedups.
Part 2 (Parallel BF): Implement a parallel program for Bellman-Ford, using these different forms of synchronization (i.e. different versions of the same algorithm):
Part 3 Extra Credit (Edge distribution): Assigning equals numbers of nodes to threads will result in poor load-balancing for power-law graphs. You can get better load-balancing for these graphs by assigning equal numbers of edges to threads, although this complicates the algorithm a little. Implement this approach, using only the compare-and-swap approach for the relaxations.
Input graphs: Use rmat15 and road-NY in DIMACS format, which you used in Assignment 4.
Source nodes (DIMACS node numbers): These are the nodes with the highest degree.
Output of your program: Your program should output, as a .txt file, one line for each node, specifying the number of the node and the label of that node.
Compare-and-swap
Figure 3 shows a way to use C++11 atomic compare and swap to achieve the same functionality as a mutex. var is the variable whose value is of type double to be synchronized. It is declared as std::atomic<double>. The function call compare exchange weak(old, new, ..) on var compares its value with old. If it is equal, it sets new as its value and returns true. Otherwise, it copies its value to old and returns false. All this is done atomically.