Một số vấn đề về hiệu năng

Một phần của tài liệu Song song hoá thuật toán tìm đường đi ngắn nhất trên nguồn dữ liệu lớn dùng MPI luận văn thạc sĩ (Trang 29)

4. Phương pháp nghiên cứu

2.2.2. Một số vấn đề về hiệu năng

2.2.2.1 Năng lực tính toán

Việc song song hóa một chương trình nhằm làm cho chương trình đó chạy nhanh hơn, tuy nhiên chương trình đó sẽ chạy nhanh hơn bao nhiêu lần? Định luật Amdahl’s [3] cho phép ta xác định điều này. Giả sử xét về khía cạnh thời gian

chạy chương trình, một phần p của chương trình có thể song song hóa và phần 1- p còn lại buộc phải chạy tuần tự. Trong trường hợp lý tưởng, nếu thực thi chương trình sử dụng n bộ xử lý, thời gian chạy chương trình sẽ là 1-p + p/n của thời gian chạy chương trình một cách tuần tự. Đây là hệ quả trực tiếp của định luật Amdahl áp dụng cho trường hợp thực thi lý tưởng.

Ví dụ: nếu 80% chương trình có thể được song song hóa, và ta có 4 bộ xử lý, thời gian chạy song song sẽ là: 1 - 0.8 + 0.8/4 = 0.4 tức là bằng 40% thời gian chạy tuần tự.

Hình 2.1: khả năng tăng tốc độ tính toán, trường hợp lý tưởng

Đối với chương trình trên, thời gian chạy song song sẽ không thể nào nhỏ hơn 20% thời gian chạy tuần tự cho dù ta sử dụng số lượng vô cùng lớn các bộ xử lý. Trên thực tế, khi chạy một chương trình song song, thường xuất hiện các chi phí truyền thông và việc phân công công việc không cân bằng giữa các bộ xử lý. Do đó thời gian chạy chương trình sẽ là:

Hinh 2.2: Khả năng tăng tốc độ tính toán, trường hợp thực tế.

Do vậy để tăng tốc độ của chương trình ta cần:

- Tăng tỉ lệ (thành phần) được song song hóa của chương trình. - Phân công công việc một cách công bằng cho các bộ xử lý. - Giảm tới mức tối thiểu thời gian truyền thông.

2.2.2.2 Cân bằng tải

Giả sử rằng nếu dữ liệu được phân tán trên các bộ nhớ địa phương của các bộ xử lý trong hệ thống nhiều máy tính, khi đó khối lượng công việc của các bộ xử lý cần phải được phân phối hợp lý trong suốt quá trình tính toán. Trong nhiều trường hợp, giả sử này là đúng, tuy nhiên trong thực tế điều này không phải lúc nào cũng thực hiện được. Giải pháp được đưa ra ở đây là cân bằng tải động nhằm mục đích làm thay đổi sự phân phối khối lượng công viêc giữa các bộ xử lý trong quá trình thực hiện tính toán.

Thông thường sau khi phân phối khối lượng công việc cho các bộ xử lý, quá trình cân bằng tải động thực hiện bốn bước cơ bản sau:

- Giám sát hiệu năng của các bộ xử lý.

- Trao đổi thông tin trạng thái giữa các bộ xử lý.

- Tính toán và ra quyết định phân phối lại khối lượng công việc. - Thực hiện việc chuyển đổi dữ liệu thực sự.

Để thực hiện được điều này, rất nhiều thuật toán đã được đề xuất. Người ta phân lớp các thuật toán này theo các chiến lược: tập trung, phân tán hoàn toàn (fully distributed) và phân tán một nửa (semi distributed).

a) Các thuật toán cân bằng tải tập trung

Các thuật toán này thường đưa ra quyết định có tính chất tổng thể trong việc phân phối lại khối lượng công việc cho các bộ xử lý. Một vài thuật toán trong lớp này sử dụng thông tin hệ thống có tính toàn cục để lưu trạng thái các máy tính riêng lẻ. Thông tin này sẽ giúp thuật toán phân phối công việc một cách dễ dàng. Tuy nhiên, khối lượng thông tin tăng theo tỉ lệ thuận với số lượng các bộ xử lý, do đó nó đòi hỏi khối lượng lớn bộ nhớ trên một bộ xử lý để lưu thông tin trạng thái. Vì vậy thuật toán thuộc lớp này không được tiếp cận một cách rộng rãi.

b) Các thuật toán cân bằng tải phân tán hoàn toàn

Trong các thuật toán dạng này, mỗi bộ xử lý có một bản sao về thông tin trạng thái của hệ thống. Các bộ xử lý trao đổi thông tin trạng thái với nhau và sử dụng các thông tin này để làm thay đổi một cách cục bộ việc phân chia công việc. Tuy

nhiên các bộ xử lý chỉ có thông tin trạng thái cục bộ nên việc cân bằng tải không tốt bằng các thuật toán cân bằng tải tập trung.

c) Các thuật toán cân bằng tải phân tán một nửa

Các thuật toán thuộc lớp này chia các bộ xử lý thành từng miền. Trong mỗi miền sử dụng thuật toán cân bằng tải tập trung để phân phối công việc cho các bộ xử lý thuộc miền đó.

2.2.2.3 Sự bế tắc

Các tiến trình xử lý bị rơi vào tình trạng bế tắc nếu mỗi tiến trình đó nắm giữ tài nguyên mà một vài tiến trình khác đang yêu cầu để xử lý. Lý do tiềm ẩn của sự bế tắc là do nhiều tiến trình cùng sử dụng nguồn tài nguyên chung mà không có sự kiểm soát tốt.

Đối với các hệ thống đa máy tính, một trong những sự bế tắc phổ biến nhất là bế tắc vùng đệm (buffer deadlock) xảy ra khi một tiến trình đợi một thông điệp mà thông điệp này có thể không bao giờ nhận được do vùng đệm đã đầy.

Bốn điều kiện sau là nguyên nhân gây ra bế tắc:

1. Sự loại trừ lẫn nhau: mỗi tiến trình có sự độc quyền trong việc sử dụng tài nguyên của nó.

2. Không có sự ưu tiên: Mỗi tiến trình không bao giờ giải phóng tài nguyên mà nó đang chiếm giữ cho tới tận khi không còn sử dụng chúng nữa.

3. Sự chờ đợi tài nguyên: mỗi tiến trình đang chiếm giữ tài nguyên trong khi lại chờ đợi các tiến trình khác giải phóng chúng.

4. Sự chờ đợi giữa các tiến trình: tiến trình chờ đợi tài nguyên mà tiến trình kế tiếp đang chiếm giữ mà tài nguyên đó không được giải phóng.

* Một số giải pháp khắc phục sự bế tắc

- Dò tìm sự bế tắc khi chúng xảy ra và cố gắng khôi phục lại.

- Sử dụng các thông tin yêu cầu tài nguyên của các tiến trình để điều khiển sự phân phối để khi tiếp tục phân phối các tài nguyên không là nguyên nhân để các tiến trình rơi vào bế tắc.

CHƯƠNG 3 - MPI TRONG THUẬT TOÁN DIJKSTRA CHO BÀI TOÁN TÌM KIẾM ĐƯỜNG ĐI NGẮN NHẤT

3.1. Yêu cầu đặt ra cho bài toán tìm kiếm đường đi ngắn nhất theo giải thuật Dijksta thuật Dijksta

Thuật toán Dijkstra 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. Độ phức tạp của thuật toán này là O(n2).

Yêu cầu đặt ra ở đây là với số đỉnh lớn, mỗi đỉnh có số cạnh kề lớn, chi phí để tìm đường đi ngắn nhất tương ứng với thuật toán này là không nhỏ.

Để đáp ứng yêu cầu trên với chi phí thấp nhất, cần cải tiến thuật toán Dijkstra cổ điển để đáp ứng yêu cầu về thời gian.

Trong luận văn này, tác giả đề xuất hướng giải quyết bằng cách song song hoá thuật toán Dijkstra sử dụng mô hình truyền thông điệp MPI.

3.2. Xây dựng hàm tìm kiếm đường đi ngắn nhất

Phương pháp song song hoá được đề xuất trong luận văn là phương pháp chia tập đỉnh nguồn. Với phương pháp này, mỗi bộ xử lý sẽ chạy thuật toán Dijkstra tuần tự cho tập con các đỉnh nguồn.

Để xây dựng thuật toán Dijkstra song song, trước hết cần xây dựng thuật toán Dijkstra tuần tự phù hợp với yêu cầu đặt ra.

3.2.1 Xây dựng thuật toán Dijkstra tuần tự cho bài toán

Procedure Seq Dijkstra (V,E,w,s) Begin

VT:= {s}; For all v є (V-VT) do If tồn tại cạnh (s, v) đặt l[v] := w(s, v); else đặt L[v] := ∞; while VT ≠ V do Begin Tìm một cạnh u mà L[u] := min{L[u]|v ϵ (V – VT)}; VT := VT ᴜ {u}; For all v ϵ (V – VT) do

L[v] := min{L[v], L[u] + w(u, v)}; End

Endwhile End

End Pro

3.2.2 Thực hiện song song hoá

- Giả sử, bài toán có n đỉnh, thuật toán sử dụng p bộ xử lý.

- Tập đỉnh V được chia thành p tập con, mỗi tập con có n/p đỉnh và gán cho 1 bộ xử lý.

- Bộ xử lý Pi quản lý tập đỉnh con Vi và tính toán khoảng cách L[v] cho các đỉnh v ϵ Vi

3.2.3 Thuật toán song song

Procedure Parallel Dijkstra (V,E,w,s) Begin

VT:= {s};

For all v є (V-VT) do

If tồn tại cạnh (s, v) đặt L[v] := w(s, v); else đặt L[v] := ∞;

Chia tập đỉnh V thành p tập con và gán cho mỗi tiến trình while VT ≠ V do

Begin

Tại mỗi tiến trình, tìm một cạnh u mà Li[u] := min{Li[u]|v ϵ (V – VT)};

Kết hợp các giá trị min{Li-min | i = 0..p-1} từ tất cả các tiến trình và phân phối trở lại tất cả các tiến trình

Đánh dấu đỉnh đã thực hiện

Cập nhật giá trị min trên mỗi tiến trình End

Tổng hợp kết quả từ các tiến trình Endwhile

End End Pro

3.2.4 Lựa chọn hàm MPI cho thuật toán song song

Một chương trình MPI bao gồm nhiều chương trình tuần tự có trao đổi dữ liệu với nhau thông qua việc gọi các hàm trong thư viện. Các hàm này thuộc bốn lớp cơ bản:

1. Khởi tạo, quản lý và kết thúc trao đổi. 2. Trao đổi giữa hai tiến trình.

3. Trao đổi giữa một nhóm các tiến trình. 4. Tạo các định dạng dữ liệu bất kỳ.

Lớp đầu tiên là các hàm được gọi để khởi đầu quá trình trao đổi, xác định số lượng bộ xử lý được sử dụng, tạo một nhóm con các bộ xử lý, xác định bộ xử lý nào đang chạy chương trình hiện tại.

- MPI_Init(): khởi tạo quá trình song song. - MPI_Finalize(): kết thúc quá trình song song. - MPI_Comm_rank(): xác định tên tiến trình.

- MPI_Comm_size(): xác định tổng số tiến trình chạy song song.

Lớp thứ hai là các hàm, được gọi để trao đổi dữ liệu điểm - đến - điểm, với các kiểu gửi và nhận dữ liệu khác nhau giữa hai bộ xử lý.

- MPI_Send(): gửi dữ liệu đến một tiến trình. - MPI_Recv(): nhận dữ liệu từ một tiến trình.

Lớp thứ ba là các hàm cho phép thực hiện trao đổi song song giữa một nhóm các bộ xử lý. Các hàm cơ bản:

- MPI_Bcast(): gửi dữ liệu từ một tiến trình đi tất cả các tiến trình. - MPI_Reduce(): gửi dữ liệu từ nhiều tiến trình về một tiến trình - MPI_Barrier(): dùng để đồng bộ hoạt động giữa các máy - MPI_Gather(): nhận dữ liệu từ nhiều tiến trình.

- MPI_Scatter(): gửi dữ liệu đến nhiều tiến trình

Lớp cuối cùng là các hàm cung cấp để tạo ra các cấu trúc dữ liệu phức tạp riêng của người dùng. Các hàm cơ bản:

- MPI_Type_struct(): tạo ra kiểu dữ liệu MPI riêng của người dùng

- MPI_Type_commit(): hòan thành quá trình định nghĩa kiểu dữ liệu MPI Trong luận văn này, để thực hiện trao đổi song song giữa một nhóm các bộ xử lý cần sử dụng các hàm ở lớp thứ 3.

* Hàm Reduce

Hàm Reduce nhận kết quả từ các tiến trình và gửi kết quả đó đến tiến trình đã được chỉ định.

- Cú pháp: int MPI_ Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)

Hình 3.1: phương thức hoạt động của hàm Reduce

* Hàm All – Reduce

Hàm All – Reduce tương tự như hàm Reduce, nhưng không có Root và tất cả các tiến trình đều nhận được kết quả.

* Hàm Broadcast

Hàm Boadcast cho phép một tiến trình gửi dữ liệu đến tất cả các tiến trình khác. - Cú pháp: int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm)

* Hàm Scatter

Hàm Scatter chia nhỏ dữ liệu của một tiến trình và phân phối các phần dữ liệu được chia lên các tiến trình khác.

- Cú pháp: int MPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)

Hình 3.3: phương thức hoạt động của hàm Scatter

* Hàm Gather

Một tiến trình được chỉ định sẽ nhận kết quả từ các tiến trình khác khi sử dụng hàm Gather.

- Cú pháp: int MPI_Gather(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)

Hình 3.4: phương thức hoạt động của hàm Gather

* Hàm Gather – to – All

Tương tự như hàm Gather, nhưng tất cả các tiến trình đều nhận được kết quả như nhau.

- Cú pháp: int MPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)

Hình 3.5: phương thức hoạt động của hàm Gather – to - All

Hàm All –to – All cho phép tất cả các tiến trình phân chia dữ liệu, sau đó gửi từng phần dữ liệu đến các tiến trình khác.

- Cú pháp: int MPI_All_to_all(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)

Hình 3.6: phương thức hoạt động của hàm All – to – All

Căn cứ vào đặc điểm của các hàm ở lớp 3, luận văn sử dụng: - Hàm Reduce khi kết hợp các giá trị min;

- Hàm Broadcast để phân phối kết quả đến các tiến trình sau khi đã kết hợp; - Hàm Gather để tập hợp các kết quả sau khi duyệt hết tất cả các đỉnh;

3.2.5 Công thức song song

- Tại bước kết nạp đỉnh s vào tập VT

- Bộ xử lý Pi tính Li(v) = min{ Li(v), Li(u) + w(v,r) }, v ∈ Vi \VT

- Sử dụng mẫu liên lạc All-to-One Reduction để đưa min{Li-min | i = 0..p-1} về P0

- Giả sử giá trị nhỏ nhất đạt được tại đỉnh u, P0 broadcast u đến các bộ xử lý khác, bộ xử lý quản lý u sẽ đánh dấu u là không xét đến nữa.

* Sơ đồ khối thuật toán Dijkstra song song Begin Nếu v є (V-VT) L[v] := ∞ While VT ≠ V Tìm u có trọng số nhỏ nhất mà v ϵ (V – VT) Kết hợp Li-min, phân phối trở lại các tiến trình Đánh dấu đỉnh đã thực hiện Cập nhật giá trị min

trên mỗi tiến trình

End Nếu tồn tại (s,v) True False False True L[v] := w(s, v) True Tổng hợp kết quả từ các tiến trình False

3.3. Chi phí thời gian

- Mỗi bộ xử lý lưu n/p phần tử của mảng L

- Thời gian tính min và cập nhật giá trị của di bằng O(n/p) - Thời gian liên lạc giữa p bộ xử lý O(log p)

- Tổng thời gian O(n2/p) + O(n log p) - Tổng chi phí O(n2) + O(np log p)

CHƯƠNG 4 - KẾT QUẢ THỬ NGHIỆM

4.1. Các kết quả thử nghiệm

4.1.1. Kết quả thử nghiệm giải thuật Dijkstra cổ điển * Phần cứng * Phần cứng

- 1 máy tính Pentium IV 2.2GHz, RAM 512MB cài đặt hệ điều hành CentOS.

* Thử nghiệm

- Cài đặt thuật toán Dijkstra cổ điển với số lượng đỉnh tăng dần, trọng số giữa các cạnh được chọn ngẫu nhiên.

- Kết quả chạy thử nghiệm:

Bảng 4.1: Thời gian thực hiện thuật toán Dijkstra cổ điển

Số đỉnh Thời gian tuần tự (s)

0 0 500 0.004466 1000 0.010011 1500 0.023075 2000 0.03786 2500 0.061357 3000 0.09546 3500 0.134992 4000 0.176472 4500 0.230217 5000 0.292116 5500 0.362056 6000 0.426997 6500 0.503063

4.1.2. Kết quả thử nghiệm tìm kiếm bằng giải thuật Dijkstra song song * Phần cứng

- Hệ thống bao gồm 2 máy tính Pentium IV 2.2GHz, RAM 512MB cài đặt hệ điều hành CentOS.

- Hệ thống đã được cài đặt MPI.

* Thử nghiệm

- Cài đặt thuật toán Dijkstra song song với số lượng đỉnh tăng dần, trọng số giữa các cạnh được chọn ngẫu nhiên.

- Số tiến trình thử nghiệm là 2, tương ứng với mỗi bộ xử lý là 1 tiến trình. - Kết quả chạy thử nghiệm:

Bảng 4.2: Thời gian thực hiện thuật toán Dijkstra song song với 2 tiến trình

Số đỉnh Thời gian song song (2 tiến trình)

0 0 500 0.006841 1000 0.013739 1500 0.027807 2000 0.048473 2500 0.07326 3000 0.103994 3500 0.141089 4000 0.181721 4500 0.233742 5000 0.282327 5500 0.348231 6000 0.409863 6500 0.485421

Một phần của tài liệu Song song hoá thuật toán tìm đường đi ngắn nhất trên nguồn dữ liệu lớn dùng MPI luận văn thạc sĩ (Trang 29)

Tải bản đầy đủ (PDF)

(53 trang)