0% found this document useful (0 votes)
3 views13 pages

DAA Report

Uploaded by

atharvalitake24
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)
3 views13 pages

DAA Report

Uploaded by

atharvalitake24
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/ 13

PUNE INSTITUTE OF COMPUTER

TECHNOLOGY, DHANKAWADI, PUNE-43

Mini Project Report – Design and Analysis of Algorithms

‘Implement merge sort and multithreaded merge sort.’

Submitted By
Name: Atharva Litake
Roll no: 41143 Class: BE-1

Name: Mihir Deshpande


Roll no: 41150 Class: BE-1

Under the guidance of


Prof. RAJNI JADHAV

DEPARTMENT OF COMPUTER ENGINEERING


Academic Year 2024-25
Contents
1. TITLE

2. PROBLEM DEFINITION

3. LEARNING OBJECTIVES

4. LEARNING OUTCOMES

5. ABSTRACT

6. TECHNICAL DETAILS ABOUT THE PROJECT

7. GLIMPSE OF THE PROJECT

8. CONCLUSION
1. TITLE:
Implement merge sort and multithreaded merge sort. Compare
time required by both the algorithms. Also analyze the performance
of each algorithm for the best case and the worst case.

2. PROBLEM DEFINITION:

In this project, we aim to compare the performance of the traditional


merge sort algorithm with a multithreaded merge sort implementation.
The goal is to analyze their efficiency in terms of time complexity,
memory usage, and parallel processing in various input scenarios (best
case, worst case). This comparison will help determine how
multithreading can improve or affect the performance of the sorting
algorithm, especially for larger datasets.
Merge sort is a classic divide-and-conquer sorting algorithm
that splits an array into two halves, recursively sorts each half, and
then merges the two sorted halves back together. This merging
process ensures that the final result is a fully sorted array. It has a
consistent time complexity of O (n log n), making it efficient for
sorting large datasets. Merge sort is stable, meaning it maintains the
relative order of equal elements, and it works well for linked lists and
external sorting tasks. However, it requires additional memory for the
temporary arrays used during the merge process.
The primary goal of this project is to explore how the merge
sort algorithm, traditionally designed as a single-threaded, divide-
and-conquer approach, can be adapted to take advantage of
multithreading, effectively distributing the workload across multiple
processor cores. By distributing tasks over multiple threads, we aim to
determine whether the performance gains justify the complexity
introduced by multithreading, and under what conditions this
approach outperforms the conventional single-threaded version.
3. LEARNING OBJECTIVES:

● To understand the working of the merge sort algorithm.


● To implement multithreaded merge sort to utilize parallel computing.
● To compare the performance of single-threaded and multithreaded
algorithms in terms of speed and efficiency.
● To analyze the best-case and worst-case time complexity of merge sort
and observe how multithreading affects this.
● To understand the impact of threading in modern CPU architectures for
optimizing computations.

4. LEARNING OUTCOMES:

By the end of this project:


 Students will be able to implement merge sort and multithreaded
merge sort algorithms.
 Students will understand the performance trade-offs between single-
threaded and multithreaded approaches.
 Students will have hands-on experience in analyzing the time
complexity of algorithms in various scenarios.
 Students will gain knowledge about leveraging multithreading in CPU-
intensive tasks for performance improvement.

5. ABSTRACT:

The project explores and compares the efficiency of the traditional merge
sort algorithm with its multithreaded counterpart. Merge sort is a well-
known divide-and-conquer sorting algorithm, which we extend by
parallelizing the sorting tasks using threads. The comparison focuses on
time complexity, execution speed, and resource utilization under
different input cases (best and worst). Through this project, we aim to
demonstrate how multithreading can potentially reduce the execution
time for large datasets by parallelizing computational tasks.
6. TECHNICAL DETAILS ABOUT THE PROJECT

Merge Sort is a divide-and-conquer algorithm that recursively splits an array into


two halves, sorts each half, and then merges them back together in sorted order.
 Time Complexity: O (n log n) for all cases (best, average, and worst).
 Space Complexity: O(n), as it requires additional space for the temporary
arrays used during merging.

Multithreaded Merge Sort


In the multithreaded version of merge sort, we modify the algorithm to run the
sorting of each half of the array on separate threads. This allows the sorting
operations to occur in parallel, potentially reducing the overall execution time.
 Threading: In C++, we use the std::thread or std::async from the <thread> and
<future> libraries for parallelism.
 Challenges:
o Managing the overhead introduced by thread creation and
synchronization.
o Ensuring optimal CPU utilization, as too many threads can lead to
performance degradation due to context switching.
o Balancing between the work done by each thread to avoid idle threads.

Performance Analysis
 Best Case: The array is already sorted, leading to minimal reordering during
the merge step.
 Worst Case: The array is sorted in reverse order, requiring the most
comparisons and swaps during merging.

Time Measurement
In C++, the time can be measured using the <chrono> library to compare the
execution times of both the traditional and multithreaded merge sort algorithms.
We run the algorithms on arrays of varying sizes to get an accurate performance
comparison.

Hardware Considerations
Multithreaded performance depends heavily on the number of CPU cores
available. If the number of threads exceeds the available cores, performance
gains can diminish due to the overhead of thread context switching.
7. GLIMPSE OF THE PROJECT & DEPLOYMENT:

Merge Sort Code:


#include <iostream>
#include <vector>
using namespace std;

void merge(int left, int mid, int right, vector<int> &arr)


{
// Initialize pointers to left part and right part of array
int i = left;
int j = mid + 1;
int k = 0;

// Intiliaze result array for storing sorted arary


vector<int> result(right - left + 1);

// Append elements in sorted manner


while (i <= mid && j <= right)
{
if (arr[i] <= arr[j])
{
result[k] = arr[i];
i++;
}
else
{
result[k] = arr[j];
j++;
}
k++;
}

// Append remainig elements of left part of array


while (i <= mid)
{
result[k] = arr[i];
i++;
k++;
}

// Append remaining elements of right part of array


while (j <= right)
{
result[k] = arr[j];
j++;
k++;
}

// Update original array


for (int temp = 0; temp < k; temp++)
{
arr[left + temp] = result[temp];
}

return;
}
void mergeSort(int left, int right, vector<int> &arr)
{
// Base Case : Only single element is there, it is already sorted
if (left >= right)
{
return;
}

// Calculate mid index for dividing array equally in two parts left and right
int mid = left + (right - left) / 2;

// Invoke Merge Sort function for left part and rigth part of array
mergeSort(left, mid, arr);
mergeSort(mid + 1, right, arr);

// Merge sorted left part and right part of array


merge(left, mid, right, arr);

return;
}

int main()
{
// Take array size as input
int n;
cin >> n;

// Initialize array of size taken as input


vector<int> arr(n);

// Generate array elements


for (int i = 0; i < n; i++)
{
arr[i] = rand() % n;
}

// Display array
for (int i = 0; i < n; i++)
{
cout << arr[i] << endl;
}

// Create copy of array


vector<int> result = arr;

// Invoke Merge Sort function for Sorting


mergeSort(0, n - 1, result);

// Display sorted result array


for (int i = 0; i < n; i++)
{
cout << result[i] << endl;
}

return 0;
}
Multithreaded Merge Sort Code:
#include <iostream>
#include <vector>
#include <thread>
using namespace std;

void merge(int left, int mid, int right, vector<int> &arr)


{
// Initialize pointers to left part and right part of array
int i = left;
int j = mid + 1;
int k = 0;

// Intiliaze result array for storing sorted arary


vector<int> result(right - left + 1);

// Append elements in sorted manner


while (i <= mid && j <= right)
{
if (arr[i] <= arr[j])
{
result[k] = arr[i];
i++;
}
else
{
result[k] = arr[j];
j++;
}
k++;
}

// Append remainig elements of left part of array


while (i <= mid)
{
result[k] = arr[i];
i++;
k++;
}

// Append remaining elements of right part of array


while (j <= right)
{
result[k] = arr[j];
j++;
k++;
}

// Update original array


for (int temp = 0; temp < k; temp++)
{
arr[left + temp] = result[temp];
}

return;
}

const int THRESHOLD = 100; // Threshold for small subarrays

void mergeSort(int left, int right, vector<int> &arr)


{
// Base Case : Only single element is there, it is already sorted
if (left >= right)
{
return;
}

// Calculate mid index for dividing array equally in two parts left and right
int mid = left + (right - left) / 2;

if (right - left < THRESHOLD)


{
// Sequential sorting for small arrays
mergeSort(left, mid, arr);
mergeSort(mid + 1, right, arr);
}
else
{
// Create two threads for the left and right parts of the array
thread leftThread(mergeSort, left, mid, ref(arr));
thread rightThread(mergeSort, mid + 1, right, ref(arr));

// Wait for both threads to complete before merging


leftThread.join();
rightThread.join();
}

// Merge sorted left part and right part of array


merge(left, mid, right, arr);

return;
}
int main()
{
// Take array size as input
int n;
cout<<"Enter no. of elements in array: ";
cin >> n;

// Initialize array of size taken as input


vector<int> arr(n);

// Generate array elements


for (int i = 0; i < n; i++)
{
arr[i] = rand() % n;
}
cout<<"\n-----Generated Array------\n";
// Display array
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl;

// Invoke Merge Sort function for Sorting


mergeSort(0, n - 1, arr);

// Display sorted result array


cout<<"\n-----Sorted Array------\n";
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl;

return 0;
}
8. CONCLUSION

The project demonstrates that multithreading can significantly improve the


performance of the merge sort algorithm on large datasets, especially when sufficient
CPU cores are available. However, for smaller datasets, the overhead of thread
management might reduce the performance benefits. The project highlights the
importance of choosing the right algorithm and optimizing it based on the available
hardware, demonstrating that parallel computing can enhance the efficiency of
traditional algorithms.

You might also like