# Implementation of Quick sort using MPI, OMP and Posix thread

• Last Updated : 01 Nov, 2021

QuickSort is a Divide and Conquer Algorithm. It picks an element as a pivot and partitions the array around the picked pivot. There are many ways of choosing the pivot elements. They are:

• Always pick the first element as a pivot.
• Always pick the last element as the pivot (implemented below)
• Pick a random element as a pivot.
• Pick median as a pivot.

MPI: MPI stands for Message Passing Interface. Here the message is data. MPI allows data to be passed between processes in a distributed memory environment. In C, “mpi.h” is a header file that includes all data structures, routines, and constants of MPI. Using “mpi.h” parallelized the quick sort algorithm.  Below is the C program to implement quicksort using MPI:

## C

 `// C program to implement the Quick Sort``// Algorithm using MPI``#include ``#include ``#include ``#include ``#include ``using` `namespace` `std;` `// Function to swap two numbers``void` `swap(``int``* arr, ``int` `i, ``int` `j)``{``    ``int` `t = arr[i];``    ``arr[i] = arr[j];``    ``arr[j] = t;``}` `// Function that performs the Quick Sort``// for an array arr[] starting from the``// index start and ending at index end``void` `quicksort(``int``* arr, ``int` `start, ``int` `end)``{``    ``int` `pivot, index;` `    ``// Base Case``    ``if` `(end <= 1)``        ``return``;` `    ``// Pick pivot and swap with first``    ``// element Pivot is middle element``    ``pivot = arr[start + end / 2];``    ``swap(arr, start, start + end / 2);` `    ``// Partitioning Steps``    ``index = start;` `    ``// Iterate over the range [start, end]``    ``for` `(``int` `i = start + 1; i < start + end; i++) {` `        ``// Swap if the element is less``        ``// than the pivot element``        ``if` `(arr[i] < pivot) {``            ``index++;``            ``swap(arr, i, index);``        ``}``    ``}` `    ``// Swap the pivot into place``    ``swap(arr, start, index);` `    ``// Recursive Call for sorting``    ``// of quick sort function``    ``quicksort(arr, start, index - start);``    ``quicksort(arr, index + 1, start + end - index - 1);``}` `// Function that merges the two arrays``int``* merge(``int``* arr1, ``int` `n1, ``int``* arr2, ``int` `n2)``{``    ``int``* result = (``int``*)``malloc``((n1 + n2) * ``sizeof``(``int``));``    ``int` `i = 0;``    ``int` `j = 0;``    ``int` `k;` `    ``for` `(k = 0; k < n1 + n2; k++) {``        ``if` `(i >= n1) {``            ``result[k] = arr2[j];``            ``j++;``        ``}``        ``else` `if` `(j >= n2) {``            ``result[k] = arr1[i];``            ``i++;``        ``}` `        ``// Indices in bounds as i < n1``        ``// && j < n2``        ``else` `if` `(arr1[i] < arr2[j]) {``            ``result[k] = arr1[i];``            ``i++;``        ``}` `        ``// v2[j] <= v1[i]``        ``else` `{``            ``result[k] = arr2[j];``            ``j++;``        ``}``    ``}``    ``return` `result;``}` `// Driver Code``int` `main(``int` `argc, ``char``* argv[])``{``    ``int` `number_of_elements;``    ``int``* data = NULL;``    ``int` `chunk_size, own_chunk_size;``    ``int``* chunk;``    ``FILE``* file = NULL;``    ``double` `time_taken;``    ``MPI_Status status;` `    ``if` `(argc != 3) {``        ``printf``(``"Desired number of arguments are not their "``               ``"in argv....\n"``);``        ``printf``(``"2 files required first one input and "``               ``"second one output....\n"``);``        ``exit``(-1);``    ``}` `    ``int` `number_of_process, rank_of_process;``    ``int` `rc = MPI_Init(&argc, &argv);` `    ``if` `(rc != MPI_SUCCESS) {``        ``printf``(``"Error in creating MPI "``               ``"program.\n "``               ``"Terminating......\n"``);``        ``MPI_Abort(MPI_COMM_WORLD, rc);``    ``}` `    ``MPI_Comm_size(MPI_COMM_WORLD, &number_of_process);``    ``MPI_Comm_rank(MPI_COMM_WORLD, &rank_of_process);` `    ``if` `(rank_of_process == 0) {``        ``// Opening the file``        ``file = ``fopen``(argv, ``"r"``);` `        ``// Printing Error message if any``        ``if` `(file == NULL) {``            ``printf``(``"Error in opening file\n"``);``            ``exit``(-1);``        ``}` `        ``// Reading number of Elements in file ...``        ``// First Value in file is number of Elements``        ``printf``(``            ``"Reading number of Elements From file ....\n"``);``        ``fscanf``(file, ``"%d"``, &number_of_elements);``        ``printf``(``"Number of Elements in the file is %d \n"``,``               ``number_of_elements);` `        ``// Computing chunk size``    ``chunk_size = (number_of_elements %``                  ``number_of_process == 0) ?``                  ``(number_of_elements /``                   ``number_of_process) :``                  ``(number_of_elements /``                  ``(number_of_process - 1);` `    ``data = (``int` `*)``malloc``(number_of_process *``                         ``chunk_size *``                         ``sizeof``(``int``));``    ` `    ``// Reading the rest elements in which``    ``// operation is being performed``    ``printf``(``"Reading the array from the file.......\n"``);``    ``for``(``int` `i = 0; i < number_of_elements; i++)``    ``{``            ``fscanf``(file, ``"%d"``, &data[i]);``    ``}` `    ``// Padding data with zero``    ``for``(``int` `i = number_of_elements;``            ``i < number_of_process *``                ``chunk_size; i++)``    ``{``            ``data[i] = 0;``    ``}` `    ``// Printing the array read from file``      ``printf``(``"Elements in the array is : \n"``);``      ``for``(``int` `i = 0; i < number_of_elements; i++)``      ``{``            ``printf``(``"%d  "``, data[i]);``      ``}` `      ``printf``(``"\n"``);` `      ``fclose``(file);``      ``file = NULL;``    ``}` `    ``// Blocks all process until reach this point``    ``MPI_Barrier(MPI_COMM_WORLD);` `    ``// Starts Timer``    ``time_taken -= MPI_Wtime();` `    ``// BroadCast the Size to all the``    ``// process from root process``    ``MPI_Bcast(&number_of_elements, 1, MPI_INT, 0,``              ``MPI_COMM_WORLD);` `    ``// Computing chunk size``  ``chunk_size= (number_of_elements %``               ``number_of_process == 0) ?``              ``(number_of_elements /``               ``number_of_process) :``              ``(number_of_elements /``              ``(number_of_process - 1);` `  ``// Calculating total size of chunk``  ``// according to bits``  ``chunk = (``int` `*)``malloc``(chunk_size *``                        ``sizeof``(``int``));` `  ``// Scatter the chuck size data to all process``  ``MPI_Scatter(data, chunk_size, MPI_INT, chunk,``              ``chunk_size, MPI_INT, 0, MPI_COMM_WORLD);``  ``free``(data);``  ``data = NULL;` `  ``// Compute size of own chunk and``               ``// then sort them``  ``// using quick sort` `  ``own_chunk_size = (number_of_elements >=``                    ``chunk_size*(rank_of_process + 1)) ?``                    ``chunk_size : (number_of_elements -``                                  ``chunk_size*rank_of_process);` `  ``// Sorting array with quick sort for every``  ``// chunk as called by process``  ``quicksort(chunk, 0, own_chunk_size);` `  ``for``(``int` `step = 1; step < number_of_process; step = 2 * step)``  ``{``        ``if` `(rank_of_process % (2 * step) != 0) {``            ``MPI_Send(chunk, own_chunk_size, MPI_INT,``                     ``rank_of_process - step, 0,``                     ``MPI_COMM_WORLD);``            ``break``;``        ``}` `        ``if` `(rank_of_process + step < number_of_process) {``            ``int` `received_chunk_size``                ``= (number_of_elements``                   ``>= chunk_size``                          ``* (rank_of_process + 2 * step))``                      ``? (chunk_size * step)``                      ``: (number_of_elements``                         ``- chunk_size``                               ``* (rank_of_process + step));``            ``int``* chunk_received;``            ``chunk_received = (``int``*)``malloc``(``                ``received_chunk_size * ``sizeof``(``int``));``            ``MPI_Recv(chunk_received, received_chunk_size,``                     ``MPI_INT, rank_of_process + step, 0,``                     ``MPI_COMM_WORLD, &status);` `            ``data = merge(chunk, own_chunk_size,``                         ``chunk_received,``                         ``received_chunk_size);` `            ``free``(chunk);``            ``free``(chunk_received);``            ``chunk = data;``            ``own_chunk_size``                ``= own_chunk_size + received_chunk_size;``        ``}``  ``}` `  ``// Stop the timer``  ``time_taken += MPI_Wtime();` `  ``// Opening the other file as taken form input``  ``// and writing it to the file and giving it``  ``// as the output``  ``if``(rank_of_process == 0)``  ``{``        ``// Opening the file``        ``file = ``fopen``(argv, ``"w"``);` `        ``if` `(file == NULL) {``            ``printf``(``"Error in opening file... \n"``);``            ``exit``(-1);``        ``}` `        ``// Printing total number of elements``        ``// in the file``        ``fprintf``(``            ``file,``            ``"Total number of Elements in the array : %d\n"``,``            ``own_chunk_size);` `        ``// Printing the value of array in the file``        ``for` `(``int` `i = 0; i < own_chunk_size; i++) {``            ``fprintf``(file, ``"%d  "``, chunk[i]);``        ``}` `        ``// Closing the file``        ``fclose``(file);` `        ``printf``(``"\n\n\n\nResult printed in output.txt file "``               ``"and shown below: \n"``);` `        ``// For Printing in the terminal``        ``printf``(``"Total number of Elements given as input : "``               ``"%d\n"``,``               ``number_of_elements);``        ``printf``(``"Sorted array is: \n"``);` `        ``for` `(``int` `i = 0; i < number_of_elements; i++) {``            ``printf``(``"%d  "``, chunk[i]);``        ``}` `        ``printf``(``            ``"\n\nQuicksort %d ints on %d procs: %f secs\n"``,``            ``number_of_elements, number_of_process,``            ``time_taken);``  ``}` `  ``MPI_Finalize();``  ``return` `0;``}`

Output:   OMP: OMP is Open Multi-Processing. It’s an Application Program Interface (API) that may be used to explicitly direct multi-threaded, shared memory parallelism. In C/ C++, “omp.h” is a header file that includes all the related directives related to OMP. Using “omp.h” parallelized quick sort. Below is the C++ program to implement the above concept:

## C++

 `// C++ program to implement the Quick Sort``// using OMI``#include ``#include ``using` `namespace` `std;` `// Function to swap two numbers a and b``void` `swap(``int``* a, ``int``* b)``{``    ``int` `t = *a;``    ``*a = *b;``    ``*b = t;``}` `// Function to perform the partitioning``// of array arr[]``int` `partition(``int` `arr[], ``int` `start, ``int` `end)``{``    ``// Declaration``    ``int` `pivot = arr[end];``    ``int` `i = (start - 1);` `    ``// Rearranging the array``    ``for` `(``int` `j = start; j <= end - 1; j++) {``        ``if` `(arr[j] < pivot) {``            ``i++;``            ``swap(&arr[i], &arr[j]);``        ``}``    ``}``    ``swap(&arr[i + 1], &arr[end]);` `    ``// Returning the respective index``    ``return` `(i + 1);``}` `// Function to perform QuickSort Algorithm``// using openmp``void` `quicksort(``int` `arr[], ``int` `start, ``int` `end)``{``    ``// Declaration``    ``int` `index;` `    ``if` `(start < end) {` `        ``// Getting the index of pivot``        ``// by partitioning``        ``index = partition(arr, start, end);` `// Parallel sections``#pragma omp parallel sections``        ``{``#pragma omp section``            ``{``                ``// Evaluating the left half``                ``quicksort(arr, start, index - 1);``            ``}``#pragma omp section``            ``{``                ``// Evaluating the right half``                ``quicksort(arr, index + 1, end);``            ``}``        ``}``    ``}``}` `// Driver Code``int` `main()``{``    ``// Declaration``    ``int` `N;` `    ``// Taking input the number of``    ``// elements we wants``    ``cout << ``"Enter the number of elements"``         ``<< ``" you want to Enter\n"``;``    ``cin >> N;` `    ``// Declaration of array``    ``int` `arr[N];` `    ``cout << ``"Enter the array: \n"``;` `    ``// Taking input that array``    ``for` `(``int` `i = 0; i < N; i++) {``        ``cin >> arr[i];``    ``}` `    ``// Calling quicksort having parallel``    ``// code implementation``    ``quicksort(arr, 0, N - 1);` `    ``// Printing the sorted array``    ``cout << ``"Array after Sorting is: \n"``;` `    ``for` `(``int` `i = 0; i < N; i++) {``        ``cout << arr[i] << ``" "``;``    ``}` `    ``return` `0;``}`

Output: POSIX Threads: The POSIX thread libraries are a C/C++ thread API based on standards. It enables the creation of a new concurrent process flow. It works well on multi-processor or multi-core systems, where the process flow may be scheduled to execute on another processor, increasing speed through parallel or distributed processing. Below is the C++ program to implement quicksort using POSIX threads:

## C++14

 `// C++ program to implement the Quick Sort``// using POSIX Thread``#include ``#include ``using` `namespace` `std;` `// Structure``struct` `data_set {``    ``int` `start_index;``    ``int` `end_index;``    ``int``* data;``};` `// Function to perform swap operations``void` `swap(``int``* a, ``int``* b)``{``    ``int` `t = *a;``    ``*a = *b;``    ``*b = t;``}` `// Partition function for making``// partition in array``int` `partition(``int` `arr[], ``int` `left_index,``              ``int` `right_index)``{``    ``// Declaration and initialization``    ``// choosing pivot element form which``    ``// we make partition` `    ``// Here pivot is last element of``    ``// the array``    ``int` `pivot = arr[right_index];``    ``int` `i = left_index - 1;` `    ``// Making array as per requirement``    ``// arranging element smaller than``    ``// pivot on left side and larger``    ``// then pivot on right side``    ``for` `(``int` `j = left_index;``         ``j <= right_index - 1; j++) {` `        ``if` `(arr[j] < pivot) {``            ``i++;``            ``swap(&arr[i], &arr[j]);``        ``}``    ``}` `    ``swap(&arr[i + 1], &arr[right_index]);` `    ``// Returning the partition index``    ``return` `i + 1;``}` `// Quicksort Function for sorting``// array``void``* quick_sort(``void``* data)``{``    ``// Retrieving back the data sent``    ``// from thread``    ``struct` `data_set* info = (``struct` `data_set*)data;` `    ``// Declaration of left index``    ``int` `left_index, right_index, index;` `    ``// Initialization of left and``    ``// right index``    ``left_index = info->start_index;``    ``right_index = info->end_index;` `    ``// Recursive call of quick_sort``    ``// function``    ``if` `(left_index < right_index) {` `        ``// Declaration of pthread and``        ``// pthread attribute type object``        ``pthread_attr_t attr;``        ``pthread_t first_thread;``        ``pthread_t second_thread;` `        ``// Making two pointers of type``        ``// data_set for making again``        ``// call form thread``        ``struct` `data_set* info1 = ``new` `data_set;``        ``struct` `data_set* info2 = ``new` `data_set;` `        ``// Their initialization``        ``info1->data = info->data;``        ``info2->data = info->data;` `        ``// Initialize of pthread attribute``        ``pthread_attr_init(&attr);` `        ``// For setting the set detach``        ``// state of attribute``        ``pthread_attr_setdetachstate(``            ``&attr, PTHREAD_CREATE_JOINABLE);` `        ``// Partition the array for any``        ``// recursive call``        ``index = partition(info->data,``                          ``left_index,``                          ``right_index);` `        ``info1->start_index = left_index;``        ``info1->end_index = index - 1;` `        ``// Create pthread type object and``        ``// printing the error if any``        ``if` `(pthread_create(&first_thread,``                           ``&attr, quick_sort,``                           ``info1)) {``            ``cout << ``"Error in creating thread "``                 ``<< endl;` `            ``// Exiting in case of not``            ``// creation of thread``            ``exit``(-1);``        ``}` `        ``info2->start_index = index + 1;``        ``info2->end_index = right_index;` `        ``// Creating pthread type object``        ``// and print the error``        ``if` `(pthread_create(&second_thread,``                           ``&attr, quick_sort,``                           ``info2)) {``            ``cout << ``"Error in creating thread "``                 ``<< endl;` `            ``// Exiting in case of not``            ``// creation of thread``            ``exit``(-1);``        ``}` `        ``// Joining the threads``        ``pthread_join(first_thread, NULL);``        ``pthread_join(second_thread, NULL);``    ``}` `    ``return` `NULL;``}` `// Driver Code``int` `main()``{``    ``// Declaration of Number of threads``    ``int` `N;` `    ``struct` `data_set* info = ``new` `data_set;` `    ``// Taking number of elements as input``    ``cout << ``"Enter number of elements"``         ``<< ``" in the array: \n"``;``    ``cin >> N;` `    ``// Declaration of array``    ``int` `A[N];` `    ``// Initialization of array``    ``cout << ``"Enter the array: "` `<< endl;``    ``for` `(``int` `i = 0; i < N; i++) {``        ``cin >> A[i];``    ``}` `    ``// Initialize of structure of``    ``// data_set type``    ``info->data = A;``    ``info->start_index = 0;``    ``info->end_index = N - 1;` `    ``// Declaration of pthread object``    ``pthread_t thread_id;` `    ``// Creating and pthread object and``    ``// printing the array of any``    ``if` `(pthread_create(&thread_id, NULL,``                       ``quick_sort,``                       ``info)) {``        ``cout << ``"Error in creating thread"``             ``<< endl;` `        ``// Exit in case of error``        ``exit``(-1);``    ``}` `    ``// Joining the pthread object``    ``int` `r1 = pthread_join(thread_id, NULL);` `    ``// Printing the array if any in case``    ``// of joining``    ``if` `(r1) {``        ``cout << ``"Error in Joinging thread"``             ``<< endl;` `        ``// Exiting in case of error``        ``exit``(-1);``    ``}` `    ``// Printing the array after sorting``    ``cout << ``"Sorted Array is: "` `<< endl;` `    ``for` `(``int` `i = 0; i < N; i++) {``        ``cout << A[i] << ``" "``;``    ``}``    ``cout << endl;` `    ``// Exiting from pthread programming``    ``pthread_exit(NULL);` `    ``return` `0;``}`

Output: My Personal Notes arrow_drop_up