working: remove the node label assignment map
This commit is contained in:
parent
ce54410a21
commit
db37ce6a18
3 changed files with 89 additions and 62 deletions
|
@ -1,8 +1,8 @@
|
||||||
.PHONY: run clean
|
.PHONY: run clean
|
||||||
|
|
||||||
CFLAGS += -O3 -g
|
CFLAGS += -g -O3
|
||||||
# CFLAGS += -DFMT_HEADER_ONLY
|
CFLAGS += -DFMT_HEADER_ONLY
|
||||||
# LDFLAGS += $(shell pkg-config --libs fmt)
|
LDFLAGS += $(shell pkg-config --libs fmt)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f lpa
|
rm -f lpa
|
||||||
|
@ -10,8 +10,8 @@ clean:
|
||||||
lpac: lpa.cpp
|
lpac: lpa.cpp
|
||||||
mpicc $(CFLAGS) $(LDFLAGS) -o $@ $<
|
mpicc $(CFLAGS) $(LDFLAGS) -o $@ $<
|
||||||
|
|
||||||
lpa: lpa.cpp
|
lpa: lpa.cpp Makefile test.gdb
|
||||||
mpic++ $(CFLAGS) $(LDFLAGS) -o $@ $<
|
mpic++ $(CFLAGS) $(LDFLAGS) -o $@ lpa.cpp
|
||||||
|
|
||||||
run:
|
run:
|
||||||
watchexec -c clear 'make lpa && mpirun -n 4 ./lpa dataset/both_1000.txt'
|
watchexec -c clear 'make lpa && mpirun -n 4 ./lpa dataset/both_1000.txt'
|
||||||
|
|
|
@ -14,14 +14,14 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
// #include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
// #include <fmt/ranges.h>
|
#include <fmt/ranges.h>
|
||||||
|
|
||||||
#define TAG_SEND_NUM_EDGES 1001
|
#define TAG_SEND_NUM_EDGES 1001
|
||||||
#define TAG_SEND_EDGES 1002
|
#define TAG_SEND_EDGES 1002
|
||||||
#define TAG_SEND_FINAL_RESULT 1003
|
#define TAG_SEND_FINAL_RESULT 1003
|
||||||
|
|
||||||
#define min(a, b) \
|
#define MIN(a, b) \
|
||||||
({ \
|
({ \
|
||||||
__typeof__(a) _a = (a); \
|
__typeof__(a) _a = (a); \
|
||||||
__typeof__(b) _b = (b); \
|
__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,
|
pair compute_node_range(int p, int total_num_nodes, int each_num_nodes,
|
||||||
int process);
|
int process);
|
||||||
|
int lookup_assignment(int *base_node_assignment, pair my_node_range,
|
||||||
|
std::map<int, std::set<int>> 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) {
|
int main(int argc, char **argv) {
|
||||||
MPI_Init(&argc, &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;
|
rank == p - 1 ? total_num_nodes - rank * each_num_nodes : each_num_nodes;
|
||||||
int my_nodes[num_my_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
|
// Read the edges
|
||||||
int num_my_edges;
|
int num_my_edges;
|
||||||
pair *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?
|
// For the current process, what's the last node we're expecting to see?
|
||||||
int current_process = 0;
|
int current_process = 0;
|
||||||
pair current_node_range =
|
pair current_node_range = node_ranges[current_process];
|
||||||
compute_node_range(p, total_num_nodes, each_num_nodes, current_process);
|
|
||||||
int edge_counter = 0;
|
int edge_counter = 0;
|
||||||
|
|
||||||
for (int i = 0; i < total_num_edges; ++i) {
|
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
|
// We're starting on the next process
|
||||||
current_process += 1;
|
current_process += 1;
|
||||||
current_node_range = compute_node_range(
|
current_node_range = node_ranges[current_process];
|
||||||
p, total_num_nodes, each_num_nodes, current_process);
|
|
||||||
edge_counter = 0;
|
edge_counter = 0;
|
||||||
pair_vector_clear(&all_edges);
|
pair_vector_clear(&all_edges);
|
||||||
}
|
}
|
||||||
|
@ -146,17 +152,6 @@ int main(int argc, char **argv) {
|
||||||
MPI_COMM_WORLD, NULL);
|
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) {
|
if (rank == 0) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (line)
|
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
|
// Each process analyzes the non-local edges that are contained in its portion
|
||||||
// of the graph.
|
// of the graph.
|
||||||
#pragma region
|
#pragma region
|
||||||
std::map<int, int> node_label_assignment;
|
int node_label_assignment_vec[num_my_nodes];
|
||||||
pair my_node_range =
|
// std::map<int, int> node_label_assignment;
|
||||||
compute_node_range(p, total_num_nodes, each_num_nodes, rank);
|
pair my_node_range = node_ranges[rank];
|
||||||
|
|
||||||
// Initial node assignment
|
// Initial node assignment
|
||||||
for (int i = my_node_range.fst; i < my_node_range.snd; ++i) {
|
for (int idx = 0; idx < num_my_nodes; ++idx) {
|
||||||
node_label_assignment[i] = i;
|
node_label_assignment_vec[idx] = my_node_range.fst + idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, std::set<int>> adj;
|
std::map<int, std::set<int>> adj;
|
||||||
|
@ -209,13 +204,13 @@ int main(int argc, char **argv) {
|
||||||
for (auto entry : non_local_edges) {
|
for (auto entry : non_local_edges) {
|
||||||
int local_node = entry.first, remote_node = entry.second;
|
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
|
// The last process gets some extra nodes
|
||||||
if (corresponding_process >= p)
|
if (remote_process >= p)
|
||||||
corresponding_process = p - 1;
|
remote_process = p - 1;
|
||||||
|
|
||||||
send_map[corresponding_process].insert(local_node);
|
send_map[remote_process].insert(local_node);
|
||||||
recv_map[corresponding_process].insert(remote_node);
|
recv_map[remote_process].insert(remote_node);
|
||||||
}
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
@ -244,9 +239,9 @@ int main(int argc, char **argv) {
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (int i = 0; i < p; ++i) {
|
for (int i = 0; i < p; ++i) {
|
||||||
int count = send_map[i].size();
|
int count = send_map[i].size();
|
||||||
// std::sort(send_map[i].begin(), send_map[i].end());
|
for (auto local_node : send_map[i]) {
|
||||||
for (auto k : send_map[i]) {
|
sendbuf.push_back(
|
||||||
sendbuf.push_back(node_label_assignment[k]);
|
node_label_assignment_vec[local_node - my_node_range.fst]);
|
||||||
}
|
}
|
||||||
send_counts.push_back(count);
|
send_counts.push_back(count);
|
||||||
send_displs.push_back(offset);
|
send_displs.push_back(offset);
|
||||||
|
@ -256,7 +251,6 @@ int main(int argc, char **argv) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
for (int i = 0; i < p; ++i) {
|
for (int i = 0; i < p; ++i) {
|
||||||
int count = recv_map[i].size();
|
int count = recv_map[i].size();
|
||||||
// std::sort(recv_map[i].begin(), recv_map[i].end());
|
|
||||||
recv_counts.push_back(count);
|
recv_counts.push_back(count);
|
||||||
recv_displs.push_back(offset);
|
recv_displs.push_back(offset);
|
||||||
offset += count;
|
offset += count;
|
||||||
|
@ -269,25 +263,21 @@ int main(int argc, char **argv) {
|
||||||
MPI_INT, recvbuf.data(), recv_counts.data(),
|
MPI_INT, recvbuf.data(), recv_counts.data(),
|
||||||
recv_displs.data(), MPI_INT, MPI_COMM_WORLD);
|
recv_displs.data(), MPI_INT, MPI_COMM_WORLD);
|
||||||
|
|
||||||
std::map<int, int> total_node_label_assignment(node_label_assignment);
|
|
||||||
for (int i = 0; i < p; ++i) {
|
|
||||||
std::vector<int> 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
|
// For each local node, determine the minimum label out of its neighbors
|
||||||
std::map<int, int> new_labels;
|
std::map<int, int> new_labels;
|
||||||
for (int i = my_node_range.fst; i < my_node_range.snd; ++i) {
|
for (int i = 0; i < num_my_nodes; ++i) {
|
||||||
int current_value = total_node_label_assignment[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;
|
int min = current_value;
|
||||||
|
|
||||||
for (auto neighbor : adj[i]) {
|
for (auto neighbor : adj[node]) {
|
||||||
if (total_node_label_assignment[neighbor] < min)
|
int neighbor_value = lookup_assignment(
|
||||||
min = total_node_label_assignment[neighbor];
|
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) {
|
if (min < current_value) {
|
||||||
|
@ -311,8 +301,11 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
// Update the original node assignment
|
// Update the original node assignment
|
||||||
for (auto entry : new_labels) {
|
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
|
#pragma endregion
|
||||||
|
|
||||||
|
@ -332,19 +325,18 @@ int main(int argc, char **argv) {
|
||||||
std::vector<int> all_assignments(total_num_nodes);
|
std::vector<int> all_assignments(total_num_nodes);
|
||||||
std::map<int, int> label_count;
|
std::map<int, int> label_count;
|
||||||
int ctr = 0;
|
int ctr = 0;
|
||||||
for (int i = 0; i < p; ++i) {
|
for (int process_idx = 0; process_idx < p; ++process_idx) {
|
||||||
pair this_node_range =
|
pair this_node_range = node_ranges[process_idx];
|
||||||
compute_node_range(p, total_num_nodes, each_num_nodes, i);
|
|
||||||
int count = this_node_range.snd - this_node_range.fst;
|
int count = this_node_range.snd - this_node_range.fst;
|
||||||
if (i == 0) {
|
if (process_idx == 0) {
|
||||||
for (int j = 0; j < count; ++j) {
|
for (int j = 0; j < count; ++j) {
|
||||||
all_assignments[this_node_range.fst + 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]]++;
|
label_count[all_assignments[this_node_range.fst + j]]++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MPI_Recv(&all_assignments[this_node_range.fst], count, MPI_INT, i,
|
MPI_Recv(&all_assignments[this_node_range.fst], count, MPI_INT,
|
||||||
TAG_SEND_FINAL_RESULT, MPI_COMM_WORLD, NULL);
|
process_idx, TAG_SEND_FINAL_RESULT, MPI_COMM_WORLD, NULL);
|
||||||
for (int j = 0; j < count; ++j) {
|
for (int j = 0; j < count; ++j) {
|
||||||
label_count[all_assignments[this_node_range.fst + 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;
|
std::cout << "Done! " << label_count.size() << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::vector<int> flat_assignments;
|
std::vector<int> flat_assignments;
|
||||||
for (int i = my_node_range.fst; i < my_node_range.snd; ++i) {
|
for (int i = 0; i < num_my_nodes; ++i) {
|
||||||
flat_assignments.push_back(node_label_assignment[i]);
|
flat_assignments.push_back(node_label_assignment_vec[i]);
|
||||||
}
|
}
|
||||||
MPI_Send(flat_assignments.data(), flat_assignments.size(), MPI_INT, 0,
|
MPI_Send(flat_assignments.data(), flat_assignments.size(), MPI_INT, 0,
|
||||||
TAG_SEND_FINAL_RESULT, MPI_COMM_WORLD);
|
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 start = process * each_num_nodes;
|
||||||
int end = process == p - 1 ? total_num_nodes : start + each_num_nodes;
|
int end = process == p - 1 ? total_num_nodes : start + each_num_nodes;
|
||||||
return {.fst = start, .snd = end};
|
return {.fst = start, .snd = end};
|
||||||
|
}
|
||||||
|
|
||||||
|
int lookup_assignment(int *base_node_assignment, pair my_node_range,
|
||||||
|
std::map<int, std::set<int>> 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<int> 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];
|
||||||
}
|
}
|
5
assignments/03/test.gdb
Normal file
5
assignments/03/test.gdb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
set pagination off
|
||||||
|
run dataset/both_1000.txt
|
||||||
|
bt
|
||||||
|
frame 3
|
||||||
|
print k
|
Loading…
Reference in a new issue