From db37ce6a1888bfdbaa439a07276ed87ae46217bf Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Sat, 25 Nov 2023 07:01:01 +0000 Subject: [PATCH] working: remove the node label assignment map --- assignments/03/Makefile | 10 +-- assignments/03/lpa.cpp | 136 +++++++++++++++++++++++----------------- assignments/03/test.gdb | 5 ++ 3 files changed, 89 insertions(+), 62 deletions(-) create mode 100644 assignments/03/test.gdb diff --git a/assignments/03/Makefile b/assignments/03/Makefile index 3f36f94..bd871c1 100644 --- a/assignments/03/Makefile +++ b/assignments/03/Makefile @@ -1,8 +1,8 @@ .PHONY: run clean -CFLAGS += -O3 -g -# CFLAGS += -DFMT_HEADER_ONLY -# LDFLAGS += $(shell pkg-config --libs fmt) +CFLAGS += -g -O3 +CFLAGS += -DFMT_HEADER_ONLY +LDFLAGS += $(shell pkg-config --libs fmt) clean: rm -f lpa @@ -10,8 +10,8 @@ clean: lpac: lpa.cpp mpicc $(CFLAGS) $(LDFLAGS) -o $@ $< -lpa: lpa.cpp - mpic++ $(CFLAGS) $(LDFLAGS) -o $@ $< +lpa: lpa.cpp Makefile test.gdb + mpic++ $(CFLAGS) $(LDFLAGS) -o $@ lpa.cpp run: watchexec -c clear 'make lpa && mpirun -n 4 ./lpa dataset/both_1000.txt' diff --git a/assignments/03/lpa.cpp b/assignments/03/lpa.cpp index aff5d69..695a6ab 100644 --- a/assignments/03/lpa.cpp +++ b/assignments/03/lpa.cpp @@ -14,14 +14,14 @@ #include #include -// #include -// #include +#include +#include #define TAG_SEND_NUM_EDGES 1001 #define TAG_SEND_EDGES 1002 #define TAG_SEND_FINAL_RESULT 1003 -#define min(a, b) \ +#define MIN(a, b) \ ({ \ __typeof__(a) _a = (a); \ __typeof__(b) _b = (b); \ @@ -45,6 +45,10 @@ void pair_vector_push(struct pair_vector *v, int fst, int snd); pair compute_node_range(int p, int total_num_nodes, int each_num_nodes, int process); +int lookup_assignment(int *base_node_assignment, pair my_node_range, + std::map> recv_map, int *recvbuf, + int *recv_counts, int *recv_displs, int each_num_nodes, + int rank, int node_number); int main(int argc, char **argv) { MPI_Init(&argc, &argv); @@ -83,6 +87,10 @@ int main(int argc, char **argv) { rank == p - 1 ? total_num_nodes - rank * each_num_nodes : each_num_nodes; int my_nodes[num_my_nodes]; + pair node_ranges[p]; + for (int i = 0; i < p; ++i) + node_ranges[i] = compute_node_range(p, total_num_nodes, each_num_nodes, i); + // Read the edges int num_my_edges; pair *my_edges; @@ -95,8 +103,7 @@ int main(int argc, char **argv) { // For the current process, what's the last node we're expecting to see? int current_process = 0; - pair current_node_range = - compute_node_range(p, total_num_nodes, each_num_nodes, current_process); + pair current_node_range = node_ranges[current_process]; int edge_counter = 0; for (int i = 0; i < total_num_edges; ++i) { @@ -120,8 +127,7 @@ int main(int argc, char **argv) { // We're starting on the next process current_process += 1; - current_node_range = compute_node_range( - p, total_num_nodes, each_num_nodes, current_process); + current_node_range = node_ranges[current_process]; edge_counter = 0; pair_vector_clear(&all_edges); } @@ -146,17 +152,6 @@ int main(int argc, char **argv) { MPI_COMM_WORLD, NULL); } - char *buf = (char *)calloc(sizeof(char), 1000); - int offset = 0; // Keep track of the current position in the buffer - for (int i = 0; i < min(num_my_edges, 5); i++) { - offset += - sprintf(buf + offset, "(%d, %d)", my_edges[i].fst, my_edges[i].snd); - if (i < len - 1) { - // Add a separator (e.g., comma or space) if it's not the last - offset += sprintf(buf + offset, " "); - } - } - if (rank == 0) { fclose(fp); if (line) @@ -171,13 +166,13 @@ int main(int argc, char **argv) { // Each process analyzes the non-local edges that are contained in its portion // of the graph. #pragma region - std::map node_label_assignment; - pair my_node_range = - compute_node_range(p, total_num_nodes, each_num_nodes, rank); + int node_label_assignment_vec[num_my_nodes]; + // std::map node_label_assignment; + pair my_node_range = node_ranges[rank]; // Initial node assignment - for (int i = my_node_range.fst; i < my_node_range.snd; ++i) { - node_label_assignment[i] = i; + for (int idx = 0; idx < num_my_nodes; ++idx) { + node_label_assignment_vec[idx] = my_node_range.fst + idx; } std::map> adj; @@ -209,13 +204,13 @@ int main(int argc, char **argv) { for (auto entry : non_local_edges) { int local_node = entry.first, remote_node = entry.second; - int corresponding_process = remote_node / each_num_nodes; + int remote_process = remote_node / each_num_nodes; // The last process gets some extra nodes - if (corresponding_process >= p) - corresponding_process = p - 1; + if (remote_process >= p) + remote_process = p - 1; - send_map[corresponding_process].insert(local_node); - recv_map[corresponding_process].insert(remote_node); + send_map[remote_process].insert(local_node); + recv_map[remote_process].insert(remote_node); } #pragma endregion @@ -244,9 +239,9 @@ int main(int argc, char **argv) { int offset = 0; for (int i = 0; i < p; ++i) { int count = send_map[i].size(); - // std::sort(send_map[i].begin(), send_map[i].end()); - for (auto k : send_map[i]) { - sendbuf.push_back(node_label_assignment[k]); + for (auto local_node : send_map[i]) { + sendbuf.push_back( + node_label_assignment_vec[local_node - my_node_range.fst]); } send_counts.push_back(count); send_displs.push_back(offset); @@ -256,7 +251,6 @@ int main(int argc, char **argv) { offset = 0; for (int i = 0; i < p; ++i) { int count = recv_map[i].size(); - // std::sort(recv_map[i].begin(), recv_map[i].end()); recv_counts.push_back(count); recv_displs.push_back(offset); offset += count; @@ -269,25 +263,21 @@ int main(int argc, char **argv) { MPI_INT, recvbuf.data(), recv_counts.data(), recv_displs.data(), MPI_INT, MPI_COMM_WORLD); - std::map total_node_label_assignment(node_label_assignment); - for (int i = 0; i < p; ++i) { - std::vector ouais(recv_map[i].begin(), recv_map[i].end()); - for (int j = 0; j < recv_counts[i]; ++j) { - int remote_node = ouais[j]; - int remote_value = recvbuf[recv_displs[i] + j]; - total_node_label_assignment[remote_node] = remote_value; - } - } - // For each local node, determine the minimum label out of its neighbors std::map new_labels; - for (int i = my_node_range.fst; i < my_node_range.snd; ++i) { - int current_value = total_node_label_assignment[i]; + for (int i = 0; i < num_my_nodes; ++i) { + int node = my_node_range.fst + i; + + // int current_value = total_node_label_assignment[i]; + int current_value = node_label_assignment_vec[i]; int min = current_value; - for (auto neighbor : adj[i]) { - if (total_node_label_assignment[neighbor] < min) - min = total_node_label_assignment[neighbor]; + for (auto neighbor : adj[node]) { + int neighbor_value = lookup_assignment( + node_label_assignment_vec, my_node_range, recv_map, recvbuf.data(), + recv_counts.data(), recv_displs.data(), each_num_nodes, rank, + neighbor); + min = MIN(min, neighbor_value); } if (min < current_value) { @@ -311,8 +301,11 @@ int main(int argc, char **argv) { // Update the original node assignment for (auto entry : new_labels) { - node_label_assignment[entry.first] = entry.second; + node_label_assignment_vec[entry.first] = entry.second; } + + if (rank == 0) + printf("total changes: %d\n", total_changes); } #pragma endregion @@ -332,19 +325,18 @@ int main(int argc, char **argv) { std::vector all_assignments(total_num_nodes); std::map label_count; int ctr = 0; - for (int i = 0; i < p; ++i) { - pair this_node_range = - compute_node_range(p, total_num_nodes, each_num_nodes, i); + for (int process_idx = 0; process_idx < p; ++process_idx) { + pair this_node_range = node_ranges[process_idx]; int count = this_node_range.snd - this_node_range.fst; - if (i == 0) { + if (process_idx == 0) { for (int j = 0; j < count; ++j) { all_assignments[this_node_range.fst + j] = - node_label_assignment[this_node_range.fst + j]; + node_label_assignment_vec[j]; label_count[all_assignments[this_node_range.fst + j]]++; } } else { - MPI_Recv(&all_assignments[this_node_range.fst], count, MPI_INT, i, - TAG_SEND_FINAL_RESULT, MPI_COMM_WORLD, NULL); + MPI_Recv(&all_assignments[this_node_range.fst], count, MPI_INT, + process_idx, TAG_SEND_FINAL_RESULT, MPI_COMM_WORLD, NULL); for (int j = 0; j < count; ++j) { label_count[all_assignments[this_node_range.fst + j]]++; } @@ -354,8 +346,8 @@ int main(int argc, char **argv) { std::cout << "Done! " << label_count.size() << std::endl; } else { std::vector flat_assignments; - for (int i = my_node_range.fst; i < my_node_range.snd; ++i) { - flat_assignments.push_back(node_label_assignment[i]); + for (int i = 0; i < num_my_nodes; ++i) { + flat_assignments.push_back(node_label_assignment_vec[i]); } MPI_Send(flat_assignments.data(), flat_assignments.size(), MPI_INT, 0, TAG_SEND_FINAL_RESULT, MPI_COMM_WORLD); @@ -409,4 +401,34 @@ pair compute_node_range(int p, int total_num_nodes, int each_num_nodes, int start = process * each_num_nodes; int end = process == p - 1 ? total_num_nodes : start + each_num_nodes; return {.fst = start, .snd = end}; +} + +int lookup_assignment(int *base_node_assignment, pair my_node_range, + std::map> recv_map, int *recvbuf, + int *recv_counts, int *recv_displs, int each_num_nodes, + int rank, int node_number) { + int process_from = node_number / each_num_nodes; + + // Just return from local if local + if (process_from == rank) + return base_node_assignment[node_number - my_node_range.fst]; + + int count = recv_counts[process_from]; + int displs = recv_displs[process_from]; + + // Determine what index this node is + int index = -1, ctr = 0; + std::vector inner(recv_map[process_from].begin(), + recv_map[process_from].end()); + for (int i = 0; i < count; ++i) { + int remote_node = inner[i]; + if (node_number == remote_node) { + index = ctr; + break; + } + ctr++; + } + + // Pull the corresponding value from the map + return recvbuf[recv_displs[process_from] + index]; } \ No newline at end of file diff --git a/assignments/03/test.gdb b/assignments/03/test.gdb new file mode 100644 index 0000000..171a8f9 --- /dev/null +++ b/assignments/03/test.gdb @@ -0,0 +1,5 @@ +set pagination off +run dataset/both_1000.txt +bt +frame 3 +print k \ No newline at end of file