Sắp xếp song song tựa trên Quicksort

Một phần của tài liệu GIÁO TRÌNH: TÍNH TOÁN SONG SONG potx (Trang 85 - 90)

Quicksort là giải thuật sắp xếp đệ qui dựa trên cách tiếp cận chia để trị (divide and conquer). Quicksort thực hiện các bước lặp chia một mảng thành hai mảng nhỏ hơn và một phần tử khóa (medium). Trong đó, một mảng con chứa các phần tử bé hơn (hoặc bằng) phần tử khóa, mảng con

còn lại chứa các phần tử lớn hơn (hoặc bằng) phần tử khóa. Phần tử khóa được đặt đúng vị trí.

Quá trình này được tiếp tục một cách đệ qui.

Phần này giới thiệu về hai giải thuật song song dựa trên giải thuật sắp xếp Quicksort đó là Quicksort song song (Parallel Quicksort) và Siêu Quicksort (HyperQuicksort).

a. Thuật toán Quicksort song song (Parallel Quicksort).

Để ý rằng trong giải thuật Quicksort tuần tự thì sau khi phân hoạch thành hai mảng con, thì hai mảng con này có thể được sắp xếp độc lập với nhau.

Giả sử ta có một số tiến trình, mỗi tiến trình được thực hiện trên bộ xử lý, để thực hiện giải thuật

song song. Các phần tử cần sắp xếp được lưu vào một mảng chứa trong bộ nhớ toán cục. Một ngăn xếp trong bộ nhớ toàn cục để chứa các con trỏ trái và phải của mảng con chưa được sắp xếp.

Khi một tiến trình rảnh rỗi, nó sẽ lấy các giá trị con trỏ trái và phải của mảng con khỏi ngăn xếp

BITONIC MERGE SORT(HYPERCUBE PROCESSOR ARRAY) Biến toàn cục: d {khoảng cách giữa các phần tử cần so sánh}

Biến cục bộ: a {một trong các phần tử cần sắp xếp }

t {giá trị lấy từ bộ xử lý kế tiếp}

Begin

For i = 0 to m-1 do For j = i downto 1 do

d = 2j

For all Pk where 0 ≤ k≤ 2m-1 do If k mod 2d < d then

t = [k+d]a {lấy giá trị từ bộ xử lý liền kề}

if k mod 2i+2 <2i+1 then

[k+d]a = max (t,a) {sắp xếp từ bé đến lớn}

a = min (a,t) else

[k+d]a = min (t,a) {sắp xếp từ lớn đến bé}

a = max (a,t) endif endif endfor endfor endfor End.

trong bộ nhớ toàn cục. Nếu thành công, bộ xử lý sẽ chia đôi mảng thành hai mảng con (kích thước mỗi mảng con phụ thuộc vào giá trị của phần tử khóa). Trong đó, có một mảng con chứa

các giá trị nhỏ hơn (hoặc bằng) phần tử khóa và mảng con còn lại chứa các phần tử lớn hơn (hoặc

bằng) phần tử khóa.

Sau khi phân hoạch (giống như phân hoạch trong thuật toán tuần tự), tiến trình sẽ đặt giá trị con

trỏ trái và phải của một mảng con vào ngăn xếp trong bộ nhớ toàn cục và lặp lại quá trình phân hoạch cho mảng con còn lại.

Hàm Stack.init() khởi tạo ngăn xếp chứa các con trỏ trái và phải của mảng ban đầu chưa được sắp

xếp.Các hàm Stack.Push() và Stack.Pop() đặt vào và lấy ra các giá trị con trỏ trái và phải của

mảng con trên đỉnh ngăn xếp.

Về độ phức tạp của thuật toán : trong trường hợp xấu nhất thì sau khi phân hoạch, một mảng con

rỗng và mảng còn lại gồm n-1 phần tử, cần đến n-min lần phân hoạch để phân hoạch xong mảng.

Chính vì điều này làm cho Quicksort song song có cùng độ phức tạp với Quicksort tuần tự là O (n2). Tuy nhiên, người ta đã chứng minh và thử nghiệm được rằng tôc độ (speedup) của Quicksort

PARALLEL QUICKSORT()

Biến toàn cục: n {kích thước của mảng}

A[0,..,n-1] {mảng cần sắp xếp}

sorted {số phần tử tại vị trí đã được sắp xếp}

min, partition {mảng con nhỏ nhất được phân hoạch}

Biến cục bộ: bounds {con trỏ trái và phải của mảng chưa được sắp xếp}

median {chỉ số của giá trị khóa}

Begin

Sorted = 0 Stack.Init()

For all Pi where 0 ≤ i < p do bounds =Stack.pop()

while (bounds.low <bounds.high) do

if (bounds.high - bounds.low < min.partition) then InsertionSort (A, bounds.low, bounds.high)

AddToSorted(bounds.high - bounds.low+1) exit while

else

median = Partition(bounds.low, bounds.high) Stack.Push (median+1, bounds.high)

bounds.high = median -1

if bounds.low = bounds.high then AddToSort(1) endif endif endwhile endfor End.

song song tốt hơn so với Quicksort tuần tự (việc chứng minh cụ thể khá phức tạp, xin được không

nêu ở đây).

b. Thuật toán Siêu Quicksort (HyperQuicksort).

Thuật toán Quicksort song song ở trên làm tăng tốc độ xử lý nhờ việc sử dụng nhiều tiến trình

được thực hiện đồng thời trên nhiều bộ vi xử lý khác nhau. Ngoài ra, có một số biến thể của Quicksort song song được phát triển để tăng số lượng các bộ vi xử lý làm việc đồng thời. Ở đây,

ta giới thiệu một trong số giải thuật đó được thực hiện trên máy tính song song với các bộ vi xử lý được tổ chức theo hình siêu khối: thuật toán Siêu Quicksort được trình bày dưới đây.

Cho một dãy các phần tử được phân phối đều (evenly distributed) cho các bộ vi xử lý, ta định

nghĩa một dãy được sắp xếp khi:

(1). Mọi dãy con trên các bộ xử lý được sắp xếp và

(2). Phần tử cuối cùng của dãy con trên bộ xử lý Pi nhỏ hơn hoặc bằng phần tử đầu tiên của dãy con trên bộ xử lý Pi+1 với mọi 0 ≤ i ≤ p-2 . Các phần tử đã được sắp xếp không cần phải phân phối đều trên các bộ xử lý.

Để phát triển thuật toán, ta áp dụng chiến lược: cho mỗi bộ xử lý giải một bài toán con và sử dụng

cách giải tuần tự hiệu quả nhất trên mỗi bộ xử lý, sau đó sử dụng một thuật toán song song có

hiệu quả truyền thông tốt để kết hợp các lời giải bài toán con để thu được lời giải của bài toán ban

đầu.

Trong pha đầu của thuật toán Siêu Quicksort, mỗi bộ xử lý sử dụng giải thuật Quicksort tuần tự để sắp xếp dãy con cục bộ của nó và quá trình này diễn ra đồng thời đối với tất cả các bộ vi xử lý. Khi pha này kết thúc thì điều kiện (1) được thỏa mãn nhưng điều kiện (2) chưa được thỏa mãn. Siêu Quicksort là một giải thuật đệ qui, sử dụng cách tiếp cận chia để trị (divide and conquer) để làm điều kiện (2) được thỏa mãn. Trong mỗi bước của pha 2, một siêu khối được hai siêu khối

con (subcubes). Mỗi bộ xử lý gửi các phần tử của mình tới bộ xử lý khác trong một siêu khối con

khác, thì mỗi bộ xử lý sẽ trộn các phần tử của dãy con nó giữ với các phần tử của dãy con nó nhận được từ bộ xử lý bên cạnh.Kết quả của thao tác chia và trộn (split and merge) để chia một

siêu khối với dãy đã được sắp xếp thành hai siêu khối với 2 dãy con đã được sắp xếp, và giá trị

lớn nhất trong siêu khối dưới sẽ bé hơn phần tử nhỏ nhất của siêu khối trên. Sau d bước chia và trộn, thì từ một mạng siệu khối với 2d bộ xử lý sẽ được chia thành 2d siêu khối con với mỗi siêu khối là một bộ xử lý, và điều kiện (2) được thỏa mãn.

Bước chia và trộn chia một siêu khối d chiều thành hai siêu khối d-1 chiều. Để ý rằng các phần tử

trên mỗi bộ xử lý đã được sắp xếp. Bộ xử lý được chỉ định trong siêu khối d chiều sẽ phân phát

(broadcast) giá trị khóa (median value) tới 2d-1 bộ xử lý khác trong siêu khối. Mỗi bộ xử lý sẽ sử

dụng giá trị này để chia dãy con mà nó đang chứa thành hai nửa con sao cho các phần tử của nửa dưới nhỏ hơn hoặc bằng giá trị khóa và các phần tử thuộc nửa trên lớn hơn giá trị khóa. Mỗi bộ

xử lý Pi trong nửa dưới của siêu khối sẽ gửi nửa dãy con trên (nửa chứa các phần tử lớn hơn giá

trị khóa) tới bộ xử lý “partner” của nó ở trên nửa trên của siêu khối, đó là bộ xử lý Pi  2d-1 trong

đó  là phép tính loại trừ OR (eXclusive OR). Mỗi bộ xử lý Pi trong nửa trên của siêu khối sẽ

gửi nửa dãy con dưới (nửa chứa các phần tử nhỏ hơn hoặc bằng giá trị khóa) tới bộ xử lý

“partner” của nó ở trên nửa dưới của siêu khối, đó là bộ xử lý Pi  2d-1 trong đó  là phép tính loại trừ OR.

Mỗi bộ xử lý sẽ trộn dãy phần tử mà nó nhận được từ “partner” với dãy các phần tử mà nó đang

chứa để tạo thành một dãy mới đã được sắp xếp. Vì vậy, tất cả các phần tử nhỏ hơn hoặc bằng

phần tử khóa sẽ được chứa trong các bộ xử lý của siêu khối d-1 chiều phía dưới và tất cả các phần

tử lớn hơn phần tử khóa sẽ được chứa trong các bộ xử lý trên siêu khối d-1 chiều phía trên.

Dưới đây là một minh họa:

Hình 2.27. Một minh họa về các bước thực hiện giải thuật Siêu Quicksort

Giả sử tại thời điểm ban đầu mỗi bộ xử lý có n phần tử. Trong pha ban đầu, độ phức tạp về thời

gian kỳ vọng là O (nlogn). Giả sử rằng mỗi bộ xử lý giữ lại n/2 phần tử và chuyển n/2 phần tử

khác cho bộ xử lý partner sau mỗi bước chia và trộn, số phép so sánh kỳ vọng cần để trộn hai dãy

con đã được sắp xếp thành một dãy đã được sắp xếp là O(n). Do thao tác chia và trộn được thực

hiện trên các siêu khối d, d-1,…, 1 chiều, nên số phép so sánh kỳ vọng là O(nd). Nên số phép so

sánh kỳ vọng của thuật toán Siêu Quicksort là O (n(logn+d)).

HYPERQUICKSORT()

Biến toàn cục: n {số phần tử trên mỗi bộ xử lý}

d {chiều của siêu khối}

i {số chiều của siêu khối hiên tại}

Biến cục bộ: logicalNum {chỉ số của bộ xử lý}

partner {bộ xử lý partner để trao đổi}

root {bộ xử lý gốc của siêu khôi hiện tại}

splitter {giá trị khóa}

Begin

For all Pi where 0 ≤ i < 2ddo

Sắp xếp các phần tử sử dụng Quicksort tuần tự

If d>0 then

For I = d downto 1 do

root = gốc của khối i chiều chứa bộ xử lý logicalNum

if logicalNum = root then

splitter = giá trị trung bình của danh sách lưu bởi bộ xử lý logicalNum

endif

Bộ xử lý root phân phát splitter tới các bộ xử lý trong siêu khối i chiều

Sử dụng splitter để phân hoạch các dãy phần tử trong các bộ xử lý

Partner = logicalNum  2d-1 if logicalNum <partner then

Gửi danh sách chứa các giá trị bé hơn khóa tới bộ xử lý partner

Nhận danh sách chứa các giá trị lớn hơn khóa từ partner

Else

Gửi danh sách chứa các giá trị lớn hơn khóa tới bộ xử lý partner

Nhận danh sách chứa các giá trị bé hơn khóa từ partner

endif

Trộn hai dãy con trên mỗi bộ xử lý thành một dãy đã được sắp xếp

endfor endif

endfor

Một phần của tài liệu GIÁO TRÌNH: TÍNH TOÁN SONG SONG potx (Trang 85 - 90)

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

(112 trang)