1.
Write a OpenMP program to sort an array on n elements using both sequential and parallel
mergesort(using Section). Record the difference in execution time. c program
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include <time.h>
void merge(int arr[], int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;
int *L = (int *)malloc(n1 * sizeof(int));
int *R = (int *)malloc(n2 * sizeof(int));
for (int i = 0; i < n1; i++) L[i] = arr[left + i];
for (int i = 0; i < n2; i++) R[i] = arr[mid + 1 + i];
int i = 0, j = 0, k = left;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) arr[k++] = L[i++];
else arr[k++] = R[j++];
while (i < n1) arr[k++] = L[i++];
while (j < n2) arr[k++] = R[j++];
free(L);
free(R);
// Sequential Merge Sort
void mergeSortSequential(int arr[], int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSortSequential(arr, left, mid);
mergeSortSequential(arr, mid + 1, right);
merge(arr, left, mid, right);
// Parallel Merge Sort using OpenMP sections
void mergeSortParallel(int arr[], int left, int right, int depth) {
if (left < right) {
int mid = (left + right) / 2;
if (depth <= 3) { // limit recursion depth for parallelism
#pragma omp sections
#pragma omp section
mergeSortParallel(arr, left, mid, depth + 1);
#pragma omp section
mergeSortParallel(arr, mid + 1, right, depth + 1);
} else {
mergeSortSequential(arr, left, mid);
mergeSortSequential(arr, mid + 1, right);
merge(arr, left, mid, right);
}
// Wrapper to start parallel region only once
void parallelMergeSortWrapper(int arr[], int n) {
#pragma omp parallel
#pragma omp single
mergeSortParallel(arr, 0, n - 1, 0);
int main() {
int n;
printf("Enter number of elements: ");
scanf("%d", &n);
int *arr1 = (int *)malloc(n * sizeof(int));
int *arr2 = (int *)malloc(n * sizeof(int));
srand(time(NULL));
for (int i = 0; i < n; i++) {
int val = rand() % 100000;
arr1[i] = arr2[i] = val;
double start, end;
// Sequential
start = omp_get_wtime();
mergeSortSequential(arr1, 0, n - 1);
end = omp_get_wtime();
printf("Sequential MergeSort Time: %f seconds\n", end - start);
// Parallel
start = omp_get_wtime();
parallelMergeSortWrapper(arr2, n);
end = omp_get_wtime();
printf("Parallel MergeSort Time: %f seconds\n", end - start);
free(arr1);
free(arr2);
return 0;
gcc mergesort_openmp.c -fopenmp -o mergesort
./mergesort
2. Write an OpenMP program that divides the Iterations into chunks containing 2 iterations,
respectively (OMP_SCHEDULE=static,2). Its input should be the number of iterations, and
its output should be which iterations of a parallelized for loop are executed by which thread.
For example, if there are two threads and four iterations, the output might be the following:
a. Thread 0 : Iterations 0 −− 1
b. Thread 1 : Iterations 2 – 3
#include <stdio.h>
#include <omp.h>
int main() {
int n, i;
printf("Enter number of iterations: ");
scanf("%d", &n);
// Set environment variable for scheduling: static with chunk size 2
omp_set_schedule(omp_sched_static, 2);
// Parallel region with for loop
#pragma omp parallel for schedule(static,2)
for (i = 0; i < n; i++) {
printf("Thread %d : Iteration %d\n", omp_get_thread_num(), i);
return 0;
omp_set_schedule(omp_sched_static,
Sets the scheduling policy to static with a chunk size of 2.
#pragma omp parallel for schedule(static,2)
Tells OpenMP to distribute the loop iterations among threads in chunks of size 2.
omp_get_thread_num()
Retrieves the thread ID (e.g., 0, 1, …).
3. Write a OpenMP program to calculate n Fibonacci numbers using tasks.
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
// Recursive Fibonacci using OpenMP tasks
long long fib(int n) {
long long x, y;
if (n < 2) return n;
#pragma omp task shared(x)
x = fib(n - 1);
#pragma omp task shared(y)
y = fib(n - 2);
#pragma omp taskwait
return x + y;
}
int main() {
int n;
printf("Enter number of Fibonacci numbers: ");
scanf("%d", &n);
long long *result = (long long *)malloc(n * sizeof(long long));
double start = omp_get_wtime();
#pragma omp parallel
#pragma omp single // Only one thread starts creating tasks
for (int i = 0; i < n; i++) {
result[i] = fib(i);
double end = omp_get_wtime();
printf("Fibonacci sequence up to %d numbers:\n", n);
for (int i = 0; i < n; i++) {
printf("%lld ", result[i]);
printf("\nExecution Time: %f seconds\n", end - start);
free(result);
return 0;
}
1. fib() function:
o Uses OpenMP #pragma omp task to spawn new tasks for fib(n-1) and fib(n-2).
o Uses #pragma omp taskwait to wait until both tasks finish.
2. Main function:
o Creates a parallel region with #pragma omp parallel.
o Uses #pragma omp single so only one thread starts creating tasks.
o Iteratively calculates Fibonacci numbers for indices 0…n-1.
3. Result:
o The tasks run concurrently, allowing multiple Fibonacci calculations in parallel.
gcc fibonacci_tasks.c -fopenmp -o fibonacci
./fibonacci
4. Write a OpenMP program to find the prime numbers from 1 to n employing parallel for directive. Record
both serial and parallel execution times.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
// Function to check if a number is prime
int is_prime(int num) {
if (num <= 1) return 0;
if (num == 2) return 1;
if (num % 2 == 0) return 0;
for (int i = 3; i <= sqrt(num); i += 2) {
if (num % i == 0) return 0;
return 1;
int main() {
int n;
printf("Enter the range (1 to n): ");
scanf("%d", &n);
int *prime_serial = (int *)malloc((n+1) * sizeof(int));
int *prime_parallel = (int *)malloc((n+1) * sizeof(int));
// ================= Serial Execution =================
double start = omp_get_wtime();
for (int i = 1; i <= n; i++) {
prime_serial[i] = is_prime(i);
double end = omp_get_wtime();
printf("\nSerial Execution Time: %f seconds\n", end - start);
// ================= Parallel Execution =================
start = omp_get_wtime();
#pragma omp parallel for
for (int i = 1; i <= n; i++) {
prime_parallel[i] = is_prime(i);
end = omp_get_wtime();
printf("Parallel Execution Time: %f seconds\n", end - start);
// Printing primes (from parallel version for consistency)
printf("\nPrime numbers from 1 to %d:\n", n);
for (int i = 1; i <= n; i++) {
if (prime_parallel[i]) {
printf("%d ", i);
printf("\n");
free(prime_serial);
free(prime_parallel);
return 0;
gcc prime_parallel.c -fopenmp -lm -o prime_parallel
./prime_parallel
is_prime() → Checks if a number is prime.
Serial loop:
Uses a normal for loop to mark prime numbers.
Parallel loop:
Uses OpenMP #pragma omp parallel for to split the range among threads.
Execution times:
omp_get_wtime() measures both serial and parallel execution durations.
Output:
Prints the prime numbers and both execution times.
5. Write a MPI Program to demonstration of MPI_Send and MPI_Recv.
#include <stdio.h>
#include <mpi.h>
int main(int argc, char** argv) {
int rank, size;
int number;
MPI_Init(&argc, &argv); // Initialize MPI environment
MPI_Comm_rank(MPI_COMM_WORLD, &rank); // Get current process rank
MPI_Comm_size(MPI_COMM_WORLD, &size); // Get total number of processes
if (size < 2) {
if (rank == 0) {
printf("This program needs at least 2 processes.\n");
MPI_Finalize();
return 0;
if (rank == 0) {
// Process 0 sends data to Process 1
number = 100;
printf("Process 0 sending number %d to Process 1\n", number);
MPI_Send(&number, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
} else if (rank == 1) {
// Process 1 receives data from Process 0
MPI_Recv(&number, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("Process 1 received number %d from Process 0\n", number);
MPI_Finalize(); // Finalize MPI environment
return 0;
mpicc mpi_send_recv.c -o mpi_send_recv
mpirun -np 2 ./mpi_send_recv
6. Write a MPI program to demonstration of deadlock using point to point communication and avoidance
of deadlock by altering the call sequence.
#include <stdio.h>
#include <mpi.h>
int main(int argc, char** argv) {
int rank, size;
int msg = 0;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size < 2) {
if (rank == 0)
printf("This program needs at least 2 processes.\n");
MPI_Finalize();
return 0;
// ======= DEADLOCK SCENARIO =======
if (rank == 0) {
printf("Process 0: Sending message to Process 1 (will deadlock)...\n");
MPI_Send(&msg, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
MPI_Recv(&msg, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("Process 0: Received message from Process 1\n");
else if (rank == 1) {
printf("Process 1: Sending message to Process 0 (will deadlock)...\n");
MPI_Send(&msg, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
MPI_Recv(&msg, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("Process 1: Received message from Process 0\n");
MPI_Barrier(MPI_COMM_WORLD); // Sync before avoiding deadlock
if (rank == 0) printf("\n--- Avoiding Deadlock by Changing Call Order ---\n");
// ======= DEADLOCK AVOIDANCE =======
if (rank == 0) {
printf("Process 0: Sending message to Process 1 (safe)...\n");
MPI_Send(&msg, 1, MPI_INT, 1, 1, MPI_COMM_WORLD);
MPI_Recv(&msg, 1, MPI_INT, 1, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("Process 0: Received message from Process 1 safely\n");
else if (rank == 1) {
printf("Process 1: Receiving message from Process 0 (safe)...\n");
MPI_Recv(&msg, 1, MPI_INT, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
MPI_Send(&msg, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
printf("Process 1: Sent message back to Process 0 safely\n");
}
MPI_Finalize();
return 0;
mpicc mpi_deadlock.c -o mpi_deadlock
mpirun -np 2 ./mpi_deadlock
7. Write a MPI Program to demonstration of Broadcast operation.
#include <stdio.h>
#include <mpi.h>
int main(int argc, char** argv) {
int rank, size;
int number;
MPI_Init(&argc, &argv); // Initialize MPI
MPI_Comm_rank(MPI_COMM_WORLD, &rank); // Get process rank
MPI_Comm_size(MPI_COMM_WORLD, &size); // Get total number of processes
if (rank == 0) {
printf("Process 0: Enter a number to broadcast: ");
scanf("%d", &number);
// Broadcasting the number from Process 0 to all other processes
MPI_Bcast(&number, 1, MPI_INT, 0, MPI_COMM_WORLD);
printf("Process %d: Received number = %d\n", rank, number);
MPI_Finalize(); // Finalize MPI
return 0;
mpicc mpi_broadcast.c -o mpi_broadcast
mpirun -np 4 ./mpi_broadcast
8. Write a MPI Program demonstration of MPI_Scatter and MPI_Gather
#include <stdio.h>
#include <mpi.h>
int main(int argc, char** argv) {
int rank, size;
int send_data[100], recv_data;
int gathered_data[100];
MPI_Init(&argc, &argv); // Initialize MPI
MPI_Comm_rank(MPI_COMM_WORLD, &rank); // Get current process rank
MPI_Comm_size(MPI_COMM_WORLD, &size); // Get total number of processes
if (size > 100) {
if (rank == 0)
printf("This demo supports up to 100 processes only.\n");
MPI_Finalize();
return 0;
// Prepare data in root process
if (rank == 0) {
printf("Root process preparing data...\n");
for (int i = 0; i < size; i++) {
send_data[i] = i + 1; // Example: 1, 2, 3, ...
// Scatter: Distribute one element of send_data to each process
MPI_Scatter(send_data, 1, MPI_INT, &recv_data, 1, MPI_INT, 0, MPI_COMM_WORLD);
printf("Process %d received data: %d\n", rank, recv_data);
// Each process performs a computation (multiply by 2)
recv_data *= 2;
// Gather: Collect processed data from all processes into gathered_data array in root
MPI_Gather(&recv_data, 1, MPI_INT, gathered_data, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (rank == 0) {
printf("\nGathered data in root process:\n");
for (int i = 0; i < size; i++) {
printf("%d ", gathered_data[i]);
printf("\n");
MPI_Finalize(); // Finalize MPI
return 0;
mpicc mpi_scatter_gather.c -o mpi_scatter_gather
mpirun -np 4 ./mpi_scatter_gather
9. Write a MPI Program to demonstration of MPI_Reduce and MPI_Allreduce (MPI_MAX,
MPI_MIN, MPI_SUM, MPI_PROD)
#include <stdio.h>
#include <mpi.h>
int main(int argc, char** argv) {
int rank, size;
int value;
int result_reduce, result_allreduce;
MPI_Init(&argc, &argv); // Initialize MPI
MPI_Comm_rank(MPI_COMM_WORLD, &rank); // Get current process rank
MPI_Comm_size(MPI_COMM_WORLD, &size); // Get total number of processes
// Each process has a unique value
value = rank + 1; // Process 0 = 1, Process 1 = 2, ...
// 1. MPI_Reduce - SUM
MPI_Reduce(&value, &result_reduce, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
if (rank == 0) {
printf("MPI_Reduce SUM result: %d\n", result_reduce);
// 2. MPI_Reduce - MAX
MPI_Reduce(&value, &result_reduce, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);
if (rank == 0) {
printf("MPI_Reduce MAX result: %d\n", result_reduce);
// 3. MPI_Reduce - MIN
MPI_Reduce(&value, &result_reduce, 1, MPI_INT, MPI_MIN, 0, MPI_COMM_WORLD);
if (rank == 0) {
printf("MPI_Reduce MIN result: %d\n", result_reduce);
// 4. MPI_Reduce - PRODUCT
MPI_Reduce(&value, &result_reduce, 1, MPI_INT, MPI_PROD, 0, MPI_COMM_WORLD);
if (rank == 0) {
printf("MPI_Reduce PRODUCT result: %d\n", result_reduce);
// --- MPI_Allreduce performs the same but result is available to ALL processes ---
// 5. MPI_Allreduce - SUM
MPI_Allreduce(&value, &result_allreduce, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
printf("Process %d: MPI_Allreduce SUM = %d\n", rank, result_allreduce);
// 6. MPI_Allreduce - MAX
MPI_Allreduce(&value, &result_allreduce, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
printf("Process %d: MPI_Allreduce MAX = %d\n", rank, result_allreduce);
// 7. MPI_Allreduce - MIN
MPI_Allreduce(&value, &result_allreduce, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
printf("Process %d: MPI_Allreduce MIN = %d\n", rank, result_allreduce);
// 8. MPI_Allreduce - PRODUCT
MPI_Allreduce(&value, &result_allreduce, 1, MPI_INT, MPI_PROD, MPI_COMM_WORLD);
printf("Process %d: MPI_Allreduce PRODUCT = %d\n", rank, result_allreduce);
MPI_Finalize(); // Finalize MPI
return 0;
}
mpicc mpi_reduce_allreduce.c -o mpi_reduce_allreduce
mpirun -np 4 ./mpi_reduce_allreduce