From 69c5328b32abf5a8fec8810e2ba7ffc26f78e937 Mon Sep 17 00:00:00 2001 From: Louis Jenkins Date: Wed, 6 Jan 2021 12:28:05 -0500 Subject: [PATCH] Making steady progress, need to debug segfault. --- src/RGraph.hpp | 9 +++++ src/main.cpp | 3 +- src/rideables/TGraph.hpp | 30 ++++++++++++++ src/tests/GraphTest.hpp | 87 ++++++++++++++++++++++++++++------------ 4 files changed, 101 insertions(+), 28 deletions(-) diff --git a/src/RGraph.hpp b/src/RGraph.hpp index ab483c00..3115559f 100644 --- a/src/RGraph.hpp +++ b/src/RGraph.hpp @@ -26,6 +26,15 @@ class RGraph : public Rideable{ * @return True if the edge exists */ virtual bool remove_edge(int src, int dest) = 0; + + /** + * @brief Removes any edge from the selected vertex. + * + * @param src The integer id of the source node. + * @return true If an edge can be removed. + * @return false If an edge cannot be removed, i.e. non-allocated vertex + */ + virtual bool remove_any_edge(int src) = 0; /** * @brief Removes vertex from graph, along with the incoming and outgoing edges. diff --git a/src/main.cpp b/src/main.cpp index 91d49021..db97eba3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -144,8 +144,7 @@ int main(int argc, char *argv[]) #ifndef MNEMOSYNE gtc.addTestOption(new RecoverVerifyTest(), "RecoverVerifyTest"); - gtc.addTestOption(new GraphTest(1000000,numVertices,33,33,33, 1), "GraphTest:1m:i33r33l33:c1"); - gtc.addTestOption(new GraphTest(1000000,numVertices,25,25,25,25), "GraphTest:1m:i25r25l25:c25"); + gtc.addTestOption(new GraphTest(1000000,numVertices, meanEdgesPerVertex), "GraphTest:1m:i33r33l33:c1"); // gtc.addTestOption(new GraphRecoveryTest("graph_data/", "orkut-edge-list_", 28610, 5, true), "GraphRecoveryTest:Orkut:verify"); // gtc.addTestOption(new GraphRecoveryTest("graph_data/", "orkut-edge-list_", 28610, 5, false), "GraphRecoveryTest:Orkut:noverify"); gtc.addTestOption(new TGraphConstructionTest("graph_data/", "orkut-edge-list_", 28610, 5), "TGraphConstructionTest:Orkut"); diff --git a/src/rideables/TGraph.hpp b/src/rideables/TGraph.hpp index 44986927..b3739f06 100644 --- a/src/rideables/TGraph.hpp +++ b/src/rideables/TGraph.hpp @@ -260,6 +260,36 @@ class TGraph : public RGraph{ } return true; } + + bool remove_any_edge(int vid) { + lock(vid); + int src = -1; + int dest = -1; + + if (idxToVertex[src] != nullptr) { + // Check source first + auto search = source(src).begin(); + if (search == source(src).end()) { + // Then destination + search = destination(src).begin(); + if (search == destination(src).end()) { + goto failure; + } + } + std::shared_ptr r = *search; + src = r->src; + dest = r->dest; + } + + failure: + unlock(vid); + if (src == -1 || dest == -1) { + return false; + } else { + return remove_edge(src, dest); + } + } + bool remove_vertex(int vid) { startOver: diff --git a/src/tests/GraphTest.hpp b/src/tests/GraphTest.hpp index 7904725d..35dbfbf4 100644 --- a/src/tests/GraphTest.hpp +++ b/src/tests/GraphTest.hpp @@ -11,6 +11,7 @@ #include #include #include +#include static void print_stats(int numV, int numE, double averageDegree, int *vertexDegrees, int vertexDegreesLength) { int maxDegree = 0; @@ -26,8 +27,8 @@ static void print_stats(int numV, int numE, double averageDegree, int *vertexDeg } for (auto&& x : indexed(h)) { if (*x == 0) continue; - std::cout << boost::format("bin %i [ %.1f, %.1f ): %i\n") - % x.index() % x.bin().lower() % x.bin().upper() % *x; + std::cout << boost::format("bin %i: %i\n") + % x.index() % *x; } } @@ -37,22 +38,33 @@ class GraphTest : public Test { uint64_t total_ops; uint64_t *thd_ops; uint64_t max_verts; - int pi; - int pr; - int pl; - int pc; - unsigned prop_inserts, prop_removes, prop_lookup, prop_clear; + int insertionProb; + int removalProb; + int lookupProb; + int clearProb; + int desiredAvgDegree; + std::atomic workingThreads; + std::atomic threadsDone; - GraphTest(uint64_t numOps, uint64_t max_verts, int insertP, int removeP, int lookupP, int clearP) : - total_ops(numOps), max_verts(max_verts), pi(insertP), pr(removeP), pl(lookupP), pc(clearP) { - if (insertP + removeP + lookupP + clearP != 100) { - errexit("Probability of insert/remove/lookup must accumulate to 100!"); - } - prop_inserts = pi; - prop_removes = pi + pr; - prop_lookup = pi + pr + pl; - prop_clear = pi + pr + pl + pc; - } + + GraphTest(uint64_t numOps, uint64_t max_verts, int desiredAvgDegree) : + total_ops(numOps), max_verts(max_verts), desiredAvgDegree(desiredAvgDegree) { + } + + // New ratio is based on delta = averageDegree - desiredAvgDegree + // When delta = 0, it defaults to (33%,33%,33%,1%), but we adjust based on delta such that: + // 1) insertProb (33% + delta) + removalProb (33% - delta) = 66% + // 2) clearProb = min(0, max(1, delta / 33%)) + // 3) lookupProb = 100% - insertProb - removalProb - clearProb + void update_ratio(double averageDegree) { + double ratio = min(2.0, max(desiredAvgDegree / averageDegree - 1, averageDegree / desiredAvgDegree - 1)); + int delta = 1650 * ratio; // 16.5% is half of 33% + insertionProb = 3300 + delta; + removalProb = 3300 - delta; + clearProb = min(0.0, max(1.0, delta / 3300.0)); + lookupProb = 10000 - insertionProb - removalProb - clearProb; + std::cout << "(" << insertionProb / 100.0 << "," << removalProb / 100.0 << "," << lookupProb / 100.0 << "," << clearProb / 100.0 << ")" << std::endl; + } void init(GlobalTestConfig *gtc) { uint64_t new_ops = total_ops / gtc->task_num; @@ -74,20 +86,44 @@ class GraphTest : public Test { gtc->interval = numeric_limits::max(); auto stats = g->grab_stats(); std::apply(print_stats, stats); + update_ratio(std::get<2>(stats)); + workingThreads = gtc->task_num; + threadsDone = 0; } int execute(GlobalTestConfig *gtc, LocalTestConfig *ltc) { int tid = ltc->tid; std::mt19937_64 gen_p(ltc->seed); + std::mt19937_64 gen_v(ltc->seed + 1); + std::uniform_int_distribution<> dist(0,9999); + std::uniform_int_distribution<> distv(0,max_verts-1); for (size_t i = 0; i < thd_ops[ltc->tid]; i++) { - // Sketch: - // 1) Obtain metrics for average degree, make decision based on - // degree distribution, i.e. keep an array of pairs that are collected - // based on potential connectivity of the graph. - // 2) Use said metrics and data structures obtained from metrics to do insertions - // and removals in phases, split among threads. - // 3) Between each phase, print out metrics; log |V|, |E|, average degree, and maximum degree as a - // datapoint to be plot later. + if ((i+1) % 1000 == 0) { + threadsDone++; + while (threadsDone != workingThreads) { + pthread_yield(); + } + if (tid == 0) { + auto stats = g->grab_stats(); + std::apply(print_stats, stats); + update_ratio(std::get<2>(stats)); + threadsDone = 0; + } else { + while (threadsDone == workingThreads) { + pthread_yield(); + } + } + } + int rng = dist(gen_p); + if (rng <= insertionProb) { + g->add_edge(distv(gen_v), distv(gen_v), -1); + } else if (rng <= insertionProb + removalProb) { + g->remove_any_edge(distv(gen_v)); + } else if (rng <= insertionProb + removalProb + lookupProb) { + g->has_edge(distv(gen_v), distv(gen_v)); + } else { + g->remove_vertex(distv(gen_v)); + } } return thd_ops[ltc->tid]; } @@ -98,7 +134,6 @@ class GraphTest : public Test { void parInit(GlobalTestConfig *gtc, LocalTestConfig *ltc) { g->init_thread(gtc, ltc); - usleep(1 * 1000 * 1000); } }; #endif