diff --git a/assignments/02/process_output.py b/assignments/02/process_output.py index 1164ae4..072d4e4 100644 --- a/assignments/02/process_output.py +++ b/assignments/02/process_output.py @@ -21,4 +21,6 @@ for p in sorted(outputs.keys()): print(f"---- {p} ----") for line in lines: print(line) - print() \ No newline at end of file + print() + +print("Done.") \ No newline at end of file diff --git a/assignments/02/qs_mpi.c b/assignments/02/qs_mpi.c index 1ee0bb6..4a053e8 100644 --- a/assignments/02/qs_mpi.c +++ b/assignments/02/qs_mpi.c @@ -18,6 +18,7 @@ void local_quicksort(int *arr, int lo, int hi); char *string_of_list(int *arr, int len); +void recursive_quicksort(int *integers, int n, MPI_Comm comm); int main(int argc, char **argv) { int rank, p; @@ -45,7 +46,80 @@ int main(int argc, char **argv) { // printf(" - %d\n", integers[i]); } - int group_root = 0; + recursive_quicksort(integers, n, MPI_COMM_WORLD); + + sleep(1); + 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 + // printing it out to the file MPI_Gather(const void *sendbuf, int + // sendcount, MPI_INT, void *recvbuf, + // int recvcount, MPI_INT, 0, MPI_COMM_WORLD); + if (rank == 0) { + FILE *f = fopen(argv[2], "w"); + fclose(f); + } + + MPI_Finalize(); + printf("Done.\n"); + return 0; +} + +// hi not inclusive +void local_quicksort(int *arr, int lo, int hi) { + int temp; + + if (lo >= hi || lo < 0) + return; + + int pivot = arr[hi - 1]; + int pivot_idx = lo - 1; + for (int j = lo; j < hi; ++j) { + if (arr[j] < pivot) { + pivot_idx += 1; + + temp = arr[j]; + arr[j] = arr[pivot_idx]; + arr[pivot_idx] = temp; + } + } + + pivot_idx += 1; + temp = arr[hi - 1]; + arr[hi - 1] = arr[pivot_idx]; + arr[pivot_idx] = temp; + + // Recursive call + local_quicksort(arr, lo, pivot_idx); + local_quicksort(arr, pivot_idx + 1, hi); +} + +char *string_of_list(int *arr, int len) { + char *buffer = calloc(sizeof(char), 1000); + int offset = 0; // Keep track of the current position in the buffer + for (int i = 0; i < len; i++) { + offset += sprintf(buffer + offset, "%d", arr[i]); + if (i < len - 1) { + // Add a separator (e.g., comma or space) if it's not the last element + offset += sprintf(buffer + offset, " "); + } + } + + return buffer; +} + +void recursive_quicksort(int *integers, int n, MPI_Comm comm) { + int rank, p; + MPI_Comm_size(comm, &p); + MPI_Comm_rank(comm, &rank); + + if (p == 1) { + // Recursion base case: just sort it serially + local_quicksort(integers, 0, n); + return; + } + + int n_over_p = n / p; // Locally sort // printf("[%d] Numbers before: %s\n", rank, @@ -62,7 +136,7 @@ int main(int argc, char **argv) { // Not the real median though, need an existing element of the array pivot = integers[n_over_p / 2]; MPI_Bcast(&pivot, 1, MPI_INT, 0, MPI_COMM_WORLD); - printf("--- Broadcasted pivot: %d ---\n", pivot); + // printf("--- Broadcasted pivot: %d ---\n", pivot); // Determine where the boundary between S (lower) and L (higher) lies int boundary; @@ -79,10 +153,14 @@ int main(int argc, char **argv) { S_size, L_lo, L_hi, L_size); // Perform global arrangement - int S_global_end, L_reverse_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(&L_size, &L_reverse_end, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); + // printf("[%d] bruh %d\n", rank, S_global_end); + MPI_Reduce(&S_global_end, &S_global_max_end, 1, MPI_INT, MPI_MAX, 0, + MPI_COMM_WORLD); + int S_global_start = S_global_end - S_size, L_reverse_start = L_reverse_end - L_size, L_global_start = n - L_reverse_end, L_global_end = n - L_reverse_start; @@ -253,62 +331,37 @@ int main(int argc, char **argv) { } } - sleep(1); - 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 + // arrays - // The first node is responsible for collecting all the data and then - // printing it out to the file MPI_Gather(const void *sendbuf, int - // sendcount, MPI_INT, void *recvbuf, - // int recvcount, MPI_INT, 0, MPI_COMM_WORLD); + // Specifically, the part where it's split, break the tie to see if it goes + // down or up + int colors[p]; if (rank == 0) { - FILE *f = fopen(argv[2], "w"); - fclose(f); - } + int p_of_split = S_global_max_end / n_over_p; + int split_point = S_global_max_end % n_over_p; + printf("[%d] shiet %d\n", rank, p_of_split); - MPI_Finalize(); - printf("Done.\n"); - return 0; -} + int lo_start = 0, lo_end; + int hi_start, hi_end = p; + if (split_point > n_over_p / 2) { + // Belongs to the lower group + lo_end = hi_start = p_of_split + 1; + } else { + // Belongs to the higher group + lo_end = hi_start = p_of_split; + } -// hi not inclusive -void local_quicksort(int *arr, int lo, int hi) { - int temp; - - if (lo >= hi || lo < 0) - return; - - int pivot = arr[hi - 1]; - int pivot_idx = lo - 1; - for (int j = lo; j < hi; ++j) { - if (arr[j] < pivot) { - pivot_idx += 1; - - temp = arr[j]; - arr[j] = arr[pivot_idx]; - arr[pivot_idx] = temp; + for (int i = 0; i < p; ++i) { + if (i < lo_end) + colors[i] = 100; + else + colors[i] = 200; } } - pivot_idx += 1; - temp = arr[hi - 1]; - arr[hi - 1] = arr[pivot_idx]; - arr[pivot_idx] = temp; - - // Recursive call - local_quicksort(arr, lo, pivot_idx); - local_quicksort(arr, pivot_idx + 1, hi); -} - -char *string_of_list(int *arr, int len) { - char *buffer = calloc(sizeof(char), 1000); - int offset = 0; // Keep track of the current position in the buffer - for (int i = 0; i < len; i++) { - offset += sprintf(buffer + offset, "%d", arr[i]); - if (i < len - 1) { - // Add a separator (e.g., comma or space) if it's not the last element - offset += sprintf(buffer + offset, " "); - } - } - - return buffer; + MPI_Comm child; + MPI_Comm_split(comm, colors[rank], rank, &child); + printf("[%d] Recursing...\n", rank); + MPI_Comm_free(&child); } \ No newline at end of file