Skip to content

Commit 35136b3

Browse files
committed
Better code org and documentation.
1 parent a2f4877 commit 35136b3

File tree

7 files changed

+275
-120
lines changed

7 files changed

+275
-120
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Single-Source Shortest Path (SSSP) implementation in modern C++ for 2022 IPDPS w
1212
- `tbb` library for execution policies (automatically fetched using cmake).
1313

1414
## Quick Start Guide
15-
Before building this project, make sure your system/compiler supports **C++20** and **cmake** (see `CMakeLists.txt` for the version).
15+
Before building this project, make sure your system/compiler supports **C++20** and **cmake**.
1616

1717
```bash
1818
git clone https://github.com/owensgroup/sssp.git

include/datastructs.hxx

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/**
2+
* @file datastructs.hxx
3+
* @author Muhammad Osama (mosama@ucdavis.edu)
4+
* @brief
5+
* @version 0.1
6+
*
7+
* @copyright Copyright (c) 2022
8+
*
9+
*/
10+
11+
#pragma once
12+
13+
#include <vector>
14+
#include <algorithm>
15+
#include <execution>
16+
#include <mutex>
17+
#include <utility>
18+
#include <ranges>
19+
20+
namespace essentials {
21+
22+
/**
23+
* @brief Example frontier data structure.
24+
*
25+
* @tparam type_t
26+
*/
27+
template <typename type_t>
28+
struct frontier_t {
29+
// Underlying representation of frontier.
30+
std::vector<type_t> active_vertices;
31+
32+
// Get the number of active vertices.
33+
int size() { return active_vertices.size(); }
34+
// Get the active vertex at a given index.
35+
type_t get_active_vertex(type_t const& i) { return active_vertices[i]; }
36+
// Add a vertex to the frontier.
37+
void add_vertex(type_t const& v) { active_vertices.push_back(v); }
38+
};
39+
40+
/**
41+
* @brief Compressed-Sparse Row (CSR) matrix.
42+
*
43+
* @tparam index_t Type of index.
44+
* @tparam offset_t Type of offset.
45+
* @tparam value_t Type of value.
46+
*/
47+
template <typename index_t, typename offset_t, typename value_t>
48+
struct csr_t {
49+
index_t rows;
50+
index_t cols;
51+
offset_t nnzs;
52+
std::vector<offset_t>& row_offsets;
53+
std::vector<index_t>& column_indices;
54+
std::vector<value_t>& values;
55+
56+
/**
57+
* @brief Construct a new csr_t object.
58+
*
59+
* @param _rows Number of rows.
60+
* @param _cols Number of columns.
61+
* @param _nnzs Number of non-zeros.
62+
* @param _row_offsets Row offsets.
63+
* @param _column_indices Column indices.
64+
* @param _values Values of non-zeros.
65+
*/
66+
csr_t(index_t& _rows,
67+
index_t& _cols,
68+
offset_t& _nnzs,
69+
std::vector<offset_t>& _row_offsets,
70+
std::vector<index_t>& _column_indices,
71+
std::vector<value_t>& _values)
72+
: rows(_rows),
73+
cols(_cols),
74+
nnzs(_nnzs),
75+
row_offsets(_row_offsets),
76+
column_indices(_column_indices),
77+
values(_values) {}
78+
};
79+
80+
/**
81+
* @brief Graph data structure based on CSR format.
82+
*
83+
* @tparam vertex_t Type of vertex.
84+
* @tparam edge_t Type of edge.
85+
* @tparam weight_t Type of weight.
86+
*/
87+
template <typename vertex_t, typename edge_t, typename weight_t>
88+
struct graph_t : public csr_t<vertex_t, edge_t, weight_t> {
89+
using csr_type = csr_t<vertex_t, edge_t, weight_t>;
90+
using vertex_type = vertex_t;
91+
using edge_type = edge_t;
92+
using weight_type = weight_t;
93+
94+
/**
95+
* @brief Construct a new graph_t object.
96+
*
97+
* @param rows Number of rows.
98+
* @param cols Number of columns.
99+
* @param nnzs Number of non-zeros.
100+
* @param row_offsets Row offsets.
101+
* @param column_indices Column indices.
102+
* @param values Values of non-zeros.
103+
*/
104+
graph_t(vertex_t& rows,
105+
vertex_t& cols,
106+
edge_t& nnzs,
107+
std::vector<edge_t>& row_offsets,
108+
std::vector<vertex_t>& column_indices,
109+
std::vector<weight_t>& values)
110+
: csr_type(rows, cols, nnzs, row_offsets, column_indices, values) {}
111+
112+
weight_t get_edge_weight(edge_t const& e) { return csr_type::values[e]; }
113+
vertex_t get_num_vertices() { return csr_type::rows; }
114+
vertex_t get_dest_vertex(edge_t const& e) {
115+
return csr_type::column_indices[e];
116+
}
117+
auto get_edges(const vertex_t& v) {
118+
return std::ranges::iota_view{csr_type::row_offsets[v],
119+
csr_type::row_offsets[v + 1]};
120+
}
121+
auto get_vertices() { return std::ranges::iota_view{0, get_num_vertices()}; }
122+
};
123+
124+
} // namespace essentials

include/load.hxx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @file load.hxx
33
* @author Muhammad Osama (mosama@ucdavis.edu)
4-
* @brief
4+
* @brief Matrix Market file loader.
55
* @version 0.1
66
*
77
* @copyright Copyright (c) 2022
@@ -14,7 +14,7 @@
1414
#include <assert.h>
1515
#include <externals/mmio.hxx>
1616

17-
namespace sssp {
17+
namespace essentials {
1818

1919
/**
2020
* @brief Matrix Market format supports two kind of formats, a sparse coordinate
@@ -71,10 +71,12 @@ struct matrix_market_t {
7171

7272
int num_rows, num_columns, num_nonzeros;
7373

74+
// COO vectors
7475
std::vector<vertex_t> row_indices;
7576
std::vector<vertex_t> column_indices;
7677
std::vector<weight_t> values;
7778

79+
// CSR vectors
7880
std::vector<edge_t> Ap;
7981
std::vector<vertex_t> Aj;
8082
std::vector<weight_t> Ax;
@@ -86,15 +88,12 @@ struct matrix_market_t {
8688
matrix_market_storage_scheme_t scheme; // Storage scheme
8789

8890
/**
89-
* @brief Loads the given .mtx file into a coordinate format, and returns the
90-
* coordinate array. This needs to be further extended to support dense
91-
* arrays, those are the only two formats mtx are written in.
91+
* @brief Loads the given .mtx file into a coordinate (COO) and
92+
* compressed-sparse row (CSR) formats.
9293
*
9394
* @param _filename input file name (.mtx)
9495
*/
95-
matrix_market_t(std::string _filename) {
96-
filename = _filename;
97-
96+
matrix_market_t(std::string _filename) : filename(_filename) {
9897
file_t file;
9998

10099
// Load MTX information
@@ -238,4 +237,4 @@ struct matrix_market_t {
238237
}
239238
};
240239

241-
} // namespace sssp
240+
} // namespace essentials

include/operators.hxx

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* @file operators.hxx
3+
* @author Muhammad Osama (mosama@ucdavis.edu)
4+
* @brief Operators for graph analytics.
5+
* @version 0.1
6+
*
7+
* @copyright Copyright (c) 2022
8+
*
9+
*/
10+
11+
#pragma once
12+
13+
#include <vector>
14+
#include <algorithm>
15+
#include <execution>
16+
#include <mutex>
17+
#include <utility>
18+
#include <ranges>
19+
20+
/**
21+
* @brief Neighbors expand operator for graph traversal.
22+
*
23+
* @par Overview
24+
* Takes an input frontier and returns the neighbors of the active vertices
25+
* within the frontier as a new frontier. During the traversal to neighbors,
26+
* also applies an expand condition on the tuple of source vertex, neighbor
27+
* vertex, edge and edge weight.
28+
*
29+
* @tparam my_graph_t Graph type.
30+
* @tparam my_frontier_t Frontier type.
31+
* @tparam expand_cond_t Condition type.
32+
* @param g Graph.
33+
* @param f Frontier.
34+
* @param condition User-defined condition.
35+
* @return my_frontier_t New frontier.
36+
*/
37+
template <typename my_graph_t, typename my_frontier_t, typename expand_cond_t>
38+
my_frontier_t neighbors_expand(my_graph_t& g,
39+
my_frontier_t& f,
40+
expand_cond_t condition) {
41+
std::mutex m;
42+
my_frontier_t output;
43+
auto expand = [&](auto const& v) {
44+
// For all edges of vertex v.
45+
for (auto e : g.get_edges(v)) {
46+
auto n = g.get_dest_vertex(e);
47+
auto w = g.get_edge_weight(e);
48+
// If expand condition is
49+
// true, add the neighbor into
50+
// the output frontier.
51+
if (condition(v, n, e, w)) {
52+
std::lock_guard<std::mutex> guard(m);
53+
output.add_vertex(n);
54+
}
55+
}
56+
};
57+
58+
// For all active vertices in the
59+
// frontier, process in parallel.
60+
std::for_each(std::execution::par, f.active_vertices.begin(),
61+
f.active_vertices.end(), expand);
62+
63+
// Return the new output frontier.
64+
return output;
65+
}

0 commit comments

Comments
 (0)