0% found this document useful (0 votes)
30 views21 pages

PDC Lab 9 Final

odkskdkdl
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views21 pages

PDC Lab 9 Final

odkskdkdl
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

ICS 311 PARALLEL AND DISTRIBUTED

COMPUTING
Lab 9
Name: Kartik Shettiwar
Roll: 2022BCS0226

1. Write a MPI program that estimates the value of the integral using trapezoidal rule for
numerical integration. 𝑨𝒓𝒆𝒂 = ∫ 𝒇(𝒙) 𝒃 𝒂 𝒅𝒙 , 𝒘𝒉𝒆𝒓𝒆 𝒇(𝒙) = 𝟑𝒙 + 𝟓 𝒂 = 𝟎, 𝒃 = 𝟑, 𝒏 = 𝟏𝟔,
𝟏𝟐𝟖, 𝟓𝟏𝟐, 𝟏𝟎𝟐𝟒.
a) Write the serial version program to estimate the value of the integral. Test the result with
classical integration value. Calculate the execution time by using the library function.
Solution =>
Code:

#include <iostream>

#include <cmath>

#include <chrono>

double f(double x) {

return 3 * x + 5; // The function to integrate

double trapezoidalRule(double a, double b, int n) {

double h = (b - a) / n; // Width of each trapezoid

double integral = 0.5 * (f(a) + f(b)); // Start with the endpoints

for (int i = 1; i < n; ++i) {

double x = a + i * h; // Compute x value


integral += f(x); // Add the function value at x

integral *= h; // Multiply by width to get the area

return integral;

int main() {

double a = 0.0; // Lower limit

double b = 3.0; // Upper limit

// Different values of n for testing

int n_values[] = {16, 128, 512, 1024};

int num_tests = sizeof(n_values) / sizeof(n_values[0]);

for (int i = 0; i < num_tests; ++i) {

int n = n_values[i];

// Start measuring time

auto start = std::chrono::high_resolution_clock::now();

double result = trapezoidalRule(a, b, n);

// End measuring time

auto end = std::chrono::high_resolution_clock::now();

std::chrono::duration<double> elapsed = end - start;

std::cout << "Estimated integral with n = " << n << ": " << result << std::endl;

std::cout << "Execution time: " << elapsed.count() << " seconds" << std::endl;

// The exact value of the integral can be calculated as:

// ∫(3x + 5) dx from 0 to 3 = [1.5x^2 + 5x] from 0 to 3 = 1.5(9) + 15 = 22.5


double exact_value = 22.5;

std::cout << "Exact value of the integral: " << exact_value << std::endl;

return 0;

Output:
b) Write the MPI code for parallel program with MPI built-in functions to estimate the value
of integral. Root process is collecting the results from the other processes and produces the
final output. Calculate the execution time by using the library function. Assume: Number of
processes=np=4, Root process=MIN(Rank of the processes).
Solution =>
Code:

#include <iostream>

#include <vector>

#include <mpi.h>

#include <chrono>

double f(double x) {

return 3 * x + 5; // The function to integrate

double trapezoidalRule(double a, double b, int n) {

double h = (b - a) / n; // Width of each trapezoid

double integral = 0.5 * (f(a) + f(b)); // Start with the endpoints

for (int i = 1; i < n; ++i) {

double x = a + i * h; // Compute x value

integral += f(x); // Add the function value at x

integral *= h; // Multiply by width to get the area

return integral;

int main(int argc, char** argv) {

MPI_Init(&argc, &argv);

int rank, size;


MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

double a = 0.0; // Lower limit

double b = 3.0; // Upper limit

int n_values[] = { 16, 128, 512, 1024 }; // Different values of n

int num_tests = sizeof(n_values) / sizeof(n_values[0]);

// The root process will print results

if (rank == 0) {

std::cout << "Estimating integral using trapezoidal rule:\n";

// Iterate through each n value

for (int j = 0; j < num_tests; ++j) {

int n = n_values[j];

int n_per_process = n / size; // Number of trapezoids per process

// Start measuring time

auto start = std::chrono::high_resolution_clock::now();

// Each process calculates its own part of the integral

double local_a = a + rank * n_per_process * (b - a) / n; // Start of range for this process

double local_b = local_a + n_per_process * (b - a) / n; // End of range for this process

double local_result = trapezoidalRule(local_a, local_b, n_per_process);

// Gather the results from all processes at the root process

double global_result = 0.0;

MPI_Reduce(&local_result, &global_result, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

// End measuring time

auto end = std::chrono::high_resolution_clock::now();

std::chrono::duration<double> elapsed = end - start;


// Only the root process prints the results

if (rank == 0) {

std::cout << "Estimated integral with n = " << n << ": " << global_result << std::endl;

std::cout << "Execution time: " << elapsed.count() << " seconds" << std::endl;

MPI_Finalize();

return 0;

Output:
2. Odd-Even Transposition Sort
a) Write a serial Program which receives input as the number of elements and elements
from the user and perform the sort operation using Odd-Even Transposition sort.
Solution =>
Code:

#include <iostream>

#include <vector>

#include <mpi.h>

void oddEvenTranspositionSort(std::vector<int>& arr, int n) {

bool isSorted = false;

while (!isSorted) {

isSorted = true;

// Odd phase

for (int i = 1; i < n - 1; i += 2) {

if (arr[i] > arr[i + 1]) {

std::swap(arr[i], arr[i + 1]);

isSorted = false;

// Even phase

for (int i = 0; i < n - 1; i += 2) {

if (arr[i] > arr[i + 1]) {

std::swap(arr[i], arr[i + 1]);

isSorted = false;

}
int main(int argc, char** argv) {

MPI_Init(&argc, &argv);

int rank, size;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

std::vector<int> arr;

int n = 0;

if (rank == 0) {

// Input number of elements

std::cout << "Enter the number of elements: ";

std::cin >> n;

arr.resize(n);

// Input elements

std::cout << "Enter the elements: ";

for (int i = 0; i < n; ++i) {

std::cin >> arr[i];

// Broadcast the number of elements to all processes

MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

// Resize the array on all processes

arr.resize(n);

// Scatter the array to all processes

int chunkSize = n / size;

std::vector<int> localArr(chunkSize);
MPI_Scatter(arr.data(), chunkSize, MPI_INT, localArr.data(), chunkSize, MPI_INT, 0, MPI_COMM_WORLD);

// Sort the local array

oddEvenTranspositionSort(localArr, chunkSize);

// Gather the sorted chunks back to the root process

MPI_Gather(localArr.data(), chunkSize, MPI_INT, arr.data(), chunkSize, MPI_INT, 0, MPI_COMM_WORLD);

// Only the root process will display the sorted array

if (rank == 0) {

std::cout << "Sorted array: ";

for (int i = 0; i < n; ++i) {

std::cout << arr[i] << " ";

std::cout << std::endl;

MPI_Finalize();

return 0;

Output:
b) Parallelise program (a) using MPI.
Solution =>
Code:

#include <iostream>

#include <vector>

#include <mpi.h>

void oddEvenTranspositionSort(std::vector<int>& arr, int n) {

bool isSorted = false;

while (!isSorted) {

isSorted = true;

// Odd phase

for (int i = 1; i < n - 1; i += 2) {

if (arr[i] > arr[i + 1]) {

std::swap(arr[i], arr[i + 1]);

isSorted = false;

// Even phase

for (int i = 0; i < n - 1; i += 2) {

if (arr[i] > arr[i + 1]) {

std::swap(arr[i], arr[i + 1]);

isSorted = false;

void merge(std::vector<int>& left, std::vector<int>& right, std::vector<int>& result) {


int i = 0, j = 0, k = 0;

while (i < left.size() && j < right.size()) {

if (left[i] < right[j]) {

result[k++] = left[i++];

else {

result[k++] = right[j++];

while (i < left.size()) {

result[k++] = left[i++];

while (j < right.size()) {

result[k++] = right[j++];

int main(int argc, char** argv) {

MPI_Init(&argc, &argv);

int rank, size;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

std::vector<int> arr;

int n = 0;

if (rank == 0) {

// Input number of elements

std::cout << "Enter the number of elements: ";

std::cin >> n;
arr.resize(n);

// Input elements

std::cout << "Enter the elements: ";

for (int i = 0; i < n; ++i) {

std::cin >> arr[i];

// Broadcast the number of elements to all processes

MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

// Resize the array on all processes

arr.resize(n);

// Scatter the array to all processes

int chunkSize = n / size;

std::vector<int> localArr(chunkSize);

MPI_Scatter(arr.data(), chunkSize, MPI_INT, localArr.data(), chunkSize, MPI_INT, 0, MPI_COMM_WORLD);

// Sort the local array

oddEvenTranspositionSort(localArr, chunkSize);

// Gather sorted chunks back to the root process

std::vector<int> sortedChunks;

if (rank == 0) {

sortedChunks.resize(n);

MPI_Gather(localArr.data(), chunkSize, MPI_INT, sortedChunks.data(), chunkSize, MPI_INT, 0,


MPI_COMM_WORLD);

// Only the root process will merge and display the sorted array

if (rank == 0) {

std::vector<int> finalSortedArray;
for (int i = 0; i < size; ++i) {

int offset = i * chunkSize;

std::vector<int> leftChunk(sortedChunks.begin() + offset, sortedChunks.begin() + offset + chunkSize);

if (i == 0) {

finalSortedArray = leftChunk;

else {

std::vector<int> merged(finalSortedArray.size() + leftChunk.size());

merge(finalSortedArray, leftChunk, merged);

finalSortedArray = merged;

std::cout << "Sorted array: ";

for (int i = 0; i < n; ++i) {

std::cout << finalSortedArray[i] << " ";

std::cout << std::endl;

MPI_Finalize();

return 0;

Output:
c) Check (a) and (b) with the test case: Number of elements=N=16, A=[151, 29, 106, 213, -
14, 415, 178, 192, 246, -118, 110, 7, 11 ,10, 25, 334 ]. Comm_size=4 (Number of Processes).
Solution =>
For Serial
Code:

#include <iostream>

#include <vector>

#include <mpi.h>

void oddEvenTranspositionSort(std::vector<int>& arr, int n) {

bool isSorted = false;

while (!isSorted) {

isSorted = true;

// Odd phase

for (int i = 1; i < n - 1; i += 2) {

if (arr[i] > arr[i + 1]) {

std::swap(arr[i], arr[i + 1]);

isSorted = false;

// Even phase

for (int i = 0; i < n - 1; i += 2) {

if (arr[i] > arr[i + 1]) {

std::swap(arr[i], arr[i + 1]);

isSorted = false;

}
}

void merge(std::vector<int>& left, std::vector<int>& right, std::vector<int>& result) {

int i = 0, j = 0, k = 0;

while (i < left.size() && j < right.size()) {

if (left[i] < right[j]) {

result[k++] = left[i++];

} else {

result[k++] = right[j++];

while (i < left.size()) {

result[k++] = left[i++];

while (j < right.size()) {

result[k++] = right[j++];

int main(int argc, char** argv) {

MPI_Init(&argc, &argv);

int rank, size;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

std::vector<int> arr;

int n = 0;

// Initialize the array only in the root process

if (rank == 0) {

n = 16; // Given number of elements


arr = {151, 29, 106, 213, -14, 415, 178, 192, 246, -118, 110, 7, 11, 10, 25, 334};

// Broadcast the number of elements to all processes

MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

// Resize the array on all processes

arr.resize(n);

// Scatter the array to all processes

int chunkSize = n / size;

std::vector<int> localArr(chunkSize);

MPI_Scatter(arr.data(), chunkSize, MPI_INT, localArr.data(), chunkSize, MPI_INT, 0, MPI_COMM_WORLD);

// Sort the local array

oddEvenTranspositionSort(localArr, chunkSize);

// Gather sorted chunks back to the root process

std::vector<int> sortedChunks;

if (rank == 0) {

sortedChunks.resize(n);

MPI_Gather(localArr.data(), chunkSize, MPI_INT, sortedChunks.data(), chunkSize, MPI_INT, 0,


MPI_COMM_WORLD);

// Only the root process will merge and display the sorted array

if (rank == 0) {

std::vector<int> finalSortedArray;

for (int i = 0; i < size; ++i) {

int offset = i * chunkSize;

std::vector<int> leftChunk(sortedChunks.begin() + offset, sortedChunks.begin() + offset + chunkSize);

if (i == 0) {

finalSortedArray = leftChunk;
} else {

std::vector<int> merged(finalSortedArray.size() + leftChunk.size());

merge(finalSortedArray, leftChunk, merged);

finalSortedArray = merged;

std::cout << "Sorted array: ";

for (int i = 0; i < n; ++i) {

std::cout << finalSortedArray[i] << " ";

std::cout << std::endl;

MPI_Finalize();

return 0;

Output:

For Parallel
Code :

#include <iostream>

#include <vector>
#include <mpi.h>

void oddEvenTranspositionSort(std::vector<int>& arr, int n) {

bool isSorted = false;

while (!isSorted) {

isSorted = true;

// Odd phase

for (int i = 1; i < n - 1; i += 2) {

if (arr[i] > arr[i + 1]) {

std::swap(arr[i], arr[i + 1]);

isSorted = false;

// Even phase

for (int i = 0; i < n - 1; i += 2) {

if (arr[i] > arr[i + 1]) {

std::swap(arr[i], arr[i + 1]);

isSorted = false;

void merge(std::vector<int>& left, std::vector<int>& right, std::vector<int>& result) {

int i = 0, j = 0, k = 0;

while (i < left.size() && j < right.size()) {

if (left[i] < right[j]) {

result[k++] = left[i++];

}
else {

result[k++] = right[j++];

while (i < left.size()) {

result[k++] = left[i++];

while (j < right.size()) {

result[k++] = right[j++];

int main(int argc, char** argv) {

MPI_Init(&argc, &argv);

int rank, size;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

std::vector<int> arr;

int n = 0;

// Initialize the array only in the root process

if (rank == 0) {

n = 16; // Given number of elements

arr = { 151, 29, 106, 213, -14, 415, 178, 192,

246, -118, 110, 7, 11, 10, 25, 334 };

// Broadcast the number of elements to all processes

MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

// Resize the array on all processes


arr.resize(n);

// Scatter the array to all processes

int chunkSize = n / size;

std::vector<int> localArr(chunkSize);

MPI_Scatter(arr.data(), chunkSize, MPI_INT, localArr.data(), chunkSize, MPI_INT, 0, MPI_COMM_WORLD);

// Sort the local array

oddEvenTranspositionSort(localArr, chunkSize);

// Gather sorted chunks back to the root process

std::vector<int> sortedChunks;

if (rank == 0) {

sortedChunks.resize(n);

MPI_Gather(localArr.data(), chunkSize, MPI_INT, sortedChunks.data(), chunkSize, MPI_INT, 0,


MPI_COMM_WORLD);

// Only the root process will merge and display the sorted array

if (rank == 0) {

std::vector<int> finalSortedArray;

for (int i = 0; i < size; ++i) {

int offset = i * chunkSize;

std::vector<int> leftChunk(sortedChunks.begin() + offset, sortedChunks.begin() + offset + chunkSize);

if (i == 0) {

finalSortedArray = leftChunk;

else {

std::vector<int> merged(finalSortedArray.size() + leftChunk.size());

merge(finalSortedArray, leftChunk, merged);

finalSortedArray = merged;

}
// Display the sorted array

std::cout << "Sorted array: ";

for (int i = 0; i < n; ++i) {

std::cout << finalSortedArray[i] << " ";

std::cout << std::endl;

MPI_Finalize();

return 0;

Output:

You might also like