0% found this document useful (0 votes)
7 views20 pages

Parallel Computing Lab

The document contains multiple OpenMP and MPI programs demonstrating various parallel computing techniques. It includes implementations for sorting arrays with mergesort, calculating Fibonacci numbers, finding prime numbers, and demonstrating MPI communication operations like send/receive, broadcast, scatter/gather, and reduce. Each section provides code snippets along with explanations of the functionality and execution timings.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views20 pages

Parallel Computing Lab

The document contains multiple OpenMP and MPI programs demonstrating various parallel computing techniques. It includes implementations for sorting arrays with mergesort, calculating Fibonacci numbers, finding prime numbers, and demonstrating MPI communication operations like send/receive, broadcast, scatter/gather, and reduce. Each section provides code snippets along with explanations of the functionality and execution timings.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

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

You might also like