diff --git a/CMakeLists.txt b/CMakeLists.txt index f0ced55..e5d848f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ FetchContent_Declare( GraphZeppelinVerifyCC GIT_REPOSITORY https://github.com/GraphStreamingProject/GraphZeppelin - GIT_TAG refactor + GIT_TAG main ) FetchContent_MakeAvailable(GraphZeppelinVerifyCC) @@ -75,7 +75,9 @@ add_executable(mpi_dynamicCC_tests test/mpi_graph_tiers_test.cpp src/skiplist.cpp + src/sketchless_skiplist.cpp src/euler_tour_tree.cpp + src/sketchless_euler_tour_tree.cpp src/link_cut_tree.cpp src/input_node.cpp src/tier_node.cpp diff --git a/include/mpi_nodes.h b/include/mpi_nodes.h index 6253e04..3211329 100644 --- a/include/mpi_nodes.h +++ b/include/mpi_nodes.h @@ -5,6 +5,7 @@ #include "types.h" #include "euler_tour_tree.h" +#include "sketchless_euler_tour_tree.h" #include "link_cut_tree.h" #include "mpi_functions.h" @@ -58,6 +59,7 @@ class InputNode { node_id_t num_nodes; uint32_t num_tiers; LinkCutTree link_cut_tree; + SketchlessEulerTourTree query_ett; UpdateMessage* update_buffer; int buffer_size; int buffer_capacity; @@ -68,7 +70,7 @@ class InputNode { int isolation_count; bool using_sliding_window = false; public: - InputNode(node_id_t num_nodes, uint32_t num_tiers, int batch_size); + InputNode(node_id_t num_nodes, uint32_t num_tiers, int batch_size, int seed); ~InputNode(); void update(GraphUpdate update); void process_all_updates(); diff --git a/include/sketchless_euler_tour_tree.h b/include/sketchless_euler_tour_tree.h new file mode 100644 index 0000000..909fdcd --- /dev/null +++ b/include/sketchless_euler_tour_tree.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include + +#include +#include "types.h" + +class SketchlessEulerTourNode { + + std::unordered_map edges; + + SketchlessSkipListNode* allowed_caller = nullptr; + long seed = 0; + + SketchlessSkipListNode* make_edge(SketchlessEulerTourNode* other); + void delete_edge(SketchlessEulerTourNode* other); + +public: + const node_id_t vertex = 0; + const uint32_t tier = 0; + + SketchlessEulerTourNode(long seed, node_id_t vertex, uint32_t tier); + SketchlessEulerTourNode(long seed); + ~SketchlessEulerTourNode(); + bool link(SketchlessEulerTourNode& other); + bool cut(SketchlessEulerTourNode& other); + + bool isvalid() const; + + SketchlessSkipListNode* get_root(); + + bool has_edge_to(SketchlessEulerTourNode* other); + + std::set get_component(); + + long get_seed() {return seed;}; + + friend std::ostream& operator<<(std::ostream& os, const SketchlessEulerTourNode& ett); +}; + +class SketchlessEulerTourTree { + long seed = 0; +public: + std::vector ett_nodes; + + SketchlessEulerTourTree(node_id_t num_nodes, uint32_t tier_num, int seed); + + void link(node_id_t u, node_id_t v); + void cut(node_id_t u, node_id_t v); + bool has_edge(node_id_t u, node_id_t v); + SketchlessSkipListNode* get_root(node_id_t u); + bool is_connected(node_id_t u, node_id_t v); +}; diff --git a/include/sketchless_skiplist.h b/include/sketchless_skiplist.h new file mode 100644 index 0000000..cb1fb19 --- /dev/null +++ b/include/sketchless_skiplist.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +class SketchlessEulerTourNode; + +extern long sketchless_skiplist_seed; +extern double sketchless_height_factor; + +class SketchlessSkipListNode { + + SketchlessSkipListNode* left = nullptr; + SketchlessSkipListNode* right = nullptr; + SketchlessSkipListNode* up = nullptr; + SketchlessSkipListNode* down = nullptr; + // Store the first node to the left on the next level up + SketchlessSkipListNode* parent = nullptr; + +public: + + SketchlessEulerTourNode* node; + + SketchlessSkipListNode(SketchlessEulerTourNode* node); + static SketchlessSkipListNode* init_element(SketchlessEulerTourNode* node); + void uninit_element(bool delete_bdry); + void uninit_list(); + + // Returns the closest node on the next level up at or left of the current + SketchlessSkipListNode* get_parent(); + // Returns the top left root node of the skiplist + SketchlessSkipListNode* get_root(); + // Returns the bottom left boundary node of the skiplist + SketchlessSkipListNode* get_first(); + // Returns the bottom right node of the skiplist + SketchlessSkipListNode* get_last(); + + std::set get_component(); + + // Returns the root of a new skiplist formed by joining the lists containing left and right + static SketchlessSkipListNode* join(SketchlessSkipListNode* left, SketchlessSkipListNode* right); + template + static SketchlessSkipListNode* join(SketchlessSkipListNode* head, T*... tail); + // Returns the root of the left list after splitting to the left of the given node + static SketchlessSkipListNode* split_left(SketchlessSkipListNode* node); + // Returns the root of the right list after splitting to the right of the given node + static SketchlessSkipListNode* split_right(SketchlessSkipListNode* node); + + bool isvalid(); + SketchlessSkipListNode* next(); + int print_list(); +}; + +template +SketchlessSkipListNode* SketchlessSkipListNode::join(SketchlessSkipListNode* head, T*... tail) { + return join(head, join(tail...)); +} diff --git a/src/euler_tour_tree.cpp b/src/euler_tour_tree.cpp index 784e6fe..e2a0920 100644 --- a/src/euler_tour_tree.cpp +++ b/src/euler_tour_tree.cpp @@ -12,6 +12,10 @@ EulerTourTree::EulerTourTree(node_id_t num_nodes, uint32_t tier_num, int seed) { this->temp_sketch = new Sketch(sketch_len, seed); } +EulerTourTree::~EulerTourTree() { + delete this->temp_sketch; +} + void EulerTourTree::link(node_id_t u, node_id_t v) { ett_nodes[u].link(ett_nodes[v], temp_sketch); } @@ -52,8 +56,8 @@ EulerTourNode::EulerTourNode(long seed) : seed(seed) { EulerTourNode::~EulerTourNode() { // Final boundary nodes are a memory leak // Need to somehow delete all the skiplist nodes at the end - // for (auto edge : edges) - // edge.second->uninit_element(false); + for (auto edge : edges) + edge.second->uninit_element(false); } SkipListNode* EulerTourNode::make_edge(EulerTourNode* other, Sketch* temp_sketch) { diff --git a/src/input_node.cpp b/src/input_node.cpp index f91665f..289eef4 100644 --- a/src/input_node.cpp +++ b/src/input_node.cpp @@ -2,8 +2,10 @@ long normal_refreshes = 0; +long dt_operation_time = 0; -InputNode::InputNode(node_id_t num_nodes, uint32_t num_tiers, int batch_size) : num_nodes(num_nodes), num_tiers(num_tiers), link_cut_tree(num_nodes){ +InputNode::InputNode(node_id_t num_nodes, uint32_t num_tiers, int batch_size, int seed) : + num_nodes(num_nodes), num_tiers(num_tiers), link_cut_tree(num_nodes), query_ett(num_nodes, 0, seed) { update_buffer = (UpdateMessage*) malloc(sizeof(UpdateMessage)*(batch_size+1)); buffer_capacity = batch_size+1; UpdateMessage msg; @@ -32,9 +34,9 @@ void InputNode::update(GraphUpdate update) { void InputNode::process_updates() { if (buffer_size == 1) return; - // If less than 1/5 of the last updates are isolated use sliding window + // If less than 1/10 of the last updates are isolated use sliding window bool prev_strat = using_sliding_window; - using_sliding_window = (isolation_count> InputNode::cc_query() { process_all_updates(); - return link_cut_tree.get_cc(); + std::vector> cc; + std::set visited; + for (uint32_t i = 0; i < query_ett.ett_nodes.size(); i++) { + if (visited.find(&query_ett.ett_nodes[i]) == visited.end()) { + std::set pointer_component = query_ett.ett_nodes[i].get_component(); + std::set component; + for (auto pointer : pointer_component) { + component.insert(pointer->vertex); + visited.insert(pointer); + } + cc.push_back(component); + } + } + return cc; } void InputNode::end() { @@ -162,6 +189,7 @@ void InputNode::end() { // Tell all nodes the stream is over update_buffer[0].end = true; bcast(update_buffer, sizeof(UpdateMessage)*buffer_capacity, 0); - std::cout << "============= INPUT NODE =============" << std::endl; + std::cout << "======================= INPUT NODE ======================" << std::endl; + std::cout << "Dynamic tree operations time (ms): " << dt_operation_time/1000 << std::endl; std::cout << "Normal refreshes: " << normal_refreshes << std::endl; } diff --git a/src/sketchless_euler_tour_tree.cpp b/src/sketchless_euler_tour_tree.cpp new file mode 100644 index 0000000..23cb20b --- /dev/null +++ b/src/sketchless_euler_tour_tree.cpp @@ -0,0 +1,170 @@ +#include + +#include + + +SketchlessEulerTourTree::SketchlessEulerTourTree(node_id_t num_nodes, uint32_t tier_num, int seed) { + // Initialize all the ETT node + ett_nodes.reserve(num_nodes); + for (node_id_t i = 0; i < num_nodes; ++i) { + ett_nodes.emplace_back(seed, i, tier_num); + } +} + +void SketchlessEulerTourTree::link(node_id_t u, node_id_t v) { + ett_nodes[u].link(ett_nodes[v]); +} + +void SketchlessEulerTourTree::cut(node_id_t u, node_id_t v) { + ett_nodes[u].cut(ett_nodes[v]); +} + +bool SketchlessEulerTourTree::has_edge(node_id_t u, node_id_t v) { + return ett_nodes[u].has_edge_to(&ett_nodes[v]); +} + +SketchlessSkipListNode* SketchlessEulerTourTree::get_root(node_id_t u) { + return ett_nodes[u].get_root(); +} + +bool SketchlessEulerTourTree::is_connected(node_id_t u, node_id_t v) { + return get_root(u) == get_root(v); +} + +SketchlessEulerTourNode::SketchlessEulerTourNode(long seed, node_id_t vertex, uint32_t tier) : seed(seed), vertex(vertex), tier(tier) { + // Initialize sentinel + this->make_edge(nullptr); +} + +SketchlessEulerTourNode::SketchlessEulerTourNode(long seed) : seed(seed) { + // Initialize sentinel + this->make_edge(nullptr); +} + +SketchlessEulerTourNode::~SketchlessEulerTourNode(){ + +} + +SketchlessSkipListNode* SketchlessEulerTourNode::make_edge(SketchlessEulerTourNode* other) { + assert(!other || this->tier == other->tier); + //Constructing a new SkipListNode with pointer to this ETT object + SketchlessSkipListNode* node = SketchlessSkipListNode::init_element(this); + if (allowed_caller == nullptr) { + allowed_caller = node; + } + //Add the new SkipListNode to the edge list + return this->edges.emplace(std::make_pair(other, node)).first->second; + //Returns the new node pointer or the one that already existed if it did +} + +void SketchlessEulerTourNode::delete_edge(SketchlessEulerTourNode* other) { + assert(!other || this->tier == other->tier); + SketchlessSkipListNode* node_to_delete = this->edges[other]; + this->edges.erase(other); + if (node_to_delete == allowed_caller) { + if (this->edges.empty()) { + allowed_caller = nullptr; + } else { + allowed_caller = this->edges.begin()->second; + } + } + node_to_delete->uninit_element(true); +} + +SketchlessSkipListNode* SketchlessEulerTourNode::get_root() { + return this->allowed_caller->get_root(); +} + +bool SketchlessEulerTourNode::has_edge_to(SketchlessEulerTourNode* other) { + return !(this->edges.find(other) == this->edges.end()); +} + +std::set SketchlessEulerTourNode::get_component() { + return this->allowed_caller->get_component(); +} + +bool SketchlessEulerTourNode::link(SketchlessEulerTourNode& other) { + assert(this->tier == other.tier); + SketchlessSkipListNode* this_sentinel = this->edges.begin()->second->get_last(); + SketchlessSkipListNode* other_sentinel = other.edges.begin()->second->get_last(); + + // There should always be a sentinel + assert(this_sentinel == this_sentinel->node->edges.at(nullptr)); + assert(other_sentinel == other_sentinel->node->edges.at(nullptr)); + + // If the nodes are already part of the same tree, don't link + if (this_sentinel == other_sentinel) { + return false; + } + + // linking BD, ABA with CDEDC + // ABA split on B gives A BA + // CDEDC removing sentinel gives CDED + // ^ might be null + // CDED split on D gives C DED + // A, construct B, DED, C, construct D, BA + // ^ ^ + // '--------------------'--- might be null + + SketchlessSkipListNode* aux_this_right = this->edges.begin()->second; + SketchlessSkipListNode* aux_this_left = SketchlessSkipListNode::split_left(aux_this_right); + + // Unlink and destory other_sentinel + SketchlessSkipListNode* aux_other = SketchlessSkipListNode::split_left(other_sentinel); + other_sentinel->node->delete_edge(nullptr); + + SketchlessSkipListNode* aux_other_left, *aux_other_right; + if (aux_other == nullptr) { + aux_other_right = aux_other_left = nullptr; + } else { + aux_other_right = other.edges.begin()->second; + aux_other_left = SketchlessSkipListNode::split_left(aux_other_right); + } + + // reroot other tree + // A, construct B, DED, C, construct D, BA + // R LR L R LR L + // N N + + SketchlessSkipListNode* aux_edge_left = this->make_edge(&other); + SketchlessSkipListNode* aux_edge_right = other.make_edge(this); + + SketchlessSkipListNode::join(aux_this_left, aux_edge_left, aux_other_right, + aux_other_left, aux_edge_right, aux_this_right); + + return true; +} + +bool SketchlessEulerTourNode::cut(SketchlessEulerTourNode& other) { + assert(this->tier == other.tier); + if (this->edges.find(&other) == this->edges.end()) { + assert(other.edges.find(this) == other.edges.end()); + return false; + } + SketchlessSkipListNode* e1 = this->edges[&other]; + SketchlessSkipListNode* e2 = other.edges[this]; + + SketchlessSkipListNode* frag1r = SketchlessSkipListNode::split_right(e1); + bool order_is_e1e2 = e2->get_last() != e1; + SketchlessSkipListNode* frag1l = SketchlessSkipListNode::split_left(e1); + this->delete_edge(&other); + SketchlessSkipListNode* frag2r = SketchlessSkipListNode::split_right(e2); + SketchlessSkipListNode* frag2l = SketchlessSkipListNode::split_left(e2); + other.delete_edge(this); + + if (order_is_e1e2) { + // e1 is to the left of e2 + // e2 should be made into a sentinel + SketchlessSkipListNode* sentinel = other.make_edge(nullptr); + SketchlessSkipListNode::join(frag2l, sentinel); + SketchlessSkipListNode::join(frag1l, frag2r); + } else { + // e2 is to the left of e1 + // e1 should be made into a sentinel + SketchlessSkipListNode* sentinel = this->make_edge(nullptr); + SketchlessSkipListNode::join(frag2r, sentinel); + SketchlessSkipListNode::join(frag2l, frag1r); + } + + return true; +} diff --git a/src/sketchless_skiplist.cpp b/src/sketchless_skiplist.cpp new file mode 100644 index 0000000..979ae42 --- /dev/null +++ b/src/sketchless_skiplist.cpp @@ -0,0 +1,251 @@ +#include +#include +#include "sketchless_skiplist.h" +#include "sketchless_euler_tour_tree.h" +#include + + +double sketchless_height_factor; +long sketchless_skiplist_seed = time(NULL); + +SketchlessSkipListNode::SketchlessSkipListNode(SketchlessEulerTourNode* node) : node(node) {} + +void SketchlessSkipListNode::uninit_element(bool delete_bdry) { + SketchlessSkipListNode* list_curr = this; + SketchlessSkipListNode* list_prev; + SketchlessSkipListNode* bdry_curr = this->left; + SketchlessSkipListNode* bdry_prev; + while (list_curr) { + list_prev = list_curr; + list_curr = list_prev->up; + delete list_prev; + } + if (delete_bdry) { + while (bdry_curr) { + bdry_prev = bdry_curr; + bdry_curr = bdry_prev->up; + delete bdry_prev; + } + } +} + +SketchlessSkipListNode* SketchlessSkipListNode::init_element(SketchlessEulerTourNode* node) { + long seed = node->get_seed(); + // NOTE: WE SHOULD MAKE IT SO DIFFERENT SKIPLIST NODES FOR THE SAME ELEMENT CAN BE DIFFERENT HEIGHTS + uint64_t element_height = sketchless_height_factor*__builtin_ctzll(XXH3_64bits_withSeed(&node->vertex, sizeof(node_id_t), sketchless_skiplist_seed))+1; + SketchlessSkipListNode* list_node, *bdry_node, *list_prev, *bdry_prev; + list_node = bdry_node = list_prev = bdry_prev = nullptr; + // Add skiplist and boundary nodes up to the random height + for (uint64_t i = 0; i < element_height; i++) { + list_node = new SketchlessSkipListNode(node); + bdry_node = new SketchlessSkipListNode(nullptr); + list_node->left = bdry_node; + bdry_node->right = list_node; + if (list_prev) { + list_node->down = list_prev; + list_prev->up = list_node; + list_prev->parent = list_node; + } + if (bdry_prev) { + bdry_node->down = bdry_prev; + bdry_prev->up = bdry_node; + bdry_prev->parent = bdry_node; + } + list_prev = list_node; + bdry_prev = bdry_node; + } + // Add one more boundary node at height+1 + SketchlessSkipListNode* root = new SketchlessSkipListNode(nullptr); + root->down = bdry_prev; + bdry_prev->up = root; + bdry_prev->parent = root; + list_prev->parent = root; + return root->get_last(); +} + +SketchlessSkipListNode* SketchlessSkipListNode::get_parent() { + // SkipListNode* curr = this; + // while (curr && !curr->up) { + // curr = curr->left; + // } + // return curr ? curr->up : nullptr; + return parent; +} + +SketchlessSkipListNode* SketchlessSkipListNode::get_root() { + SketchlessSkipListNode* prev = nullptr; + SketchlessSkipListNode* curr = this; + while (curr) { + prev = curr; + curr = prev->get_parent(); + } + return prev; +} + +SketchlessSkipListNode* SketchlessSkipListNode::get_first() { + // Go to the root first and then down to the first element, because if we start at some lower level + // we may have to travel right a lot more on that level, takes log time instead of linear time + SketchlessSkipListNode* prev = nullptr; + SketchlessSkipListNode* curr = this->get_root(); + while (curr) { + prev = curr; + curr = prev->down; + } + return prev; +} + +SketchlessSkipListNode* SketchlessSkipListNode::get_last() { + // Go to the root first and then down to the last element, because if we start at some lower level + // we may have to travel left a lot more on that level, takes log time instead of linear time + SketchlessSkipListNode* prev = nullptr; + SketchlessSkipListNode* curr = this->get_root(); + while (curr) { + prev = curr; + curr = prev->right ? prev->right : prev->down; + } + return prev; +} + +std::set SketchlessSkipListNode::get_component() { + std::set nodes; + SketchlessSkipListNode* curr = this->get_first()->right; //Skip over the boundary node + while (curr) { + nodes.insert(curr->node); + curr = curr->right; + } + return nodes; +} + +void SketchlessSkipListNode::uninit_list() { + SketchlessSkipListNode* curr = this->get_first(); + SketchlessSkipListNode* prev; + while (curr) { + prev = curr; + curr = prev->right; + prev->uninit_element(false); + } + prev->uninit_element(false); +} + +SketchlessSkipListNode* SketchlessSkipListNode::join(SketchlessSkipListNode* left, SketchlessSkipListNode* right) { + assert(left || right); + if (!left) return right->get_root(); + if (!right) return left->get_root(); + + SketchlessSkipListNode* l_curr = left->get_last(); + SketchlessSkipListNode* r_curr = right->get_first(); // this is the bottom boundary node + SketchlessSkipListNode* r_first = r_curr->right; + SketchlessSkipListNode* l_prev = nullptr; + SketchlessSkipListNode* r_prev = nullptr; + + // Go up levels. link pointers, add aggregates + while (l_curr && r_curr) { + // Fix right pointer + l_curr->right = r_curr->right; // skip over boundary node + if (r_curr->right) r_curr->right->left = l_curr; // skip over boundary node, but to the left + + if (r_prev) delete r_prev; // Delete old boundary nodes + l_prev = l_curr; + r_prev = r_curr; + l_curr = l_prev->get_parent(); + r_curr = r_prev->up; + } + + // If left list was taller add the root agg in right to the rest in left + while (l_curr) { + l_prev = l_curr; + l_curr = l_prev->get_parent(); + } + + // If right list was taller add new boundary nodes to left list + if (r_curr) { + while (r_curr) { + l_curr = new SketchlessSkipListNode(nullptr); + l_curr->down = l_prev; + l_prev->up = l_curr; + l_prev->parent = l_curr; + l_curr->right = r_curr->right; + if (r_curr->right) r_curr->right->left = l_curr; + + if (r_prev) delete r_prev; // Delete old boundary nodes + l_prev = l_curr; + r_prev = r_curr; + r_curr = r_prev->up; + } + } + delete r_prev; + // Update parent pointers in right list + while (r_first) { + while (r_first && !r_first->up) { + r_first->parent = r_first->left->parent; + r_first = r_first->right; + } + if (r_first) + r_first = r_first->up; + } + // Returns the root of the joined list + return l_prev; +} + +SketchlessSkipListNode* SketchlessSkipListNode::split_left(SketchlessSkipListNode* node) { + assert(node && node->left && !node->down); + // If just splitting off the boundary nodes do nothing instead + if (!node->left->left) { + return nullptr; + } + long seed = node->node->get_seed(); + // Construct new boundary nodes with correct aggregates for the right component + // New aggs will be sum of all aggs on each level in the right path + // Subtract those new aggregates from the "corners" of the left path + // And unlink the nodes and link with the new boundary nodes + SketchlessSkipListNode* r_curr = node; + SketchlessSkipListNode* l_curr = node->left; + SketchlessSkipListNode* bdry = new SketchlessSkipListNode(nullptr); + SketchlessSkipListNode* new_bdry; + while (r_curr) { + r_curr->left = bdry; + bdry->right = r_curr; + l_curr->right = nullptr; + // Get next l_curr, r_curr, and bdry + l_curr = l_curr->get_parent(); + new_bdry = new SketchlessSkipListNode(nullptr); + while (r_curr && !r_curr->up) { + r_curr->parent = new_bdry; + r_curr = r_curr->right; + } + r_curr = r_curr ? r_curr->up : nullptr; + new_bdry->down = bdry; + bdry->up = new_bdry; + bdry->parent = new_bdry; + bdry = new_bdry; + } + // Subtract the final right agg from the rest of the aggs on left path + SketchlessSkipListNode* l_prev = nullptr; + while (l_curr) { + l_prev = l_curr; + l_curr = l_curr->get_parent(); + } + // Trim extra boundary nodes on the left list + l_curr = l_prev->down; + while (!l_curr->right) { + delete l_prev; + l_prev = l_curr; + l_curr = l_prev->down; + } + l_prev->up = nullptr; + l_prev->parent = nullptr; + // Returns the root of left list + return l_prev; +} + +SketchlessSkipListNode* SketchlessSkipListNode::split_right(SketchlessSkipListNode* node) { + assert(node); + SketchlessSkipListNode* right = node->right; + if (!right) return nullptr; + SketchlessSkipListNode::split_left(right); + return right->get_root(); +} + +SketchlessSkipListNode* SketchlessSkipListNode::next() { + return this->right; +} diff --git a/test/mpi_graph_tiers_test.cpp b/test/mpi_graph_tiers_test.cpp index 3149fce..dadb9c2 100644 --- a/test/mpi_graph_tiers_test.cpp +++ b/test/mpi_graph_tiers_test.cpp @@ -33,7 +33,10 @@ TEST(GraphTiersSuite, mpi_mini_correctness_test) { sketch_err = DEFAULT_SKETCH_ERR; if (world_rank == 0) { - InputNode input_node(num_nodes, num_tiers, update_batch_size); + int seed = time(NULL); + srand(seed); + std::cout << "InputNode seed: " << seed << std::endl; + InputNode input_node(num_nodes, num_tiers, update_batch_size, seed); MatGraphVerifier gv(num_nodes); // Link all of the nodes into 1 connected component for (node_id_t i = 0; i < num_nodes-1; i++) { @@ -94,7 +97,10 @@ TEST(GraphTiersSuite, mpi_mini_replacement_test) { sketch_err = DEFAULT_SKETCH_ERR; if (world_rank == 0) { - InputNode input_node(num_nodes, num_tiers, update_batch_size); + int seed = time(NULL); + srand(seed); + std::cout << "InputNode seed: " << seed << std::endl; + InputNode input_node(num_nodes, num_tiers, update_batch_size, seed); MatGraphVerifier gv(num_nodes); // Link all of the nodes into 1 connected component for (node_id_t i = 0; i < num_nodes-1; i++) { @@ -163,7 +169,10 @@ TEST(GraphTiersSuite, mpi_mini_batch_test) { sketch_err = DEFAULT_SKETCH_ERR; if (world_rank == 0) { - InputNode input_node(num_nodes, num_tiers, update_batch_size); + int seed = time(NULL); + srand(seed); + std::cout << "InputNode seed: " << seed << std::endl; + InputNode input_node(num_nodes, num_tiers, update_batch_size, seed); MatGraphVerifier gv(num_nodes); // Link all of the nodes into 1 connected component for (node_id_t i = 0; i < num_nodes-1; i++) { @@ -284,7 +293,10 @@ TEST(GraphTiersSuite, mpi_correctness_test) { FAIL() << "MPI world size too small for graph with " << num_nodes << " vertices. Correct world size is: " << num_tiers+1; if (world_rank == 0) { - InputNode input_node(num_nodes, num_tiers, update_batch_size); + int seed = time(NULL); + srand(seed); + std::cout << "InputNode seed: " << seed << std::endl; + InputNode input_node(num_nodes, num_tiers, update_batch_size, seed); MatGraphVerifier gv(num_nodes); int edgecount = stream.edges(); int count = 20000000; @@ -341,6 +353,7 @@ TEST(GraphTierSuite, mpi_speed_test) { // Parameters int update_batch_size = DEFAULT_BATCH_SIZE; height_factor = 1./log2(log2(num_nodes)); + sketchless_height_factor = height_factor; sketch_len = Sketch::calc_vector_length(num_nodes); sketch_err = DEFAULT_SKETCH_ERR; @@ -348,17 +361,20 @@ TEST(GraphTierSuite, mpi_speed_test) { FAIL() << "MPI world size too small for graph with " << num_nodes << " vertices. Correct world size is: " << num_tiers+1; if (world_rank == 0) { - long time = 0; - InputNode input_node(num_nodes, num_tiers, update_batch_size); + int seed = time(NULL); + srand(seed); + std::cout << "InputNode seed: " << seed << std::endl; + InputNode input_node(num_nodes, num_tiers, update_batch_size, seed); long edgecount = stream.edges(); // long count = 1000000; // edgecount = std::min(edgecount, count); + long time = 0; START(timer); for (long i = 0; i < edgecount; i++) { // Read an update from the stream and have the input node process it GraphUpdate update = stream.get_edge(); input_node.update(update); - unlikely_if(i%100000 == 0 || i == edgecount-1) { + unlikely_if(i%1000000 == 0 || i == edgecount-1) { std::cout << "FINISHED UPDATE " << i << " OUT OF " << edgecount << " IN " << stream_file << std::endl; } } @@ -394,12 +410,13 @@ TEST(GraphTiersSuite, mpi_queries_speed_test) { uint32_t num_tiers = log2(num_nodes)/(log2(3)-1); int nodecount = stream.nodes(); int edgecount = stream.edges(); - int count = 20000000; + int count = /**15000000;*/ edgecount/2; edgecount = std::min(edgecount, count); // Parameters int update_batch_size = DEFAULT_BATCH_SIZE; height_factor = 1./log2(log2(num_nodes)); + sketchless_height_factor = height_factor; sketch_len = Sketch::calc_vector_length(num_nodes); sketch_err = DEFAULT_SKETCH_ERR; @@ -407,7 +424,10 @@ TEST(GraphTiersSuite, mpi_queries_speed_test) { FAIL() << "MPI world size too small for graph with " << num_nodes << " vertices. Correct world size is: " << num_tiers+1; if (world_rank == 0) { - InputNode input_node(num_nodes, num_tiers, update_batch_size); + int seed = time(NULL); + srand(seed); + std::cout << "InputNode seed: " << seed << std::endl; + InputNode input_node(num_nodes, num_tiers, update_batch_size, seed); std::cout << "Building up graph..." << std::endl; for (int i = 0; i < edgecount; i++) { @@ -415,8 +435,8 @@ TEST(GraphTiersSuite, mpi_queries_speed_test) { input_node.update(update); } - int querycount = 1000000; - int cc_querycount = querycount/100; + long querycount = 100000000; + long cc_querycount = 1000; long con_query_time = 0; long cc_query_time = 0; @@ -426,19 +446,19 @@ TEST(GraphTiersSuite, mpi_queries_speed_test) { input_node.connectivity_query(rand()%nodecount, rand()%nodecount); } STOP(con_query_time, con_query_timer); - std::cout << querycount << " Connectivity Queries, Time: " << con_query_time/1000 << std::endl; + std::cout << querycount << " Connectivity Queries, Time (ms): " << con_query_time/1000 << std::endl; START(cc_query_timer); for (int i = 0; i < cc_querycount; i++) { input_node.cc_query(); } STOP(cc_query_time, cc_query_timer); - std::cout << cc_querycount << " Connected Components Queries, Time: " << cc_query_time/1000 << std::endl; + std::cout << cc_querycount << " Connected Components Queries, Time (ms): " << cc_query_time/1000 << std::endl; input_node.end(); std::ofstream file; file.open ("mpi_kron_query_results.txt", std::ios_base::app); - file << stream_file << " connectivity queries/s: " << 1000*querycount/(con_query_time/1000) << std::endl; + file << stream_file << " connectivity queries/s: " << querycount/(con_query_time/1000)*1000 << std::endl; file << stream_file << " cc queries/s: " << 1000*cc_querycount/(cc_query_time/1000) << std::endl; file.close();