Skip to content
This repository has been archived by the owner on Dec 22, 2022. It is now read-only.

Benchmarking, Triangle Counting, Intersection. #145

Merged
merged 69 commits into from
Jun 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
499acbf
update CL description
annielytical Apr 10, 2022
a323515
typo fix
annielytical Apr 16, 2022
f648f02
benchmarking
annielytical May 2, 2022
80b0974
Merge branch 'gunrock:master' into master
annielytical May 9, 2022
f1e3423
Merge branch 'gunrock:master' into bench
annielytical May 9, 2022
2a93db0
benchmarking fixes
annielytical May 10, 2022
0ec56de
name updates
annielytical May 10, 2022
2c6f039
more benchmarks
annielytical May 10, 2022
0899edc
Fix cuda namespace collision
jdwapman May 18, 2022
4605cb8
Merge branch 'master' into dev_pull
jdwapman May 18, 2022
9a95991
pass file to nvbench (still has free error)
annielytical May 23, 2022
778517a
minor tweaks
annielytical May 23, 2022
540d159
multiple benchmarks
annielytical May 23, 2022
9002360
Support reading smtx files
jdwapman May 28, 2022
d2cf9c0
Merge branch 'dev_pull' of github.com:jdwapman/essentials into dev_pull
jdwapman May 28, 2022
c3a17ab
Merge pull request #138 from jdwapman/dev_pull
neoblizz May 28, 2022
de8d03c
multiple benchmarks
annielytical May 29, 2022
187f5db
param fixes
annielytical May 29, 2022
22d2f8e
add more algorithm benchmarks
annielytical May 29, 2022
7d527c7
split benchmarks; add geo / hits
annielytical Jun 1, 2022
4e2b399
add spgemm
annielytical Jun 1, 2022
5def279
geo fixes
annielytical Jun 2, 2022
37dc586
cleanup
annielytical Jun 2, 2022
12910c9
Merge pull request #1 from annielytical/bench
annielytical Jun 2, 2022
21e2a6f
cleanup
annielytical Jun 2, 2022
f1851a3
Merge pull request #2 from annielytical/bench
annielytical Jun 2, 2022
dd66976
benchmark testing script
annielytical Jun 2, 2022
0766c56
[skip ci] test_benchmarks script updates
annielytical Jun 3, 2022
d1f668c
Merge pull request #139 from annielytical/master
neoblizz Jun 3, 2022
b7881e4
Add initial TC implementation
maawad Jun 17, 2022
992ab27
Add binary search using lower bound
maawad Jun 18, 2022
c9231d4
Count total number of triangles
maawad Jun 18, 2022
79b0d78
Use lower bound
maawad Jun 18, 2022
19011d1
Add unit test
maawad Jun 18, 2022
166809f
Add switch source and destionation optimization
maawad Jun 22, 2022
9fd00ac
Remove comments
maawad Jun 22, 2022
115a1b1
Fix documentation
maawad Jun 22, 2022
2b08742
Add post processing step
maawad Jun 22, 2022
c9ee768
[skip ci] Use thrust algorithm for lower bound
maawad Jun 23, 2022
d89537d
[skip ci] User entire graph as input frontier
maawad Jun 23, 2022
f514314
[skip ci] Remove dead code
maawad Jun 23, 2022
c1f1b55
Remove edge and vertices count from `graph`
maawad Jun 23, 2022
c53f7d8
Move `syncthreads` to correct location
maawad Jun 23, 2022
3e16375
Correct initializer list order
maawad Jun 23, 2022
197325f
[skip ci] Add intersection optimization back
maawad Jun 23, 2022
17567b8
Fix compile error
maawad Jun 23, 2022
bc7cb06
Remove dead code
maawad Jun 23, 2022
6b8b15f
Intersection + Triangle Counting algorithm and improvements.
neoblizz Jun 24, 2022
0cc81b1
Add TC benchmarking
maawad Jun 24, 2022
f8efd99
Add TC to script
maawad Jun 24, 2022
efd574b
Remove extra comment
maawad Jun 24, 2022
08775e5
Merge pull request #141 from maawad/tc_bench
neoblizz Jun 24, 2022
bd2d44d
Simplifying readme.
neoblizz Jun 25, 2022
51f005b
Add reference CPU TC implementation
maawad Jun 25, 2022
101b630
Use `cxxopts` and add validation option
maawad Jun 25, 2022
914b2a2
Add self loop unit test
maawad Jun 25, 2022
d69f762
Handle self loops in intersection lambda
maawad Jun 25, 2022
10dc2bf
Add self loops not in `get_intersection_count`
maawad Jun 25, 2022
ba0deca
Remove extra comments
maawad Jun 25, 2022
7463dbe
Remove debugging code
maawad Jun 25, 2022
ab7b3ec
Add optimization back
maawad Jun 25, 2022
df0f3c1
Improved dataset collection from gunrock.
neoblizz Jun 26, 2022
36373c0
Points generator imported from gunrock.
neoblizz Jun 26, 2022
ff50e26
(wip) improvements to coloring.
neoblizz Jun 26, 2022
0df4c41
Advance does NOT remove self-loops for the user.
neoblizz Jun 26, 2022
3e1a6bc
simpler logic for bfs.
neoblizz Jun 26, 2022
4401db4
Merge pull request #144 from maawad/tc_validate
neoblizz Jun 26, 2022
2db6b52
or/and fixes.
neoblizz Jun 26, 2022
fa0fa06
[skip ubuntu] minor clarity in code.
neoblizz Jun 26, 2022
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
40 changes: 25 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# **Essentials:** High-Performance C++ GPU Graph Analytics
# [Essentials: High-Performance C++ GPU Graph Analytics](https://github.com/gunrock/essentials/wiki)
[![Ubuntu](https://github.com/gunrock/essentials/actions/workflows/ubuntu.yml/badge.svg)](https://github.com/gunrock/essentials/actions/workflows/ubuntu.yml) [![Windows](https://github.com/gunrock/essentials/actions/workflows/windows.yml/badge.svg)](https://github.com/gunrock/essentials/actions/workflows/windows.yml) [![Code Quality](https://github.com/gunrock/essentials/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/gunrock/essentials/actions/workflows/codeql-analysis.yml) [![Ubuntu: Testing](https://github.com/gunrock/essentials/actions/workflows/ubuntu-tests.yml/badge.svg)](https://github.com/gunrock/essentials/actions/workflows/ubuntu-tests.yml)

**Gunrock/Essentials** is a CUDA library for graph-processing designed specifically for the GPU. It uses a **high-level**, **bulk-synchronous**, **data-centric abstraction** focused on operations on vertex or edge frontiers. Gunrock achieves a balance between performance and expressiveness by coupling high-performance GPU computing primitives and optimization strategies, particularly in the area of fine-grained load balancing, with a high-level programming model that allows programmers to quickly develop new graph primitives that scale from one to many GPUs on a node with small code size and minimal GPU programming knowledge.

## Quick Start Guide

Before building Gunrock make sure you have **CUDA Toolkit**[^1] installed on your system. Other external dependencies such as `NVIDIA/thrust`, `NVIDIA/cub`, etc. are automatically fetched using `cmake`.
- [Gunrock's Documentation](https://github.com/gunrock/essentials/wiki)

Before building Gunrock make sure you have **CUDA Toolkit**[<sup>[1]</sup>](#footnotes) installed on your system. Other external dependencies such as `NVIDIA/thrust`, `NVIDIA/cub`, etc. are automatically fetched using `cmake`.

```shell
git clone https://github.com/gunrock/essentials.git
Expand All @@ -15,20 +17,8 @@ cmake ..
make sssp # or for all algorithms, use: make -j$(nproc)
bin/sssp ../datasets/chesapeake/chesapeake.mtx
```
[^1]: Preferred **CUDA v11.5.1 or higher** due to support for stream ordered memory allocators (e.g. `cudaFreeAsync()`).

## Getting Started with Gunrock

- [👻 (GitHub Template) `essentials` project example](https://github.com/gunrock/applications)
- [Gunrock's documentation](https://github.com/gunrock/essentials/wiki)
- [Gunrock's overview](https://github.com/gunrock/essentials/wiki/Overview)
- [Gunrock's programming model](https://github.com/gunrock/essentials/wiki/Programming-Model)
- [Publications](https://github.com/gunrock/essentials/wiki/Publications) and [presentations](https://github.com/gunrock/essentials/wiki/Presentations)
- [Essentials](https://github.com/gunrock/essentials) versus [Gunrock](https://github.com/gunrock/gunrock)[^2]

[^2]: Essentials is the future of Gunrock. The idea is to take the lessons learned from Gunrock to a new design, which simplifies the effort it takes to **(1)** implement graph algorithms, **(2)** add internal optimizations, **(3)** conduct future research. One example is Gunrock's SSSP, implemented in 4-5 files with 1000s of lines of code versus in essentials, it is a single file with less than 200 lines of code. Our end goal with essentials is possibly releasing it as a `v2.0.0` for Gunrock.

## How to Cite Gunrock
## How to Cite Gunrock & Essentials
Thank you for citing our work.

```tex
Expand All @@ -53,6 +43,26 @@ Thank you for citing our work.
}
```

```tex
@InProceedings{Osama:2022:EOP,
author = {Muhammad Osama and Serban D. Porumbescu and John D. Owens},
title = {Essentials of Parallel Graph Analytics},
booktitle = {Proceedings of the Workshop on Graphs,
Architectures, Programming, and Learning},
year = 2022,
series = {GrAPL 2022},
month = may,
pages = {314--317},
doi = {10.1109/IPDPSW55747.2022.00061},
url = {https://escholarship.org/uc/item/2p19z28q},
}
```

## Copyright and License

Gunrock is copyright The Regents of the University of California. The library, examples, and all source code are released under [Apache 2.0](https://github.com/gunrock/essentials/blob/master/LICENSE).

<a class="anchor" id="1"></a>
## Footnotes
1. Preferred **CUDA v11.5.1 or higher** due to support for stream ordered memory allocators (e.g. `cudaFreeAsync()`).
2. Essentials is intended as a future release of Gunrock. You can read more about in our vision paper: [Essentials of Parallel Graph Analytics](https://escholarship.org/content/qt2p19z28q/qt2p19z28q_noSplash_38a658bccc817ba025517311a776840f.pdf).
34 changes: 27 additions & 7 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
set(BENCHMARK_SOURCES
for.cu
bc_bench.cu
bfs_bench.cu
color_bench.cu
geo_bench.cu
hits_bench.cu
kcore_bench.cu
mst_bench.cu
ppr_bench.cu
pr_bench.cu
spgemm_bench.cu
spmv_bench.cu
sssp_bench.cu
tc_bench.cu
)

foreach(SOURCE IN LISTS BENCHMARK_SOURCES)
get_filename_component(BENCHMARK_NAME ${SOURCE} NAME_WLE)
add_executable(${BENCHMARK_NAME} ${SOURCE})
target_link_libraries(${BENCHMARK_NAME}
PRIVATE essentials
PRIVATE nvbench::main
)
get_target_property(ESSENTIALS_ARCHITECTURES
if(SOURCE MATCHES "for.cu")
target_link_libraries(${BENCHMARK_NAME}
PRIVATE essentials
PRIVATE nvbench::main
)
else()
target_link_libraries(${BENCHMARK_NAME}
PRIVATE essentials
PRIVATE nvbench::nvbench
)
endif()
get_target_property(ESSENTIALS_ARCHITECTURES
essentials CUDA_ARCHITECTURES
)
set_target_properties(${BENCHMARK_NAME}
PROPERTIES
set_target_properties(${BENCHMARK_NAME}
PROPERTIES
CUDA_ARCHITECTURES ${ESSENTIALS_ARCHITECTURES}
)
message(STATUS "Benchmark Added: ${BENCHMARK_NAME}")
Expand Down
130 changes: 130 additions & 0 deletions benchmarks/bc_bench.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include <nvbench/nvbench.cuh>
#include <cxxopts.hpp>
#include <gunrock/algorithms/algorithms.hxx>
#include <gunrock/algorithms/bc.hxx>

using namespace gunrock;
using namespace memory;

using vertex_t = int;
using edge_t = int;
using weight_t = float;

std::string filename;

struct parameters_t {
std::string filename;
bool help = false;
cxxopts::Options options;

/**
* @brief Construct a new parameters object and parse command line arguments.
*
* @param argc Number of command line arguments.
* @param argv Command line arguments.
*/
parameters_t(int argc, char** argv) : options(argv[0], "BC Benchmarking") {
options.allow_unrecognised_options();
// Add command line options
options.add_options()("h,help", "Print help") // help
("m,market", "Matrix file",
cxxopts::value<std::string>()); // mtx

// Parse command line arguments
auto result = options.parse(argc, argv);

if (result.count("help")) {
help = true;
std::cout << options.help({""});
std::cout << " [optional nvbench args]" << std::endl << std::endl;
// Do not exit so we also print NVBench help.
} else {
if (result.count("market") == 1) {
filename = result["market"].as<std::string>();
if (!util::is_market(filename)) {
std::cout << options.help({""});
std::cout << " [optional nvbench args]" << std::endl << std::endl;
std::exit(0);
}
} else {
std::cout << options.help({""});
std::cout << " [optional nvbench args]" << std::endl << std::endl;
std::exit(0);
}
}
}
};

void bc_bench(nvbench::state& state) {
// --
// Add metrics
state.collect_dram_throughput();
state.collect_l1_hit_rates();
state.collect_l2_hit_rates();
state.collect_loads_efficiency();
state.collect_stores_efficiency();

// --
// Define types
using csr_t =
format::csr_t<memory_space_t::device, vertex_t, edge_t, weight_t>;

// --
// Build graph + metadata
csr_t csr;
io::matrix_market_t<vertex_t, edge_t, weight_t> mm;
csr.from_coo(mm.load(filename));

thrust::device_vector<vertex_t> row_indices(csr.number_of_nonzeros);
thrust::device_vector<vertex_t> column_indices(csr.number_of_nonzeros);
thrust::device_vector<edge_t> column_offsets(csr.number_of_columns + 1);

auto G = graph::build::from_csr<memory_space_t::device,
graph::view_t::csr>(
csr.number_of_rows, // rows
csr.number_of_columns, // columns
csr.number_of_nonzeros, // nonzeros
csr.row_offsets.data().get(), // row_offsets
csr.column_indices.data().get(), // column_indices
csr.nonzero_values.data().get(), // values
row_indices.data().get(), // row_indices
column_offsets.data().get() // column_offsets
);

// --
// Params and memory allocation
vertex_t n_vertices = G.get_number_of_vertices();
thrust::device_vector<weight_t> bc_values(n_vertices);

// --
// Run BC with NVBench
state.exec(nvbench::exec_tag::sync, [&](nvbench::launch& launch) {
gunrock::bc::run(G, bc_values.data().get());
});
}

int main(int argc, char** argv) {
parameters_t params(argc, argv);
filename = params.filename;

if (params.help) {
// Print NVBench help.
const char* args[1] = {"-h"};
NVBENCH_MAIN_BODY(1, args);
} else {
// Create a new argument array without matrix filename to pass to NVBench.
char* args[argc - 2];
int j = 0;
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--market") == 0 || strcmp(argv[i], "-m") == 0) {
i++;
continue;
}
args[j] = argv[i];
j++;
}

NVBENCH_BENCH(bc_bench);
NVBENCH_MAIN_BODY(argc - 2, args);
}
}
137 changes: 137 additions & 0 deletions benchmarks/bfs_bench.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#include <nvbench/nvbench.cuh>
#include <cxxopts.hpp>
#include <gunrock/algorithms/algorithms.hxx>
#include <gunrock/algorithms/bfs.hxx>

using namespace gunrock;
using namespace memory;

using vertex_t = int;
using edge_t = int;
using weight_t = float;

std::string filename;

struct parameters_t {
std::string filename;
bool help = false;
cxxopts::Options options;

/**
* @brief Construct a new parameters object and parse command line arguments.
*
* @param argc Number of command line arguments.
* @param argv Command line arguments.
*/
parameters_t(int argc, char** argv) : options(argv[0], "BFS Benchmarking") {
options.allow_unrecognised_options();
// Add command line options
options.add_options()("h,help", "Print help") // help
("m,market", "Matrix file",
cxxopts::value<std::string>()); // mtx

// Parse command line arguments
auto result = options.parse(argc, argv);

if (result.count("help")) {
help = true;
std::cout << options.help({""});
std::cout << " [optional nvbench args]" << std::endl << std::endl;
// Do not exit so we also print NVBench help.
} else {
if (result.count("market") == 1) {
filename = result["market"].as<std::string>();
if (!util::is_market(filename)) {
std::cout << options.help({""});
std::cout << " [optional nvbench args]" << std::endl << std::endl;
std::exit(0);
}
} else {
std::cout << options.help({""});
std::cout << " [optional nvbench args]" << std::endl << std::endl;
std::exit(0);
}
}
}
};

void bfs_bench(nvbench::state& state) {
// --
// Add metrics
state.collect_dram_throughput();
state.collect_l1_hit_rates();
state.collect_l2_hit_rates();
state.collect_loads_efficiency();
state.collect_stores_efficiency();

// --
// Define types
using csr_t =
format::csr_t<memory_space_t::device, vertex_t, edge_t, weight_t>;

// --
// IO
csr_t csr;

io::matrix_market_t<vertex_t, edge_t, weight_t> mm;
csr.from_coo(mm.load(filename));

thrust::device_vector<vertex_t> row_indices(csr.number_of_nonzeros);
thrust::device_vector<vertex_t> column_indices(csr.number_of_nonzeros);
thrust::device_vector<edge_t> column_offsets(csr.number_of_columns + 1);

// --
// Build graph + metadata
auto G = graph::build::from_csr<memory_space_t::device,
graph::view_t::csr>(
csr.number_of_rows, // rows
csr.number_of_columns, // columns
csr.number_of_nonzeros, // nonzeros
csr.row_offsets.data().get(), // row_offsets
csr.column_indices.data().get(), // column_indices
csr.nonzero_values.data().get(), // values
row_indices.data().get(), // row_indices
column_offsets.data().get() // column_offsets
);

// --
// Params and memory allocation
vertex_t single_source = 0;

vertex_t n_vertices = G.get_number_of_vertices();
thrust::device_vector<vertex_t> distances(n_vertices);
thrust::device_vector<vertex_t> predecessors(n_vertices);

// --
// Run BFS with NVBench
state.exec(nvbench::exec_tag::sync, [&](nvbench::launch& launch) {
gunrock::bfs::run(G, single_source, distances.data().get(),
predecessors.data().get());
});
}

int main(int argc, char** argv) {
parameters_t params(argc, argv);
filename = params.filename;

if (params.help) {
// Print NVBench help.
const char* args[1] = {"-h"};
NVBENCH_MAIN_BODY(1, args);
} else {
// Create a new argument array without matrix filename to pass to NVBench.
char* args[argc - 2];
int j = 0;
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--market") == 0 || strcmp(argv[i], "-m") == 0) {
i++;
continue;
}
args[j] = argv[i];
j++;
}

NVBENCH_BENCH(bfs_bench);
NVBENCH_MAIN_BODY(argc - 2, args);
}
}
Loading