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

Áp dụng tính toán song song vào giải quyết bài toán tìm đi ngắn nhất xuất phát từ một đỉnh sử dụng giải thuật dijkstra

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 (255.29 KB, 13 trang )

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
  

Bài tập lớn Lập trình song song
Đề tài : Áp dụng tính toán song song vào giải quyết bài toán tìm đi ngắn nhất
xuất phát từ một đỉnh sử dụng giải thuật Dijkstra.
Giảng viên hướng dẫn : Ths. Nguyễn Tiến Dũng
Nhóm 2

Lớp : Hệ Thống Thông Tin K53
Hà Nội tháng 11/2011
1


Mục lục
Tổng quan về mô hình lập trình song song OpenMP
1- Giới thiệu về mô hình OpenMP
2- Mô hình lập trình song song OpenMP
3- Một số chỉ thị trong OpenMP
4- Một số mệnh đề thường gặp trong OpenMP
5- Thư viện và các biến môi trường
Bài toán tìm đường đi ngắn nhất
1- Các khái niệm mở đầu
2- Bài toán đường đi ngắn nhất xuất phát từ một đỉnh
Giải thuật Dijkstra
1- Thuật toán Dijkstra
2- Tính đúng đắn của thuật toán Dijkstra
3- Độ phức tạp của thuật toán Dijkstra

I-



II-

III-

Kết quả thực nghiệm
1- Cài đặt bằng lập trình tuần tự
2- Cài đặt bằng lập trình song song
3- Kết luận.

IV-

I-

Tổng quan về mô hình lập trình song song OpenMP
1- Giới thiệu về mô hình OpenMP
a- OpenMP là gì?
2


Theo Wikipedia:
OpenMP- Open Multi-Processing là một giao diện lập trình ứng dụng API (Application
programming interface) hỗ trợ đa nền tảng dựa trên cấu trúc chia sẻ bộ nhớ chung, đa
ngôn ngữ lập trình C, C++, Fortran và hầu hết các bộ kiến trúc vi xử lý và hệ điều hành
Linux, Unix, Mac OS X, nền tảng Microsoft Windows.
Nó bao gồm :
• Các chỉ thị biên dịch (Compiler directives)
• Các thư viện Runtime (Library rountines)
• Các biến môi trường (Environment variables)


b- Lịch sử OpenMP

OpenMP Architecture Review Board(ARB) được công bố như một giao diện lập trình
ứng dụng đầu tiên, phiên bản 1.0 ra đời vào tháng 10 năm 1997 cho Fortran. Tháng 10
năm sau đó là phiên bản cho C/C++.
Năm 2000 phiên bản 2.0 cho Fortran và năm 2002 là phiên bản 2.0 cho C/C++.
Năm 2005 phiên bản 2.5 cho C/C++/Fortran ra đời.
Tháng 5-2008 phiên bản 3.0 ra đời bao gồm thêm nhiều tính năng mới các khái niệm về
task và nhiện vụ của task.

3


2- Mô hình lập trình song song OpenMP

OpenMP sử dụng mô hình Fork-Join để thực thi song song
Trong mô hình này tất cả các chương trình song song đều bắt đầu với việc xử lý đơn
bởi một luồng chủ (master thread). Luồng chủ này sẽ thực thi một cách tuần tự cho tới
khi bắt gặp vùng song song (parallel region) đầu tiên .
FORK: Có nghĩa là luồng chủ sau đó sẽ tạo ra một tập các luồng song song. Và sau đó
đoạn mã trong vùng song song được thực thi song song bởi tập luồng song song vừa
tạo ra
JOIN: Khi mà tập luồng song song đã hoàn thành đoạn mã trong vùng song song
chúng sẽ được đồng bộ và kết thúc rồi sau đó công việc lại được thực hiện bởi
luồngchủ.

3- Một số chỉ thị trong OpenMP
3.1 Khuôn dạng chỉ thị

Chỉ thị trong OpenMP được cho dưới dạng sau

# pragma omp directive-name [clause...] newline
• # pragma omp: Yêu cầu bắt buộc đối với mọi chỉ thị OpenMP C/C++
• directive-name: Là tên của chỉ thị phải xuất hiện sau #pragma omp và đứng
trước bất kì mệnh đề nào
• [clause...]: Các mệnh đề này không bắt buộc trong chỉ thị

4


• newline : Yêu cầu bắt buộc với mỗi chỉ thị nó là tập mã lệnh nằm trong khối
cấu trúc được bao bọc bởi chỉ thị
Ví dụ:
#pragma omp parallel default ( shared ) private (beta,pi)
3.2 Phạm vi của chỉ thị:
• Phạm vi tĩnh ( Static Extent )
Đó là những đoạn mã nguyên bản trong phạm vi từ đầu đến cuối khối cấu trúc
cho sau mỗi chỉ thị. Phạm vi tĩnh của chỉ thị không mở rộng đến các thủ tục và các tệp
chứa mã.
• Chỉ thị đơn độc (Orphaned Directive)
Chỉ thị đơn độc là chỉ thị xuất hiện độc lập với chỉ thị khác. Nó tồn tại ở ngoài
phạm vi tĩnh của chỉ thị khác. Chỉ thị đơn độc mở rộng với các thử tục và các tệp mã
nguồn
• Phạm vi động (Dynamic Extent)
Phạm vi động của chỉ thị bao gồm phạm vi tĩnh của của chỉ thị và phạm vi của các chỉ
thị mồ côi
OpenMP có rất nhiều chỉ thị như: atomic, barrier, critical, flush, for, master, ordered,
parallel, section, single, threadprivate.
Các cấu trúc thường gặp :
• Cấu trúc chia sẻ
• Cấu trúc đồng bộ

Trong phạm vi bài tập lớn này em xin trình bày các chỉ thị đã dùng:
3.3 Cấu trúc chia sẻ
3.3.1 Chỉ thị do/for
• Mệnh đề schedule
#pragma omp for schedule(static,t)
T= so dinh cua do thi / so luong.
For(i=1;i{
Printf(“\n nhap du lieu o luong ”)
C[i][j]= ran();
}
#pragma omp for schedule(dynamic,t)
T là biến chunk_size.
• Mệnh đề Ordered
• Mệnh đề Nowait
Với mệnh đề này thì các luồng không cần đồng bộ tại điểm cuối cùng của vòng lặp
song song. Các luồng sẽ xử lý trực tiếp đoạn mã lệnh cho tiếp sau vòng lặp.
3.3.2 Chỉ thị sections
• Chỉ thị này dùng để chỉ ra các phần mã trong vùng song song chia cho các
luồng thực hiện. trong phạm vi của chỉ thị sections có các chỉ chị section . mỗi một
section sẽ được thực hiện bởi các luồng khác nhau. Khuôn dạng của chỉ thị
sections.
3.3.3 Chỉ thị Single
Chỉ thị single chỉ ra rằng đoạn mã bao quanh chỉ thị chỉ được thực hiện bởi một
luồng trong tập các luồng.Nếu không có mệnh đề Nowait được khai báo thì các
luồng khác (các luồng không thực thi đoạn mã Single ) sẽ phải đợi cho đến khi
5


luồng thực thi đoạn mã trong chỉ thị kết thúc mới được thực hiện các công việc

khác ngoài chỉ thị
Trong chỉ thị Single chỉ có hai mệnh đề là Private và firstprivate
Khuôn dạng chỉ thị Single
#pragma omp single [clauses]
{
structured-block
}
Chỉ thị Single cho phép bạn chỉ định một phần của đoạn mã được thực hiện trên một
luồng duy nhất , không nhất thiết là luồng master.
Các clause có thể là một trong số sau :
• Private
• Firstprivate
• Copyprivate
• Nowait
Các luồng khác mà không thực thi đoạn mã trong chỉ thị SINGLE sẽ phải đợi
đến khi luồng thực thi đoạn mã trong chỉ thị kết thúc mới được thực hiện các công
việc ngoài chỉ thị SINGLE nếu không có mệnh đề NOWAIT được đưa ra. Lưu ý trong chỉ
thị SINGLE chỉ có hai mệnh đề là private và firstprivate .
.

3.4 Cấu trúc đồng bộ dữ liệu
3.4.1 Chỉ thị master
Trong chỉ thị master đoạn mã bao quanh chỉ thị chỉ được thực hiện bởi luồng chủ
trong tập các luồng.
Trong chỉ thị này không có bất cứ mệnh đề nào và các luồng khác không cần chờ
đến khi luồng chủ thực hiện xong công việc cho bởi chỉ thị master mới được thực
hiện công việc của mình.
3.4.2 Chỉ thị critical
với chỉ thị Critical thì vùng mã được cho bởi chỉ thị tại một thời điểm chỉ được thực
hiện tại một luồng.

Nếu một luồng nào đó đang thực hiện công việc cho bởi chỉ thị mà có một luồng
khác cố gắng đòi thực hiện công việc đó thì nó sẽ bị khóa cho đếnkhi luồng kia thực
hiện xong công việc đó.
có thể tồn tại nhiều chỉ thị critical với các tên khác nhau trong cùng một vùng song
song.
3.4.3 Chỉ thị Barrier
Chỉ thị này dùng để đồng bộ tất cả các luông trong tập các luồng . khi bắt gặp chỉ
thị Barrier thì mỗi luồng sẽ chờ tại thời điểm đó(thời điểm bắt gặp chỉ thị Barrier)
cho đến khi tất cả các luồng còn lại bắt gặp chỉ thị Barrier. Sau đó các luồng sẽ
cùng thực thi chỉ thị barrier.
Khuôn dạng chỉ thị Barrier :
#pragma omp barrier new-line
6


3.4.4 Chỉ thị Atomic
Trong chỉ thị Atomic các địa chỉ vùng nhớ được cập nhập một cách nguyên tố hơn
là việc dùng nhiều luồng cố gắng ghi lên nó.
#pragma omp atomic newline
statemens_expression
Chỉ thị này chỉ áp dụng trực tiếp một trong các lệnh sau
x binop = expr
x++
++x
x- --x
x là biến mở rộng
expr là một biểu thức mở rộng không tham chiếu đến x
binop là một trong +,*,- , / , & , ^ , | , ≥ or ≤
Chú ý rằng chỉ có phép nạp và lưu trữ biến x mới là nguyên tố .
4- Một số mệnh đề trong OpenMP

Trong OpenMP sử dụng các mện đề sau
- Mệnh đề Private
- Mệnh đề Firstprivate
- Mệnh đề Lastprivate
- Mệnh đề Shared
- Mệnh đề Default
- Mênh đề Reduction
- Mệnh đề Copyin
5- Thư viện và các biến môi trường
5.1 Thư viện Runtime
OpenMP cung cấp một thư viện với rất nhiều các hàm chức năng bao gồm các truy
vấn liên quan đến số lượng và chỉ số các luồng, thiết lập số lượng các luồng sử dụng,
semaphores, và các hàm thiết lập môi trường thực thi. Trong C/C++ để có thể sử dụng
các hàm trên thì phải đính vào file thư viện omp.h.
• OMP_SET_NUM_THREADS
• OMP_GET_NUM_THREADS
• OMP_GET_MAX_THREADS
• OMP_GET_THREAD_NUM
• OMP_GET_NUM_PROCS
• OMP_IN_PARALLEL
• OMP_SET_DYNAMIC
• OMP_GET_DYNAMIC
• OMP_SET_NESTED
• OMP_GET_NESTED
• OMP_INIT_LOCK
• OMP_SET_LOCK
• OMP_UNSET_LOCK
• OMP_TEST_LOCK
5.2 Biến môi trường
7



Các biến môi trường được dùng để điều khiển sự thực hiện đoạn mã song
song. Bao gồm các biến môi trường sau:
• OMP_SCHEDULE
• OMP_NUM_THREADS
• OMP_DYNAMIC
• OMP_NESTED

8


II-

Bài toán tìm đường đi ngắn nhất
1- Các khái niệm mở đầu
• Đồ thị có hướng : Đồ thị có hướng G là một cặp có thứ tự G:=(V, E), trong đó
- V, tập các đỉnh hoặc nút,
- E, tập các cặp có thứ tự chứa các đỉnh, được gọi là các cạnh có hướng hoặc cung.
Một cạnh e = (x, y) được coi là có hướng từ x tới y; x được gọi là điểm đầu/gốc và
y được gọi là điểm cuối/ngọn của cạnh.
• Nếu với mỗi cạnh e=(x,y) thuộc E ta đặt một số thực tương ứng c(x,y) gọi là trọng số
của nó . và c(x,y)= ∞ nếu e=(x,y) không thuộc E.
• Nếu dãy v0, v1, v2………vp là một đường đi trên G thì độ dài của nó được định nghĩa
như sau :
p
∑ c(vi-1, vi)
I=1
Tức là độ dài của đường đi chính là tổng các trọng số trên các cạnh đó.
2- Bài toán tìm đường đi ngắn nhất

Bài toán tìm đường đi ngắn nhất là bài toán quan trọng trong Lý thuyết đồ thị, nó được
áp dụng để giải quyết rất nhiều bài toán trong thực tế như điều khiển tối ưu, giao thông
vận tải, mạng viễn thông ...
Bài toán này có thể chia làm 2 loại:
Tìm đường đi ngắn nhất giữa một cặp đỉnh: Cho đồ thị G(V,E) có trọng số cạnh và
hai đỉnh u, v thuộc V tìm đường đi ngắn nhất từ đỉnh u đến đỉnh v trên đồ thị G. Các giải
thuật được phát triển để giải bài toán dạng này tiêu biểu là các giải thuật: Dijkstra,
Bellman-Ford,...
Tìm đường đi ngắn nhất giữa tất cả các cặp đỉnh: Cho đồ thị G(V,E) có trọng số
cạnh tìm đường đi từ đỉnh u đến đỉnh v, với mọi cặp đỉnh u, v thuộc V. Các giải thuật đã
được phát triển để giải bài toán này là: Floyd-Warshall, Johnson,...
Trong thực tế nhiều khi ta không chỉ cần tìm đường đi ngắn nhất giữa hai đỉnh mà còn
cần xác định đường đi ngắn nhất giữa một tập đỉnh này đến một tập đỉnh khác. Bài toán
đó được phát biểu như sau: Cho đồ thị G(V,E) có trọng số cạnh và hai tập đỉnh A,B ⊂ V
tìm đường đi ngắn nhất từ tập đỉnh A đến tập đỉnh B.
Các thuật toán quan trọng nhất giải quyết bài toán này là:

• Thuật toán Dijkstra — giải bài toán nguồn đơn nếu tất cả các trọng số đều không âm.
Thuật toán này có thể tính toán tất cả các đường đi ngắn nhất từ một đỉnh xuất phát
cho trước s tới mọi đỉnh khác mà không làm tăng thời gian chạy.

• Thuật toán Bellman-Ford — giải bài toán nguồn đơn trong trường hợp trọng số có thể
có giá trị âm.

• Giải thuật tìm kiếm A* giải bài toán nguồn đơn sử dụng heuristics để tăng tốc độ tìm
kiếm

• Thuật toán Floyd-Warshall — giải bài toán đường đi ngắn nhất cho mọi cặp đỉnh.
• Thuật toán Johnson — giải bài toán đường đi ngắn nhất cho mọi cặp đỉnh, có thể
nhanh hơn thuật toán Floyd-Warshall trên các đồ thị thưa.


9


• Lý thuyết nhiễu (Perturbation theory); tìm đường đi ngắn nhất địa phương (trong
trường hợp xấu nhất)

Ứng dụng thực tế của bài toán tìm đường đi ngắn nhất:
Trong phạm vi bài tập lớn này em chỉ tìm hiểu về đường đi ngắn nhất giữa một cặp
đỉnh nào đó.
III- Giải thuật Dijkstra
1- Giải thuật Dijkstra
Trong trường hợp trọng số trên các cạnh là không âm thuật toán do Dijkstra đề
xuất để giải bài toán tìm đường đi ngắn nhất từ đỉnh s đến các đỉnh còn lại của đồ
thị làm việc hữu hiệu hơn rất nhiều so với các thuật toán đã trình bày ở mục trước.
Thuật toán dựa trên cơ sở gán cho các đỉnh các nhãn tạm thời. Nhãn của mỗi đỉnh
cho biết cận trên của độ dài đường đi ngắn nhất từ s đến nó. Các nhãn này biến đổi
theo một thủ tục lặp, mà ở đó mỗi bước lặp cơ một nhãn tạm thời trở thành nhãn
cố định. Nếu nhãn của một đỉnh nào đó trở thành cố định thì nõ sẽ cho ta không
phải là cận trên của độ dài mà là độ dài của đường đi ngắn nhất từ đỉnh s đến nó.
Thuật toán được mô tả cụ thể như sau :
Procedure Dijkstra
(*
Đầu vào : Đồ thị có hướng G=(V,E) với n đỉnh
S thuộc V là đỉnh xuất phát , c[u][v] , u,v thuộc V ma trận trọng số
Giả thiết: a[u,v]>=0 u,v thuộc V
Đầu ra : Khoảng cách từ s đến các đỉnh còn lại d[v], v thuộc V
Truoc[v] ghi nhận đỉnh đi trước v trong đường đi ngắn nhất từ s đến v
*)
Begin

(* khởi tạo *)
For v
Begin
D[v]= c[s,v];
Truoc[v]=s;
End
D[s]=0 ;
T= V\{s} (* T là tập các đỉnh có nhãn tạm thời *)
(* bước lặp *)
While (T do
Begin
Tìm đỉnh u T thỏa mãn d[u]= min{ d[z]: z T};
T= T\{u}; (* cố định nhãn u *)
For v do (* Gán lại nhãn cho các đỉnh trong T*)
If( d[v]>d[u]+a[u,v] )
Begin
d[v]=d[u]+a[u,v];
truoc[v]=u;
10


end;
end;
end;
Ví dụ :
Ma trận trọng số

1
1 0
2 ∞

3 ∞
4 2
5 ∞
6 ∞

A=

2
1
0





3

5
0
1



4
5


2




0
4
3
0

1

6

7
1




Bảng kết quả tính toán theo thuật toán Dijkstra :
Quy ước viết hai thành phần của nhãn theo thứ tự là d[v] và truoc[v]
Bước lặp
Khởi tạo
1
2
3
4
5

2-

Đỉnh 1
0.1

-

Đỉnh 2
1,1*
-

Đỉnh 3
∞,1
6,2
4,4*
-

Đỉnh 4
∞,1
3.2*
-

Đỉnh 5
∞,1
∞,1
7,4
7,4
6,6*
-

Đỉnh 6
∞,1
8,2
8.2
5,3*

-

Tính đúng đắn của giải thuật Dijkstra
Trước hết ta đi chứng minh là thuật toán tìm được đường đi ngắn nhất từ đỉnh s đến
các đỉnh còn lại của đồ thị.
Giả sử rằng ở một bước lặp nào đó các nhãn cố định cho ta độ dài các đường đi ngắn
nhất từ s đến các đỉnh có nhãn cố định, ta sẽ chứng minh ở lần lặp tiếp theo nếu đỉnh u *
thu được nhãn cố định là d[u*] chính là độ dài đường đi ngắn nhất từ s đến u*.
Thật vậy ta có
Kí hiệu S1 là tập các đỉnh có nhãn cố đinh còn S 2 là tập các đỉnh có nhãn tạm thời ở
bước lặp đang xét. Kết thúc mỗi bước lặp nhãn tạm thời d[v] cho ta độ dài đường đi từ s
đến v chỉ qua những tập nằm hoàn toàn trong S 1. Giả sử rằng đường đi ngắn nhất từ s
11


đến u* không nằm ngọn trong S 1, tức là nó đi qua ít nhất một đỉnh của tập S 2. Gọi z thuộc
S2 là đỉnh đầu tiên như vậy trên đường đi này. Do trọng số trên các cung là không âm,
nên đoạn đường từ z đến u* có độ dài là L>0 và
d[z]< d[u*] –LBất đẳng thức này mâu thuẫn với cách xác định đỉnh u * là đỉnh có nhãn tạm thời nhỏ
nhất. vậy đường đi ngắn nhất từ s đến u* phải nằm trọn trong S1 và vì thế d[u*] là độ dài
của nó. Do ở lần lặp đầu tiên S 1={s} và sau mỗi lần lặp ta chỉ thêm vào S 1 một đỉnh u*
nên giả thiết d[v] cho độ dài đường đi ngắn nhất từ s đến v với mọi v thuộc S 1 là đúng
với bước lặp đầu tiên. Theo quy nạp toán học suy ra thuật toán cho ta đường đi ngắn
nhất từ đỉnh s đến mọi đỉnh của đồ thị.
3- Thời gian tính toán của thuật toán Dijkstra
Định lý : Thuật toán Dijkstra tìm được đường đi ngắn nhất trên đồ thị sau thời gian cỡ
O(n2)
Bây giờ ta sẽ đánh giá số phép toán cần thực hiện theo thuật toán. Ở mỗi bước lặp để
tìm ra đỉnh u cần phải thực hiện O(n) phép toán và để gán nhãn lại cũng cần phải thực

hiện một số lượng phép toán cũng là O(n). Thuật toán phải thực hiện n-1 bước lặp vậy
thời gian tính toán của thuật toán là O(n2)
IV- Kết quả thực nghiệm
1- So sánh giữa lập trình tuần tự và lập trình song song
Nếu ta tăng dần dữ liệu đầu vào (tăng kích thước ma trận trọng số). Thì thời gian
tính toán của thuật toán Dijkstra cài đặt bằng lập trình tuần tự sẽ tăng dần theo đồ thị
sau :

2- Kết luận

Qua kết quả thực nghiệm cho thấy
Thời gian tính toán của lập trình song song là nhanh hơn so với lập trình tuần
tự. Khi kích thước bộ dữ liệu đầu vào càng lớn thì thời gian tính toán của lập trình
song song càng nhanh hơn so với lập trình tuần tự
Thời gian tính toán của lập trình song song sẽ tăng nếu ta tăng số luồng thực
hiện, tăng số bộ sử lý
Định luật Amdahl: Gọi f là phần nhỏ của thao tác tính toán trong quá trình tính
toán phải thực hiện một cách tuần tự, 0 ≤ f ≤ 1. Tốc độ tối đa S có thể đạt được bằng
cách sử dụng máy tính song song với p BXL được cho bởi công thức
S ≤
Thời gian cho phần việc xử lý song song của ứng dụng sẽ dảm dần đến 0 khi
ta tăng số lượng BXL. Thời gian cho việc xử lý tuần tự luôn là hằng số.
Lập trình song song cũng như tính toán hiệu năng cao đang là xu hƣớng hiện nay
trên thế giới. Xu hướng này có thể dễ dàng nhận thấy qua sự tăng vọt về số lượng
bộ xử lý vật lý tích hợp trên một chip trong những năm gần đây. Thêm vào đó rất

12


nhiều trợ những hệ thống giúp tính toán song song đã được phát triển như Window

HPC Server, Rock Cluster… tạo đà cho sự phát triển của lập trình song song.

Tài liệu tham khảo
1- Internet
2- Giáo trình toán rời rạc – Nguyễn Đức Nghĩa , Nguyễn Tô Thành

13



×