Skip to content

BFS and Bellman Ford implementation #32

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

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@

# IDEA configurations
/.idea

# Doc files
/docs*
46 changes: 46 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,20 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${GraphMLIR_BINARY_DIR})

set(GraphMLIR_EXAMPLES OFF CACHE BOOL "Build examples")

set(GraphMLIR_BENCHMARK OFF CACHE BOOL "Benchmark the Graph Algorithms")

# Add MLIR and LLVM headers to the include path
include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${MLIR_INCLUDE_DIRS})

# Add GraphMLIR files to the include path
include_directories(${GraphMLIR_MAIN_INCLUDE_DIR})
include_directories(${GraphMLIR_INCLUDE_DIR})
include_directories(${GraphMLIR_INCLUDE_DIR}/Interface)
include_directories(${GraphMLIR_INCLUDE_DIR}/Dialect)
include_directories(${GraphMLIR_INCLUDE_DIR}/Utility)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include/Dialect)
include_directories(${GraphMLIR_SOURCE_DIR}/lib)

#-------------------------------------------------------------------------------
# Directory setup
Expand All @@ -82,3 +87,44 @@ add_subdirectory(tools)
if(GraphMLIR_EXAMPLES)
add_subdirectory(examples)
endif()

if(GraphMLIR_BENCHMARK)
#-------------------------------------------------------------------------------
# Deploy google/benchmark
#-------------------------------------------------------------------------------

message(STATUS "Configuring benchmarks: google")

include(ExternalProject)

ExternalProject_Add(project_googlebenchmark
GIT_REPOSITORY https://github.com/google/benchmark.git
GIT_TAG "v1.6.0"
GIT_SHALLOW 1
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/benchmark
TIMEOUT 10
BUILD_BYPRODUCTS <INSTALL_DIR>/lib/${CMAKE_STATIC_LIBRARY_PREFIX}benchmark${CMAKE_STATIC_LIBRARY_SUFFIX}
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/vendor/benchmark
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DBENCHMARK_ENABLE_TESTING=OFF
UPDATE_COMMAND ""
TEST_COMMAND "")

ExternalProject_Get_Property(project_googlebenchmark INSTALL_DIR)

file(MAKE_DIRECTORY ${INSTALL_DIR}/include)
add_library(GoogleBenchmark STATIC IMPORTED)
target_include_directories(GoogleBenchmark INTERFACE ${INSTALL_DIR}/include)
set_property(TARGET GoogleBenchmark PROPERTY IMPORTED_LOCATION
"${INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}benchmark${CMAKE_STATIC_LIBRARY_SUFFIX}")

add_dependencies(GoogleBenchmark project_googlebenchmark)

find_package(Threads)
target_link_libraries(GoogleBenchmark INTERFACE Threads::Threads)
endif()

if(GraphMLIR_BENCHMARK)
add_subdirectory(benchmarks)
endif()
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
# GraphMLIR

An IR based solution for optimising graph algorithms.

## Clone repository and its dependencies

```
git clone https://github.com/meshtag/GraphMLIR.git
cd GraphMLIR
git submodule update --init
```

## Build LLVM

```
cd llvm && mkdir build && cd build
cmake -G Ninja ../llvm \
Expand All @@ -21,6 +24,7 @@ ninja check-mlir
```

## Build project

```
cd ../../ && mkdir build && cd build
cmake -G Ninja .. \
Expand All @@ -32,3 +36,27 @@ cmake -G Ninja .. \
ninja bfsExample
cd bin && ./bfsExample
```

## Benchmark project

```
cmake -G Ninja .. \
-DMLIR_DIR=$PWD/../llvm/build/lib/cmake/mlir \
-DLLVM_DIR=$PWD/../llvm/build/lib/cmake/llvm \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DCMAKE_BUILD_TYPE=RELEASE \
-DGraphMLIR_BENCHMARK=ON \
-DLEMON_DIR=/PATH/TO/LEMON/SOURCE/CODE
ninja graph-processing-benchmark
cd bin && ./graph-processing-benchmark
```

_Note_ : Rename the `lemon.1.x.x` folder to `lemon`. For benchmarking install `BOOST` library in system.

## Instructions for generating docs

```
Use doxywizard for generating docs automatically from relevant source directories.
```

#### After this go to docs and open index.html in the html subdirectory with your prefered browser.
80 changes: 80 additions & 0 deletions benchmarks/Bfs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include <benchmark/benchmark.h>
#include <bits/stdc++.h>

using namespace std;

#define V 1000

namespace {
int graph[V][V];
int parent[V];
int dist[V];
} // namespace

void bfs(int graph[V][V], int *parent, int *dist) {
bool visited[V];

for (int i = 0; i < V; i++)
visited[i] = false;

queue<int> q;

visited[0] = true;
q.push(0);

while (!q.empty()) {
int u = q.front();
q.pop();

for (int v = 0; v < V; v++) {
if (visited[v] == false && graph[u][v] != 0) {
visited[v] = true;

dist[v] = dist[u] + graph[u][v];
parent[v] = u;

q.push(v);
}
}
}
}

void initializeBfs() {
int MAX_EDGES = V * (V - 1) / 2;

for (int i = 0; i < MAX_EDGES; i++) {
int u = rand() % V;
int v = rand() % V;
int d = rand() % 100;

graph[u][v] = d;
}
}

static void Bfs(benchmark::State &state) {
for (auto _ : state) {
for (int i = 0; i < state.range(0); i++) {
bfs(graph, parent, dist);
}
}
}

BENCHMARK(Bfs)->Arg(1);

void generateResultBfs() {
initializeBfs();
cout << "-------------------------------------------------------\n";
cout << "BFS Result Information ]\n";

bfs(graph, parent, dist);

for (int i = 0; i < V; i++)
cout << parent[i] << " ";
cout << endl;

for (int i = 0; i < V; i++)
cout << dist[i] << " ";
cout << endl;

cout << "BFS operation finished!\n";
}
112 changes: 112 additions & 0 deletions benchmarks/BoostBellmanFordBenchmarking.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
//===- BoostBellmanforBenchmarking.cpp -----------------------------------===//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//===----------------------------------------------------------------------===//
//
// This file implements the benchmark for Boost Bellmanford example benchmark.
//
//===----------------------------------------------------------------------===//

#include <iostream>
#include <benchmark/benchmark.h>
#include <boost/config.hpp>
#include <boost/graph/undirected_graph.hpp>
#include <boost/graph/exterior_property.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/bellman_ford_shortest_paths.hpp>
#include <vector>
#include <Utility/Utils.h>

using namespace std;

#define SIZE 100

namespace {
typedef int t_weight;

// define the graph type
typedef boost::property<boost::edge_weight_t, t_weight> EdgeWeightProperty;
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
boost::no_property, EdgeWeightProperty>
Graph;

typedef boost::property_map<Graph, boost::edge_weight_t>::type WeightMap;


Graph g;

std::vector<int> distnce(SIZE, (std::numeric_limits<int>::max)());
int source_node_index = 0;
std::vector<std::size_t> parent(SIZE);

} // namespace

void initializeBoostBellmanFord() {

const int vertices = SIZE;
int num_edges = vertices * (vertices -1) / 2;

// define edges
// int edges[] = {1, 2, 2, 3, 3, 4, 4, 1, 1, 3, 2, 4};

// t_weight weight[] = {4, 3, 3, 6, 2, 2};

std::vector<int> edges;
std::vector<int> weight;

graph::generateRandomGraph(edges, weight, vertices);

for (std::size_t k = 0; k < num_edges; ++k)
boost::add_edge(edges[k * 2] - 1, edges[k * 2 + 1] - 1, weight[k], g);
WeightMap weight_pmap = boost::get(boost::edge_weight, g);


for (int i = 0; i < num_vertices(g); ++i)
parent[i] = i;
distnce[source_node_index] = 0;


}

// Benchmarking function.
static void Boost_BellmanFord(benchmark::State &state) {

for (auto _ : state) {
WeightMap weight_pmap = boost::get(boost::edge_weight, g);

for (int i = 0; i < state.range(0); ++i) {
bool r = bellman_ford_shortest_paths(g, num_vertices(g), weight_pmap, &parent[0],
&distnce[0], boost::closed_plus< int >(), std::less< int >(),
boost::default_bellman_visitor());
}
}
}

// Register benchmarking function.
BENCHMARK(Boost_BellmanFord)->Arg(1);

void generateResultBoostBellmanFord() {
initializeBoostBellmanFord();
WeightMap weight_pmap = boost::get(boost::edge_weight, g);
for (int i = 0; i < num_vertices(g); ++i)
parent[i] = i;
distnce[source_node_index] = 0;

cout << "-------------------------------------------------------\n";
cout << "[ BOOST FloydWarshall Result Information ]\n";
bool r = bellman_ford_shortest_paths(g, num_vertices(g), weight_pmap, &parent[0],
&distnce[0], boost::closed_plus< int >(), std::less< int >(),
boost::default_bellman_visitor());
cout << "Boost FloydWarshall operation finished!\n";
}
Loading