Skip to content
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
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# See README.md for instruction on how to build SHAD with CMake

cmake_minimum_required(VERSION 3.1)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

if (NOT DEFINED SHAD_VERSION_MAJOR)
set(SHAD_VERSION_MAJOR 0)
Expand Down Expand Up @@ -114,6 +115,8 @@ configure_file(
${SHAD_INCLUDE_DIR}/shad/config/test-config.h)

if (SHAD_RUNTIME_SYSTEM STREQUAL "GMT")
set(RUNTIME_PKGS ${RUNTIME_PKGS} "gmt")
# TODO should be use everytime given the MPI dependencies for collective operations
find_package(MPI REQUIRED)
include_directories(${MPI_INCLUDE_PATH})
endif()
Expand All @@ -122,8 +125,12 @@ include_directories(${SHAD_MAIN_INCLUDE_DIR} ${SHAD_INCLUDE_DIR})

configure_file(
${SHAD_MAIN_SRC_DIR}/pkgconfig/shad.pc.in
${SHAD_BINARY_DIR}/pkgconfig/shad.pc @ONLY)
install(FILES ${SHAD_BINARY_DIR}/pkgconfig/shad.pc DESTINATION pkgconfig)
${SHAD_BINARY_DIR}/pkgconfig/shad.pc
@ONLY
)
install(FILES ${SHAD_BINARY_DIR}/pkgconfig/shad.pc
DESTINATION "pkgconfig")

install(FILES ${SHAD_MAIN_SRC_DIR}/cmake/FindSHAD.cmake DESTINATION cmake)

# Test commands
Expand Down
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_subdirectory(array)
add_subdirectory(edge_index_graph)
add_subdirectory(clique_covering)
add_subdirectory(blackscholes)
add_subdirectory(pi)
13 changes: 13 additions & 0 deletions examples/clique_covering/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
set(program
clique_covering)


foreach(p ${program})
add_executable(${p} ${p}.cc)
# Add debug symbols only for Debug and RelWithDebInfo configs:
# target_compile_options(${p} PRIVATE
# $<$<CONFIG:Debug>:-g>
# $<$<CONFIG:RelWithDebInfo>:-g>
# )
target_link_libraries(${p} ${SHAD_RUNTIME_LIB} runtime)
endforeach(p)
124 changes: 124 additions & 0 deletions examples/clique_covering/clique_covering.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//===------------------------------------------------------------*- C++ -*-===//
//
// SHAD
//
// The Scalable High-performance Algorithms and Data Structure Library
//
//===----------------------------------------------------------------------===//
//
// Copyright 2018 Battelle Memorial Institute
//
// 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.
//
//===----------------------------------------------------------------------===//

// Simple implementation of triangle counting, through graph pattern matching

#include <atomic>
#include <fstream>
#include <iostream>
#include <sstream>
#include <utility>

#include <likwid.h>
#include "shad/core/algorithm.h"
#include "shad/data_structures/array.h"
#include "shad/extensions/graph_library/algorithms/jp_coloring.h"
#include "shad/extensions/graph_library/edge_index.h"
#include "shad/runtime/runtime.h"
#include "shad/util/measure.h"

using graph_t = shad::EdgeIndex<size_t, size_t>;

// The GraphReader expects an input file in METIS dump format
graph_t::ObjectID GraphReader(std::ifstream &GFS) {
std::string line;
unsigned long EdgeNumber, VertexNumber;

std::getline(GFS, line);

std::istringstream headlineStream(line);

headlineStream >> VertexNumber >> EdgeNumber;
EdgeNumber <<= 1;

auto eiGraph = graph_t::Create(VertexNumber);
shad::rt::Handle handle;

for (size_t i = 0L; i < VertexNumber; i++) {
size_t destination;

std::getline(GFS, line);
std::istringstream lineStream(line);
std::vector<size_t> edges;
while (!lineStream.eof()) {
lineStream >> destination;
destination--;
edges.push_back(destination);
}
eiGraph->AsyncInsertEdgeList(handle, i, edges.data(), edges.size());
}
shad::rt::waitForCompletion(handle);
return eiGraph->GetGlobalID();
}

void printHelp(const std::string programName) {
std::cerr << "Usage: " << programName << " FILENAME" << std::endl;
}

namespace shad {

int main(int argc, char **argv) {
if (argc != 2) {
printHelp(argv[0]);
return -1;
}

graph_t::ObjectID OID(-1);
auto loadingTime = shad::measure<std::chrono::seconds>::duration([&]() {
// The GraphReader expects an input file in METIS dump format
std::ifstream inputFile;
inputFile.open(argv[1], std::ifstream::in);
OID = GraphReader(inputFile);
});
std::cout << "Graph loaded in " << loadingTime.count()
<< " seconds\nLet's start..." << std::endl;
auto eiPtr = graph_t::GetPtr(OID);

size_t num_vertices = eiPtr->Size();
std::cout << "NumVertices: " << num_vertices
<< " Num Edges: " << eiPtr->NumEdges() << std::endl;
shad::Array<int32_t>::SharedPtr result;
LIKWID_MARKER_REGISTER("foo");
LIKWID_MARKER_START("foo");
auto duration = shad::measure<std::chrono::seconds>::duration(
[&]() { result = jp_coloring<graph_t, size_t>(OID, num_vertices); });
LIKWID_MARKER_STOP("foo");
if (shad::rt::thisLocality() == shad::rt::Locality(0)) {
for (auto i = 0; i < num_vertices; ++i) {
std::cout << i << " " << result->At(i) << "\n";
}

auto c =
*(shad::max_element(result->begin(), result->end(), std::less<>())) + 1;
std::cout << "Num colors " << c << "\n";
}

std::cout << "Success " << duration.count() << " seconds" << std::endl;

graph_t::Destroy(OID);
shad::Array<int32_t>::Destroy(result->GetGlobalID());
return 0;
}

} // namespace shad
144 changes: 144 additions & 0 deletions include/shad/extensions/graph_library/algorithms/jp_coloring.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#ifndef INCLUDE_SHAD_EXTENSIONS_GRAPH_LIBRARY_ALGORITHMS_JP_COVER_H_
#define INCLUDE_SHAD_EXTENSIONS_GRAPH_LIBRARY_ALGORITHMS_JP_COVER_H_

#include <cstdint>
#include <limits>

#include "shad/data_structures/array.h"
#include "shad/extensions/graph_library/edge_index.h"
#include "shad/runtime/runtime.h"

// -------------------------
// Helper: deterministic-ish hash for priority (no RNG needed)
// -------------------------
static inline uint32_t hash32(uint32_t x) {
x ^= x >> 16;
x *= 0x7feb352dU;
x ^= x >> 15;
x *= 0x846ca68bU;
x ^= x >> 16;
return x;
}

// Neighbor scan to find if any UNCOLORED neighbor beats v in priority.
template <typename VertexT>
void jp_check_neighbor(shad::rt::Handle & /*handle*/, const VertexT &v,
const VertexT &nbr,
shad::Array<int32_t>::ObjectID &colorID,
shad::Array<uint8_t>::ObjectID &isWinnerID) {
auto color = shad::Array<int32_t>::GetPtr(colorID);
if (color->At(v) >= 0) return; // v already colored
if (color->At(nbr) >= 0) return; // only compare vs uncolored neighbors

const uint32_t pv = hash32(static_cast<uint32_t>(v));
const uint32_t pn = hash32(static_cast<uint32_t>(nbr));

// Tie-break by vertex id to be deterministic
if (pn > pv || (pn == pv && nbr > v)) {
auto win = shad::Array<uint8_t>::GetPtr(isWinnerID);
win->InsertAt(v, 0); // v is NOT a winner
}
}

// For each vertex: tentatively mark winner=1, then scan neighbors to
// disqualify.
template <typename GraphT, typename VertexT>
void jp_pick_winners(shad::rt::Handle &handle, const VertexT &v,
typename GraphT::ObjectID &gid,
shad::Array<int32_t>::ObjectID &colorID,
shad::Array<uint8_t>::ObjectID &isWinnerID) {
auto color = shad::Array<int32_t>::GetPtr(colorID);
if (color->At(v) >= 0) return;

auto win = shad::Array<uint8_t>::GetPtr(isWinnerID);
win->InsertAt(v, 1); // tentatively winner

auto g = GraphT::GetPtr(gid);
g->AsyncForEachNeighbor(handle, v, jp_check_neighbor<VertexT>, colorID,
isWinnerID);
}

struct Scratch {
std::vector<uint32_t> seen;
};

// A simple (slow but correct) color choice: scan neighbors, mark forbidden
// colors in a small local bitmap. You can optimize later (see section 6).
template <typename GraphT, typename VertexT>
void jp_color_winner_neighbor(const VertexT &v, const VertexT &nbr,
shad::Array<int32_t>::ObjectID &colorID,
Scratch *&sp) {
auto color = shad::Array<int32_t>::GetPtr(colorID);
int32_t cn = color->At(nbr);
if (cn >= 0) sp->seen.push_back(cn);
}

template <typename GraphT, typename VertexT>
void jp_color_winners(shad::rt::Handle &handle, const VertexT &v,
typename GraphT::ObjectID &gid,
shad::Array<int32_t>::ObjectID &colorID,
shad::Array<uint8_t>::ObjectID &isWinnerID) {
auto color = shad::Array<int32_t>::GetPtr(colorID);
if (color->At(v) >= 0) return;

auto win = shad::Array<uint8_t>::GetPtr(isWinnerID);
if (win->At(v) == 0) return; // not a winner this round

Scratch s;
Scratch *sp = &s;

auto g = GraphT::GetPtr(gid);
// TODO does not work with multi node, potentially a vertex could be on
// another node
g->ForEachNeighbor(v, jp_color_winner_neighbor<GraphT, VertexT>, colorID, sp);

auto &u = s.seen;
std::sort(u.begin(), u.end());
u.erase(std::unique(u.begin(), u.end()), u.end());

int32_t mex = 0;
for (int32_t c : u) {
if (c == mex)
++mex;
else if (c > mex)
break;
}
color->InsertAt(v, mex);
u.clear();
}

// Public API: returns vertex->color (clique id) on conflict graph => clique
// cover on compatibility graph.
template <typename GraphT, typename VertexT>
shad::Array<int32_t>::SharedPtr jp_coloring(typename GraphT::ObjectID gid,
size_t num_vertices) {
auto color = shad::Array<int32_t>::Create(num_vertices, -1);
auto win = shad::Array<uint8_t>::Create(num_vertices, 0);

auto colorID = color->GetGlobalID();
auto winID = win->GetGlobalID();

auto g = GraphT::GetPtr(gid);

// Very simple termination: loop fixed rounds until no -1 remains would
// require a reduction; start with a conservative upper bound for a first
// version.
const size_t max_rounds = num_vertices; // refine later
for (size_t r = 0; r < max_rounds; ++r) {
shad::rt::Handle h1;
g->AsyncForEachVertex(h1, jp_pick_winners<GraphT, VertexT>, gid, colorID,
winID);
shad::rt::waitForCompletion(h1);

shad::rt::Handle h2;
g->AsyncForEachVertex(h2, jp_color_winners<GraphT, VertexT>, gid, colorID,
winID);
shad::rt::waitForCompletion(h2);
}

shad::Array<uint8_t>::Destroy(win->GetGlobalID());

return color;
}

#endif // INCLUDE_SHAD_EXTENSIONS_GRAPH_LIBRARY_ALGORITHMS_JP_COVER_H_
6 changes: 4 additions & 2 deletions include/shad/extensions/graph_library/algorithms/sssp.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,14 @@ size_t sssp_length(typename GraphT::ObjectID gid, VertexT src, VertexT dest) {
auto q1Ptr = shad::Set<VertexT>::Create(num_vertices / 2);
auto visited = shad::Array<bool>::Create(num_vertices, false);
auto found = shad::Array<bool>::Create(1, false);
return __sssp_length<GraphT, VertexT>(gid, num_vertices, q0Ptr, q1Ptr,
visited, found, src, dest);

shad::Set<VertexT>::Destroy(q0Ptr->GetGlobalID());
shad::Set<VertexT>::Destroy(q1Ptr->GetGlobalID());
shad::Array<bool>::Destroy(visited->GetGlobalID());
shad::Array<bool>::Destroy(found->GetGlobalID());

return __sssp_length<GraphT, VertexT>(gid, num_vertices, q0Ptr, q1Ptr,
visited, found, src, dest);
}

#endif // INCLUDE_SHAD_EXTENSIONS_GRAPH_LIBRARY_ALGORITHMS_SSSP_H_
Loading