save b4 messing with shit
This commit is contained in:
parent
432f17726c
commit
9d064bef0d
3 changed files with 105 additions and 44 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -5,5 +5,6 @@
|
||||||
"[python]": {
|
"[python]": {
|
||||||
"editor.defaultFormatter": "ms-python.black-formatter"
|
"editor.defaultFormatter": "ms-python.black-formatter"
|
||||||
},
|
},
|
||||||
"python.formatting.provider": "none"
|
"python.formatting.provider": "none",
|
||||||
|
"discord.enabled": true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.PHONY: all clean
|
.PHONY: all clean run-example
|
||||||
|
|
||||||
CC := cc
|
CC := cc
|
||||||
|
|
||||||
|
@ -10,6 +10,9 @@ LDFLAGS += $(shell pkg-config --libs mpi)
|
||||||
|
|
||||||
all: qs_mpi
|
all: qs_mpi
|
||||||
|
|
||||||
|
run-example: qs_mpi
|
||||||
|
mpirun --allow-run-as-root -np 4 ./qs_mpi 32 output.txt
|
||||||
|
|
||||||
qs_mpi: qs_mpi.o
|
qs_mpi: qs_mpi.o
|
||||||
$(CC) $^ $(CFLAGS) $(LDFLAGS) -o $@
|
$(CC) $^ $(CFLAGS) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
void local_quicksort(int *arr, int lo, int hi);
|
void local_quicksort(int *arr, int lo, int hi);
|
||||||
char *string_of_list(int *arr, int len);
|
char *string_of_list(int *arr, int len);
|
||||||
void recursive_quicksort(int *integers, int n, MPI_Comm comm);
|
void recursive_quicksort(int *integers, int n, int root, MPI_Comm comm);
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int rank, p;
|
int rank, p;
|
||||||
|
@ -33,7 +33,7 @@ int main(int argc, char **argv) {
|
||||||
int n_over_p = n / p;
|
int n_over_p = n / p;
|
||||||
int integers[n_over_p];
|
int integers[n_over_p];
|
||||||
|
|
||||||
// Important implementation detail: srand(0) is specially handled by glibc to
|
// Minor implementation detail: srand(0) is specially handled by glibc to
|
||||||
// behave as if it was called with srand(1). To get around this, I'm seeding
|
// behave as if it was called with srand(1). To get around this, I'm seeding
|
||||||
// with rank + 1
|
// with rank + 1
|
||||||
//
|
//
|
||||||
|
@ -46,17 +46,26 @@ int main(int argc, char **argv) {
|
||||||
// printf(" - %d\n", integers[i]);
|
// printf(" - %d\n", integers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
recursive_quicksort(integers, n, MPI_COMM_WORLD);
|
recursive_quicksort(integers, n, 0, MPI_COMM_WORLD);
|
||||||
|
|
||||||
sleep(1);
|
// sleep(1);
|
||||||
printf("[%d] after: %s\n", rank, string_of_list(integers, n_over_p));
|
// printf("[%d] after: %s\n", rank, string_of_list(integers, n_over_p));
|
||||||
|
|
||||||
// The first node is responsible for collecting all the data and then
|
// The first node is responsible for collecting all the data and then
|
||||||
// printing it out to the file MPI_Gather(const void *sendbuf, int
|
// printing it out to the file MPI_Gather(const void *sendbuf, int
|
||||||
// sendcount, MPI_INT, void *recvbuf,
|
// sendcount, MPI_INT, void *recvbuf,
|
||||||
// int recvcount, MPI_INT, 0, MPI_COMM_WORLD);
|
// int recvcount, MPI_INT, 0, MPI_COMM_WORLD);
|
||||||
|
int recvbuf[n];
|
||||||
|
MPI_Allgather(integers, n_over_p, MPI_INT, recvbuf, n_over_p, MPI_INT,
|
||||||
|
MPI_COMM_WORLD);
|
||||||
|
|
||||||
if (rank == 0) {
|
if (rank == 0) {
|
||||||
FILE *f = fopen(argv[2], "w");
|
FILE *f = fopen(argv[2], "w");
|
||||||
|
// printf("integers: %s\n", string_of_list(recvbuf, n));
|
||||||
|
for (int i = 0; i < p; i += 1) {
|
||||||
|
printf("[%d] integers: %s\n", rank,
|
||||||
|
string_of_list(&recvbuf[i * n_over_p], n_over_p));
|
||||||
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +117,7 @@ char *string_of_list(int *arr, int len) {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void recursive_quicksort(int *integers, int n, MPI_Comm comm) {
|
void recursive_quicksort(int *integers, int n, int root, MPI_Comm comm) {
|
||||||
int rank, p;
|
int rank, p;
|
||||||
MPI_Comm_size(comm, &p);
|
MPI_Comm_size(comm, &p);
|
||||||
MPI_Comm_rank(comm, &rank);
|
MPI_Comm_rank(comm, &rank);
|
||||||
|
@ -116,10 +125,19 @@ void recursive_quicksort(int *integers, int n, MPI_Comm comm) {
|
||||||
if (p == 1) {
|
if (p == 1) {
|
||||||
// Recursion base case: just sort it serially
|
// Recursion base case: just sort it serially
|
||||||
local_quicksort(integers, 0, n);
|
local_quicksort(integers, 0, n);
|
||||||
|
printf("Quicksorted: %s\n", string_of_list(integers, n));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
printf("\n\n");
|
||||||
|
int n_over_p_max = (n + p - 1) / p;
|
||||||
int n_over_p = n / p;
|
int n_over_p = n / p;
|
||||||
|
if (rank == root)
|
||||||
|
n_over_p += n - p * n_over_p;
|
||||||
|
printf(
|
||||||
|
"[%d] :::::::::::::::::::::::::::: RECURSIVE QUICKSORT (n=%d, n/p=%d)\n",
|
||||||
|
rank, n, n_over_p);
|
||||||
|
|
||||||
// Locally sort
|
// Locally sort
|
||||||
// printf("[%d] Numbers before: %s\n", rank,
|
// printf("[%d] Numbers before: %s\n", rank,
|
||||||
|
@ -131,12 +149,26 @@ void recursive_quicksort(int *integers, int n, MPI_Comm comm) {
|
||||||
// Select a pivot.
|
// Select a pivot.
|
||||||
// This pivot is broadcasted to all nodes
|
// This pivot is broadcasted to all nodes
|
||||||
int pivot;
|
int pivot;
|
||||||
|
{
|
||||||
|
// First, select a random element
|
||||||
|
int rand_el = integers[rand() % n_over_p];
|
||||||
|
|
||||||
// The pivot is selected as the median (see chp. 9.4.4)
|
// Gather it
|
||||||
// Not the real median though, need an existing element of the array
|
int rand_els[p];
|
||||||
pivot = integers[n_over_p / 2];
|
MPI_Gather(&rand_el, 1, MPI_INT, rand_els, 1, MPI_INT, root, comm);
|
||||||
MPI_Bcast(&pivot, 1, MPI_INT, 0, MPI_COMM_WORLD);
|
|
||||||
// printf("--- Broadcasted pivot: %d ---\n", pivot);
|
// Get the median
|
||||||
|
if (rank == root) {
|
||||||
|
// Sort
|
||||||
|
local_quicksort(rand_els, 0, p);
|
||||||
|
|
||||||
|
// Get the middle element
|
||||||
|
pivot = rand_els[p / 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
MPI_Bcast(&pivot, 1, MPI_INT, root, comm);
|
||||||
|
}
|
||||||
|
printf("[%d] Broadcasted pivot: %d\n", rank, pivot);
|
||||||
|
|
||||||
// Determine where the boundary between S (lower) and L (higher) lies
|
// Determine where the boundary between S (lower) and L (higher) lies
|
||||||
int boundary;
|
int boundary;
|
||||||
|
@ -154,12 +186,12 @@ void recursive_quicksort(int *integers, int n, MPI_Comm comm) {
|
||||||
|
|
||||||
// Perform global arrangement
|
// Perform global arrangement
|
||||||
int S_global_end, L_reverse_end, S_global_max_end;
|
int S_global_end, L_reverse_end, S_global_max_end;
|
||||||
MPI_Scan(&S_size, &S_global_end, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
|
MPI_Scan(&S_size, &S_global_end, 1, MPI_INT, MPI_SUM, comm);
|
||||||
MPI_Scan(&L_size, &L_reverse_end, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
|
MPI_Scan(&L_size, &L_reverse_end, 1, MPI_INT, MPI_SUM, comm);
|
||||||
|
|
||||||
// printf("[%d] bruh %d\n", rank, S_global_end);
|
// printf("[%d] bruh %d\n", rank, S_global_end);
|
||||||
MPI_Reduce(&S_global_end, &S_global_max_end, 1, MPI_INT, MPI_MAX, 0,
|
// Get the boundary element between S and L
|
||||||
MPI_COMM_WORLD);
|
MPI_Allreduce(&S_global_end, &S_global_max_end, 1, MPI_INT, MPI_MAX, comm);
|
||||||
|
|
||||||
int S_global_start = S_global_end - S_size,
|
int S_global_start = S_global_end - S_size,
|
||||||
L_reverse_start = L_reverse_end - L_size,
|
L_reverse_start = L_reverse_end - L_size,
|
||||||
|
@ -240,7 +272,7 @@ void recursive_quicksort(int *integers, int n, MPI_Comm comm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MPI_Alltoallv(send_ctl, ctl_send_counts, ctl_send_displs, MPI_INT, S_ctl,
|
MPI_Alltoallv(send_ctl, ctl_send_counts, ctl_send_displs, MPI_INT, S_ctl,
|
||||||
recv_counts, recv_displs, MPI_INT, MPI_COMM_WORLD);
|
recv_counts, recv_displs, MPI_INT, comm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send L to the correct target
|
// Send L to the correct target
|
||||||
|
@ -282,7 +314,7 @@ void recursive_quicksort(int *integers, int n, MPI_Comm comm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MPI_Alltoallv(send_ctl, ctl_send_counts, ctl_send_displs, MPI_INT, L_ctl,
|
MPI_Alltoallv(send_ctl, ctl_send_counts, ctl_send_displs, MPI_INT, L_ctl,
|
||||||
recv_counts, recv_displs, MPI_INT, MPI_COMM_WORLD);
|
recv_counts, recv_displs, MPI_INT, comm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// After sending S and L information
|
// After sending S and L information
|
||||||
|
@ -296,9 +328,12 @@ void recursive_quicksort(int *integers, int n, MPI_Comm comm) {
|
||||||
// integers_recv_buf,
|
// integers_recv_buf,
|
||||||
// recv_counts, recv_displs, MPI_INT, MPI_COMM_WORLD);
|
// recv_counts, recv_displs, MPI_INT, MPI_COMM_WORLD);
|
||||||
MPI_Allgather(integers, n_over_p, MPI_INT, integers_recv_buf, n_over_p,
|
MPI_Allgather(integers, n_over_p, MPI_INT, integers_recv_buf, n_over_p,
|
||||||
MPI_INT, MPI_COMM_WORLD);
|
MPI_INT, comm);
|
||||||
// printf("[%d] ints: %s\n", rank, string_of_list(integers_recv_buf, n));
|
// printf("[%d] ints: %s\n", rank, string_of_list(integers_recv_buf, n));
|
||||||
|
|
||||||
|
for (int i = 0; i < p; ++i) {
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < p; ++i) {
|
for (int i = 0; i < p; ++i) {
|
||||||
int count = S_ctl[i * CTL_SIZE];
|
int count = S_ctl[i * CTL_SIZE];
|
||||||
int from_global_start = S_ctl[i * CTL_SIZE + 1];
|
int from_global_start = S_ctl[i * CTL_SIZE + 1];
|
||||||
|
@ -306,7 +341,7 @@ void recursive_quicksort(int *integers, int n, MPI_Comm comm) {
|
||||||
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
printf(
|
printf(
|
||||||
"[%d] <<- S received (%d) from processor %d {%d..%d} to [%d..%d]\n",
|
"[%d] <<- S received (%d) from processor %d {%d..%d} to [% d..% d]\n",
|
||||||
rank, count, i, from_global_start, from_global_start + count,
|
rank, count, i, from_global_start, from_global_start + count,
|
||||||
to_local_start, to_local_start + count);
|
to_local_start, to_local_start + count);
|
||||||
for (int j = 0; j < count; ++j) {
|
for (int j = 0; j < count; ++j) {
|
||||||
|
@ -322,7 +357,7 @@ void recursive_quicksort(int *integers, int n, MPI_Comm comm) {
|
||||||
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
printf(
|
printf(
|
||||||
"[%d] <<- S received (%d) from processor %d {%d..%d} to [%d..%d]\n",
|
"[%d] <<- S received (%d) from processor %d {%d..%d} to [% d..% d]\n",
|
||||||
rank, count, i, from_global_start, from_global_start + count,
|
rank, count, i, from_global_start, from_global_start + count,
|
||||||
to_local_start, to_local_start + count);
|
to_local_start, to_local_start + count);
|
||||||
for (int j = 0; j < count; ++j) {
|
for (int j = 0; j < count; ++j) {
|
||||||
|
@ -331,37 +366,59 @@ void recursive_quicksort(int *integers, int n, MPI_Comm comm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("[%d] after: %s\n", rank, string_of_list(integers, n_over_p));
|
||||||
|
|
||||||
// Now, determine which processes should be responsible for taking the S and L
|
// Now, determine which processes should be responsible for taking the S and L
|
||||||
// arrays
|
// arrays
|
||||||
|
|
||||||
// Specifically, the part where it's split, break the tie to see if it goes
|
// Specifically, the part where it's split, break the tie to see if it goes
|
||||||
// down or up
|
// down or up
|
||||||
int colors[p];
|
int colors[p];
|
||||||
if (rank == 0) {
|
int p_of_split = S_global_max_end / n_over_p;
|
||||||
int p_of_split = S_global_max_end / n_over_p;
|
int split_point = S_global_max_end % n_over_p;
|
||||||
int split_point = S_global_max_end % n_over_p;
|
// printf("[%d] p_of_split = %d / %d = %d\n", rank, S_global_max_end,
|
||||||
printf("[%d] shiet %d\n", rank, p_of_split);
|
// n_over_p,
|
||||||
|
// p_of_split);
|
||||||
|
int S_split_add = split_point, L_split_sub = n_over_p - split_point;
|
||||||
|
|
||||||
int lo_start = 0, lo_end;
|
int lo_start = 0, lo_end;
|
||||||
int hi_start, hi_end = p;
|
int hi_start, hi_end = p;
|
||||||
if (split_point > n_over_p / 2) {
|
if (split_point > n_over_p / 2) {
|
||||||
// Belongs to the lower group
|
// Belongs to the lower group
|
||||||
lo_end = hi_start = p_of_split + 1;
|
lo_end = hi_start = p_of_split + 1;
|
||||||
} else {
|
} else {
|
||||||
// Belongs to the higher group
|
// Belongs to the higher group
|
||||||
lo_end = hi_start = p_of_split;
|
lo_end = hi_start = p_of_split;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < p; ++i) {
|
int child_root = -1;
|
||||||
if (i < lo_end)
|
for (int i = 0; i < p; ++i) {
|
||||||
colors[i] = 100;
|
if (i < lo_end)
|
||||||
else
|
colors[i] = 100;
|
||||||
colors[i] = 200;
|
else {
|
||||||
|
colors[i] = 200;
|
||||||
|
if (child_root == -1)
|
||||||
|
child_root = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MPI_Comm child;
|
// MPI_Comm child;
|
||||||
MPI_Comm_split(comm, colors[rank], rank, &child);
|
// MPI_Comm_split(comm, colors[rank], rank, &child);
|
||||||
printf("[%d] Recursing...\n", rank);
|
// printf("[%d] Recursing...\n", rank);
|
||||||
MPI_Comm_free(&child);
|
|
||||||
|
// int child_size;
|
||||||
|
// MPI_Comm_size(child, &child_size);
|
||||||
|
|
||||||
|
// int start_at = 0, new_n = child_size * n_over_p;
|
||||||
|
// if (colors[rank] == 100) {
|
||||||
|
// new_n += S_split_add;
|
||||||
|
// } else {
|
||||||
|
// new_n -= L_split_sub;
|
||||||
|
// if (rank == p_of_split)
|
||||||
|
// start_at = split_point;
|
||||||
|
// }
|
||||||
|
// recursive_quicksort(integers, n, child_root, child);
|
||||||
|
|
||||||
|
// printf("[%d] Done recursing.\n", rank);
|
||||||
|
// MPI_Comm_free(&child);
|
||||||
}
|
}
|
Loading…
Reference in a new issue