Tải bản đầy đủ (.docx) (28 trang)

Đánh giá hiệu năng một số thuật toán sắp xếp sử dụng OpenMP

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (576.13 KB, 28 trang )

TRƯỜNG ĐẠI HỌC CÔNG NGHIỆP HÀ NỘI
KHOA CÔNG NGHỆ THÔNG TIN
------------------

BÁO CÁO BÀI TẬP LỚN
Học Phần: TÍNH TỐN HIỆU NĂNG CAO (HPC)
ĐỀ TÀI: Đánh giá hiệu năng một số thuật toán sắp
xếp sử dụng OpenMP

Giảng viên hướng dẫn

: TS Hà Mạnh Đào

Lớp

: 20231IT6069001

Nhóm thực hiện

: Nhóm 9

1. Nguyễn Quang Anh - 2021600416
2. Đỗ Mạnh Cường - 2021600593
3. Nguyễn Hồng Quân – 2021600807

Hà Nội, 2023


1

LỜI MỞ ĐẦU


Trong thời đại ngày nay, với sự bùng nổ của cơng nghệ thơng tin, các
máy tính đa nhân, đa lõi đã mở ra một hướng phát triển mới về mặt tính tốn.
Mọi người đã khơng cịn xa lạ với những máy tính mà ngày nay đều được
trang bị những bộ xử lý có khả năng xử lý song song cao giúp tăng cường
hiệu năng tính tốn và giảm thời gian cho các tác vụ phức tạp.
Tuy nhiên, để khai thác được hết hiệu năng tính tốn mà bộ xử lý đa
nhân, đa lõi mang lại thì khơng cịn cách nào khác là thay vì lập trình, tính
tốn tuần tự chuyển sang lập trình, tính tốn song song.
Các cơng cụ hỗ trợ lập trình, tính tốn song song nổi bật có thể kể đến
như: Thư viện MPI (Message Passing Interface), CUDA (Compute Unified
Device Architecture), OpenCL (Open Computing Language), OpenMP (Open
Multi – Processing). Trong bài báo cáo này, chúng em sẽ tìm hiểu, áp dụng
lập trình, tính tốn song song trên cơ sở sử dụng thư viện OpenMP trong đề
tài “Đánh giá hiệu năng một số thuật toán sắp xếp sử dụng OpenMP”. Ngoài
lời mở đầu, mục lục, danh mục hình ảnh và tài liệu tham khảo thì nội dung
của bài báo cáo bao gồm 3 chương:
 Chương 1: Kiến thức cơ sở
 Chương 2: Mô tả chi tiết thuật toán
 Chương 3: Đánh giá hiệu năng


2

MỤC LỤC
DANH MỤC HÌNH ẢNH...................................................................................4
Chương 1. Kiến thức cơ sở.................................................................................5
1.1 Tính tốn hiệu năng cao là gì?..............................................................5
1.2 Lập trình, tính tốn song song là gì?.....................................................5
1.3 So sánh lập trình, tính tốn tuần tự và lập trình, tính tốn song song...5
1.4 Mơ hình máy tính tính tốn song song..................................................6

1.4.1

Máy tính SISD..............................................................................6

1.4.2

Máy tính SIMD.............................................................................6

1.4.3

Máy tính MISD.............................................................................7

1.4.4

Máy tính MIMD...........................................................................8

1.5 Các mơ hình lập trình song song...........................................................9
1.6 Kỹ thuật thiết kế giải thuật song song...................................................9
1.7 Giới thiệu OpenMP...............................................................................9
1.7.1

Giới thiệu......................................................................................9

1.7.2

Mục đích.....................................................................................10

Chương 2. Mơ tả chi tiết thuật toán.................................................................11
2.1 Giới thiệu một số thuật toán sắp xếp...................................................11
2.1.1


Thuật toán merge sort.................................................................11

2.1.2

Thuật toán insertion sort.............................................................11

2.1.3

Thuật toán selection sort.............................................................11

2.2 Triển khai chi tiết................................................................................12
2.2.1

Thuật tốn merge sort.................................................................12

2.2.1.1

Chương trình tuần tự............................................................12

2.2.1.2

Chương trình song song.......................................................14

2.2.2

Thuật tốn insertion sort.............................................................15

2.2.2.1


Chương trình tuần tự............................................................15


3
2.2.2.2
2.2.3

Chương trình song song.......................................................16

Thuật tốn slection sort...............................................................17

2.2.3.1

Chương trình tuần tự............................................................17

2.2.3.2

Chương trình song song.......................................................18

Chương 3. Đánh giá hiệu năng.........................................................................20
3.1 Đánh giá hiệu năng lý thuyết...............................................................20
3.1.1

Thuật toán merge sort.................................................................20

3.1.2

Thuật toán insertion sort.............................................................20

3.1.3


Thuậtt toán selection sort.........................................................21

3.2 Đánh giá hiệu năng thực tiễn...............................................................21
3.2.1

Thuật toán merge sort.................................................................21

3.2.1.1

Chương trình tuần tự............................................................21

3.2.1.2

Chương trình song song.......................................................22

3.2.1.3

Đánh giá...............................................................................22

3.2.2

Thuật tốn insertion sort.............................................................23

3.2.2.1

Chương trình tuần tự............................................................23

3.2.2.2


Chương trình song song.......................................................23

3.2.2.3

Đánh giá...............................................................................24

3.2.3

Thuật tốn selection sort.............................................................25

3.2.3.1

Chương trình tuần tự............................................................25

3.2.3.2

Chương trình song song.......................................................25

3.2.3.3

Đánh giá...............................................................................25

TÀI LIỆU THAM KHẢO................................................................................27


4

DANH MỤC HÌNH ẢNH
Hình 1.1 Cấu trúc máy tính SISD.....................................................................6
Hình 1.2 Cấu trúc máy tính SIMD....................................................................7

Hình 1.3 Cấu trúc máy tính MISD....................................................................8
Hình 1.4 Cấu trúc máy tính MIMD...................................................................8
Hình 3.1 Kết quả chạy chương trình tuần tự merge sort với 100 phần tử.......21
Hình 3.2 Kết quả chạy chương trình song song merge sort với 100 phần tử..22
Hình 3.3 Kết quả chạy chương trình tuần tự insertion sort với 100 phần tử...23
Hình 3.4 Kết quả chạy chương trình song song insertion sort với 100 phần tử
.........................................................................................................................23
Hình 3.5 Kết quả chạy chương trình tuần tự selection sort với 100 phần tử...25
Hình 3.6 Kết quả chạy chương trình song song selection sort với 100 phần tử
.........................................................................................................................25


5

Chương 1. Kiến thức cơ sở
1.1 Tính tốn hiệu năng cao là gì?
Tính tốn hiệu năng cao (High-Performance Computing - HPC) là một
lĩnh vực rộng lớn trong công nghệ thông tin và khoa học máy tính, tập trung
vào việc tối ưu hóa hiệu suất tính tốn của hệ thống máy tính để đáp ứng các
u cầu tính tốn phức tạp và cơng việc lớn.
1.2 Lập trình, tính tốn song song là gì?
Tính tốn song song là sự thực hiện một cách đồng thời hai hoặc nhiều
phép tốn, cơng việc vào một thời điểm, được thực hiện bởi các bộ xử lý khác
nhau.
1.3 So sánh lập trình, tính tốn tuần tự và lập trình, tính tốn song song
Lập trình, tính tốn tuần tự
- Chương trình ứng dụng chạy trên
bộ xử lý đơn.
- Các chỉ thị lệnh được bộ vi xử lý
(CPU) thực hiện một cách lần lượt,

tuần tự.
- Mỗi chỉ thị lệnh chỉ được thực hiện
trên duy nhất một thành phần dữ
liệu.
- Lập trình viên chỉ cần đảm bảo viết
đúng mã lệnh theo giải thuật là
chương trình có thể biên dịch, chạy
và cho ra kết quả.

Lập trình, tính tốn song song
- Chương trình ứng dụng chạy trên
hai hoặc nhiều bộ xử lý.
- Các chỉ lệnh được các bộ vi xử lý
thực hiện một cách song song, đồng
thời.
- Mỗi chỉ thị lệnh có thể được thao
tác trên hai hoặc nhiều thành phần
dữ liệu khác nhau.
- Lập trình viên khơng chỉ phải viết
đúng mã lệnh theo giải thuật mà còn
phải chỉ ra trong chương trình đoạn
mã nào được thực hiện song song,
đồng thời.
- Thường được áp dụng đối với các - Thường được áp dụng đối với các
bài tốn có dữ liệu nhỏ, độ phức tạp bài tốn có lượng dữ liệu lớn, độ
ít hoặc bình thường và có thời gian phức tạp cao và thời gian ngắn.
cho phép.


6

1.4 Mơ hình máy tính tính tốn song song
Cả hai máy tính tuần tự và song song đều hoạt động trên một tập hợp
(dịng) lệnh được gọi là thuật tốn. Tập hợp các lệnh (thuật tốn) này hướng
dẫn máy tính về những gì nó phải làm trong mỗi bước.
Tùy thuộc vào luồng lệnh và luồng dữ liệu, máy tính có thể được phân
thành bốn loại:
 Máy tính luồng lệnh đơn, luồng dữ liệu đơn (SISD)
 Máy tính một luồng lệnh, nhiều luồng dữ liệu (SIMD)
 Máy tính nhiều luồng lệnh, một luồng dữ liệu (MISD)
 Máy tính nhiều luồng lệnh, nhiều luồng dữ liệu (MIMD)
1.4.1 Máy tính SISD
Máy tính SISD chứa một control unit, một processing unit và một
memory unit.

Hình 1.1 Cấu trúc máy tính SISD

Trong loại máy tính này, bộ xử lý nhận một luồng lệnh từ bộ điều khiển
và hoạt động trên một luồng dữ liệu từ bộ nhớ. Trong q trình tính tốn, ở
mỗi bước, bộ xử lý nhận một lệnh từ bộ điều khiển và hoạt động trên một dữ
liệu duy nhất nhận được từ bộ nhớ.
1.4.2 Máy tính SIMD
Máy tính SIMD chứa một control unit, nhiều processing units và
một shared memory or interconnection network.


7

Hình 1.2 Cấu trúc máy tính SIMD

Tại đây, một đơn vị điều khiển duy nhất sẽ gửi hướng dẫn đến tất cả

các đơn vị xử lý. Trong q trình tính toán, ở mỗi bước, tất cả các bộ xử lý
nhận được một bộ lệnh duy nhất từ bộ điều khiển và hoạt động trên bộ dữ liệu
khác nhau từ bộ nhớ.
Mỗi đơn vị xử lý có bộ nhớ cục bộ riêng để lưu trữ cả dữ liệu và lệnh.
Trong máy tính SIMD, các bộ xử lý cần giao tiếp với nhau. Điều này được
thực hiện bởi shared memory hoặc bằng cách interconnection network.
Trong khi một số bộ xử lý thực thi một tập hợp các lệnh, các bộ xử lý
còn lại sẽ chờ tập các lệnh tiếp theo của chúng. Hướng dẫn từ bộ phận điều
khiển quyết định bộ xử lý nào sẽ là active (thực hiện hướng dẫn) hoặc
inactive (chờ hướng dẫn tiếp theo).
1.4.3 Máy tính MISD
Như tên cho thấy, máy tính MISD chứa nhiều control units, nhiều
processing units và một common memory unit.


8

Hình 1.3 Cấu trúc máy tính MISD

Ở đây, mỗi bộ xử lý có bộ điều khiển riêng và chúng chia sẻ một bộ
nhớ chung. Tất cả các bộ xử lý đều nhận được hướng dẫn riêng lẻ từ bộ điều
khiển của riêng họ và chúng hoạt động trên một luồng dữ liệu duy nhất theo
hướng dẫn mà chúng đã nhận được từ bộ điều khiển tương ứng. Bộ xử lý này
hoạt động đồng thời.
1.4.4 Máy tính MIMD
Máy tính MIMD có nhiều control units, nhiều processing units và một
shared memory hoặc là interconnection network.

Hình 1.4 Cấu trúc máy tính MIMD


Ở đây, mỗi bộ xử lý có đơn vị điều khiển riêng, bộ nhớ cục bộ, đơn vị
số học và logic. Chúng nhận được các bộ hướng dẫn khác nhau từ các đơn vị
điều khiển tương ứng và hoạt động trên các bộ dữ liệu khác nhau.


9
Máy tính MIMD chia sẻ bộ nhớ chung được gọi là multiprocessors.
1.5 Các mơ hình lập trình song song

Một số mơ hình lập trình song song thường được sử dụng:





Mơ hình dùng chung bộ nhớ (Shared memory)
Mơ hình luồng (Thread)
Mơ hình truyền thơng điệp (Message passing)
Mơ hình song song dữ liệu (Data parallel)

1.6 Kỹ thuật thiết kế giải thuật song song

Lựa chọn một kỹ thuật thiết kế thích hợp cho một thuật tốn song
song là nhiệm vụ khó khăn và quan trọng nhất. Hầu hết các vấn đề lập
trình song song có thể có nhiều hơn một giải pháp. Trong chương này,
chúng ta sẽ thảo luận về các kỹ thuật thiết kế sau đây cho các thuật toán
song song  Phân chia và chinh phục
 Phương pháp tham lam
 Lập trình năng động
 Thuật tốn bẻ khóa (Backtracking)

 Chi nhánh và ràng buộc
 Lập trình tuyến tính
1.7 Giới thiệu OpenMP
1.7.1 Giới thiệu
OpenMP (Open Multi - Processing) là một giao điện lập trình ứng dụng
(API) được sử dụng để điều khiến các luồng (Thread) dựa trên cầu trúc chia
sẻ bộ nhớ chung. Các thành phần của OpenMP gồm:
 Các chỉ thị biên dịch
 Thư viện runtime
 Các biến môi trường
OpenMP là một thư viện, giúp người lập trình đơn giản và linh hoạt để
phát triển chương trình song song chạy trên máy tính hỗ trợ nhiều bộ xử lý.
1.7.2 Mục đích
OpenMP ra đời với mục tiêu cung cấp một chuẩn chung cho rất nhiều
kiến trúc và nền tăng phần cứng. Nó là thư viện mã nguồn mở cung cấp rất


10
nhiều các hàm, các chỉ thị giúp cho người lập trình linh động và dễ dàng phát
triển ứng dụng song song của mình.


11

Chương 2. Mơ tả chi tiết thuật tốn
2.1 Giới thiệu một số thuật toán sắp xếp
2.1.1 Thuật toán merge sort
Thuật toán Merge Sort là một thuật toán sắp xếp đệ quy dựa trên
nguyên tắc "chia để trị". Nó chia một mảng không được sắp xếp thành các
nửa mảng nhỏ hơn, sắp xếp từng nửa mảng đó và sau đó trộn các nửa mảng

đã sắp xếp lại với nhau để tạo thành một mảng đã được sắp xếp.
Trong tính tốn song song, chúng ta có thể áp dụng thuật tốn Merge
Sort bằng cách sử dụng phân chia và trộn song song. Ý tưởng chính là chia
mảng ban đầu thành các phần nhỏ hơn và sắp xếp chúng đồng thời trên nhiều
luồng (thread) hoặc q trình (process). Sau đó, ta kết hợp các phần đã sắp
xếp thành mảng con đã sắp xếp và tiếp tục quá trình này cho đến khi tạo ra
một mảng đã sắp xếp hồn chỉnh.
2.1.2 Thuật tốn insertion sort
Insertion sort là một thuật toán sắp xếp đơn giản nhưng hiệu quả, được
sử dụng để sắp xếp một danh sách các phần tử. Thuật toán này hoạt động
bằng cách chia danh sách thành hai phần: một phần đã được sắp xếp và một
phần chưa được sắp xếp. Ban đầu, phần đã được sắp xếp chỉ chứa một phần tử
đầu tiên từ danh sách ban đầu. Sau đó, thuật tốn chọn lần lượt các phần tử từ
phần chưa được sắp xếp và chèn chúng vào đúng vị trí trong phần đã được
sắp xếp.
Insertion sort có độ phức tạp thời gian trung bình là O(n^2), nghĩa là
thời gian thực hiện tăng theo bình phương số lượng phần tử trong danh sách.
Tuy nhiên, với danh sách nhỏ hoặc gần như đã được sắp xếp, thuật tốn này
có thể thực hiện nhanh chóng.
2.1.3 Thuật toán selection sort
Thuật toán Selection Sort là một thuật tốn sắp xếp đơn giản và dễ
hiểu. Nó hoạt động bằng cách tìm kiếm phần tử nhỏ nhất trong mảng và đổi
chỗ nó với phần tử đầu tiên. Sau đó, nó tìm kiếm phần tử nhỏ nhất trong phần
cịn lại của mảng và đổi chỗ nó với phần tử thứ hai, và tiếp tục như vậy cho
đến khi toàn bộ mảng đã được sắp xếp.
Selection Sort không phải là một trong những thuật toán sắp xếp hiệu
suất tốt nhất. Đối với một mảng có n phần tử, thuật tốn này luôn phải thực


12

hiện n-1 lượt so sánh và có thể cần thực hiện tối đa n-1 hoặc ít nhất 0 lượt
hốn đổi. Vì vậy, độ phức tạp thời gian của Selection Sort là O(n^2), làm cho
nó khơng phù hợp cho các dãy số lớn.
2.2 Triển khai chi tiết
2.2.1 Thuật toán merge sort
2.2.1.1
#include
#include
#include
#include

Chương trình tuần tựng trình tuần tựn tự
<iostream>
<cstdlib>
<ctime>
<chrono>

void merge(int arr[], int l, int m, int r);
void mergeSort(int arr[], int l, int r);
int main()
{
int num, i;
std::cout << "Nhap so phan tu la: ";
std::cin >> num;
auto start = std::chrono::high_resolution_clock::now();
int* arr = new int[num];
srand(time(NULL));
std::cout << "Array elements:\n";
for (i = 0; i < num; i++) {
arr[i] = rand() % (2 * num) + 1;

std::cout << arr[i] << " ";
}
mergeSort(arr, 0, num - 1);
std::cout << "\nSorted elements:\n";
for (i = 0; i < num; i++) {
std::cout << arr[i] << " ";
}
delete[] arr;
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = end - start;
double seconds = elapsed.count();
std::cout << "\nElapsed time: " << seconds << " seconds" <<
return 0;
}

std::endl;


13

void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
int* L = new int[n1];
int* R = new int[n2];
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)

R[j] = arr[m + 1 + j];
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
}
else {
arr[k] = R[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
delete[] L;
delete[] R;
}
void mergeSort(int arr[], int l, int r)
{

if (l < r) {
int m = l + (r - l) / 2;
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
}
}

merge(arr, l, m, r);


14

2.2.1.2
#include
#include
#include
#include

Chương trình tuần tựng trình song song
<iostream>
<cstdlib>
<ctime>
<omp.h>

void mergesort(int a[], int i, int j);
void merge(int a[], int i1, int j1, int i2, int j2);
int main()
{
int a[100000];
int num, i;

std::cout << "Nhap so phan tu cua day: ";
std::cin >> num;
float st = clock();
std::cout << "Enter the elements:\n";
srand(time(NULL));
for (i = 0; i < num; i++) {
a[i] = rand() % 100; // Generate a random number between 0 and 99
}
mergesort(a, 0, num - 1);
std::cout << "\nSorted array:\n";
for (i = 0; i < num; i++) {
std::cout << a[i] << " ";
}
float end = clock();
std::cout << "Thoi gian thuc hien la " << (end - st) / CLOCKS_PER_SEC;
return 0;
}
void mergesort(int a[], int i, int j)
{
int mid;
if (i < j)
{
mid = (i + j) / 2;
#pragma omp parallel sections
{
#pragma omp section
{
mergesort(a, i, mid); //left recursion
}
#pragma omp section

{
mergesort(a, mid + 1, j); //right recursion
}
}
}
}

merge(a, i, mid, mid + 1, j); //merging of two sorted sub-arrays


15

void merge(int a[], int i1, int j1, int i2, int j2)
{
int n1 = j1 - i1 + 1;
int n2 = j2 - i2 + 1;
int* temp = new int[n1 + n2];
int i = i1; // beginning of the first list
int j = i2; // beginning of the second list
int k = 0;
while (i <= j1 && j <= j2) // while elements in both lists
{
if (a[i] < a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while (i <= j1) // copy remaining elements of the first list
temp[k++] = a[i++];
while (j <= j2) // copy remaining elements of the second list

temp[k++] = a[j++];
for (i = i1, k = 0; i <= j2; i++, k++)
a[i] = temp[k];
delete[] temp;
}

2.2.2 Thuật tốn insertion sort
2.2.2.1

Chương trình tuần tựng trình tuần tựn tự

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}

cout << endl;
}
int main() {
srand(time(0));
int n;
cout << "n = ";
cin >> n;
int arr[100000];
cout << "Day ban dau: ";
for (int i = 0; i < n; i++) {
arr[i] = rand() % 100;
cout << arr[i] << " ";
}
cout << endl;
insertionSort(arr, n);
cout << "Day sau khi sap xep: ";
printArray(arr, n);
return 0;
}


16

2.2.2.2
#include
#include
#include
#include

Chương trình tuần tựng trình song song

<iostream>
<cstdlib>
<ctime>
<omp.h>

using namespace std;
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int main() {
srand(time(0));
int n;
cout << "n = ";
cin >> n;
int arr[100000];
cout << "Day ban dau: ";

for (int i = 0; i < n; i++) {
arr[i] = rand() % 100;
cout << arr[i] << " ";
}
cout << endl;
#pragma omp parallel for
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
cout << "Day sau khi sap xep: ";
printArray(arr, n);
return 0;
}

#pragma omp parallel for được sử dụng để song song hóa vịng lặp for
trong thuật tốn sắp xếp chèn. Mỗi tiểu trình sẽ được giao phó một phần của


17
dãy số để sắp xếp. Vì vậy, các phần tử của dãy số sẽ được sắp xếp đồng thời
bởi nhiều tiểu trình, giúp tăng tốc độ thực thi.
2.2.3 Thuật tốn slection sort
2.2.3.1


Chương trình tuần tựng trình tuần tựn tự

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void swap(int* a, int* b);
void selectionsort(int arr[], int n);
void printArray(int arr[], int size);
int main() {
int n;
printf("Enter the number of elements (n): ");
scanf_s("%d", &n);
if (n <= 0 || n > 100000) {
printf("Invalid number of elements. Exiting...\n");
return 1;
}
clock_t start_time = clock();
int* arr = (int*)malloc(n * sizeof(int));
srand(time(NULL));
for (int i = 0; i < n; i++) {
arr[i] = rand() % 10000 + 1;
}
printf(("\nArray before sorting:\n");
printArray(arr, n);
selectionsort(arr, n);
printf("\nArray after sorting:\n");
printArray(arr, n);
clock_t end_time = clock();
double run_time = ((double)(end_time - start_time)) / CLOCKS_PER_SEC;
printf("\nExecution time: %lf seconds\n", run_time);

free(arr);
return 0;
}
void swap(int* a, int* b) {
int t = *a;
*a = *b;
*b = t;
}
void selectionsort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
int min_index = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[min_index]) {
min_index = j;
}
}
swap(&arr[min_index], &arr[i]);
}
}
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");


18
2.2.3.2
#include
#include

#include
#include

Chương trình tuần tựng trình song song
<stdio.h>
<stdlib.h>
<time.h>
<omp.h>

void swap(int* a, int* b);
void selectionsort_parallel(int arr[], int n);
void printArray(int arr[], int size);
int main() {
int n;
printf("Enter the number of elements (n): ");
scanf_s("%d", &n);
if (n <= 0 || n > 100000) {
printf("Invalid number of elements. Exiting...\n");
return 1;
}
double start_time = omp_get_wtime();
int* arr = (int*)malloc(n * sizeof(int));
srand(time(NULL));
for (int i = 0; i < n; i++) {
arr[i] = rand() % 10000 + 1;
}
printf(("\nArray before sorting:\n");
printArray(arr, n);
selectionsort_parallel(arr, n);
printf("\nArray after sorting:\n");

printArray(arr, n);
double run_time = omp_get_wtime() - start_time;
printf("\nExecution time: %lf seconds\n", run_time);
free(arr);
return 0;
}
void swap(int* a, int* b) {
int t = *a;
*a = *b;
*b = t;
}
void selectionsort_parallel(int arr[], int n) {
int i, j;
#pragma omp parallel for private(i)
for (i = 0; i < n - 1; i++) {
int min_index = i;
#pragma omp parallel for private(j)
for (j = i + 1; j < n; j++) {
if (arr[j] < arr[min_index]) {
min_index = j;
}
}
#pragma omp critical
{
swap(&arr[min_index], &arr[i]);
}
}
}
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {

printf("%d ", arr[i]);
}
printf("\n");
}


19
#pragma omp parallel for private(i): Chỉ định một vòng lặp được thực
hiện song song bởi các luồng. Biến i được xác định là riêng tư cho mỗi luồng.
#pragma omp parallel for private(j): Tương tự như trên, nhưng áp dụng
cho vòng lặp trong.
#pragma omp critical: Xác định một khu vực chỉ có một luồng có thể
thực hiện tại một thời điểm. Trong trường hợp này, nó được sử dụng để bảo
vệ việc thay đổi của biến chia sẻ min_index. Một luồng sẽ thực hiện việc cập
nhật, và các luồng khác phải chờ đến khi luồng đó hồn thành.



×