5.3.1. Thuật toán sắp xếp dựa trên cơ số
5.3.1.1. Thuật toán sắp xếp dựa trên cơ số cơ bản
Thuật toán sắp xếp dựa trên cơ số (Radix) là một trong những thuật toán sắp xếp nhanh nhất. Thuật toán sắp xếp này không dựa trên việc so sánh mà dựa trên cơ chế đếm.
Ví dụ ta có một chuỗi 7 số:
103
Sau đó ta sẽ tính tổng liền trƣớc (còn gọi là quét) dãy số này. Tức là giá trị của một phần tử sẽ bằng tổng giá trị của tất cả các phần tử ở phía trƣớc nó, ta thu đƣợc dãy:
Từ dãy này, ta thu đƣợc vị trí của từng thành phần khi sắp xếp theo giá trị hàng đơn vị. Ví dụ tức là có 2 số nhỏ hơn nó (xét theo hàng đơn vị) sẽ phải sắp xếp ở phía trƣớc nó. Dãy số thu đƣợc sau khi xếp theo chữ số hàng đơn vị là
Sau đó ta tiếp tục sắp xếp đến hàng chục thì sẽ thu đƣợc dãy số sắp xếp theo thứ tự tăng dần. Thuật toán sắp xếp cơ số là một thuật toán sắp xếp ổn định (stable) tức là nó không làm thay đổi giá trị tự nhiên của dãy đầu vào. Ta có thể thấy rõ tính chất này ở dãy kết quả ví dụ ở trên sau khi sắp xếp xong theo chữ số hàng đơn vị thì số 25 ở sau số 75. Mặc dù cả hai số này đều có chữ số 5 ở hàng đơn vị nhƣng trong dãy đầu vào số 75 đứng ở vị trí trƣớc, ở trƣờng hợp phức tạp hơn, hai số có cùng một giá trị xuất hiện trong dãy đầu vào thì thuật toán này không làm thay đổi vị trí tƣơng quan giữa hai số có cùng giá trị đó.
Giả sử dãy đầu vào có n chữ số thì thuật toán sắp xếp dựa trên cơ số sẽ cần n lần đếm và 10n bộ đếm cho mỗi phần tử trong dãy và tƣơng ứng n lần sắp xếp.
5.3.1.2. Thuật toán sắp trên dựa trên cơ số trên GPU
Về cơ bản thì thuật toán sắp sếp dựa trên cơ số sẽ vẫn tuân theo những bƣớc của thuật toán sắp xếp dựa trên cơ số trên CPU gồm ba bƣớc nhƣ trên:
- Đếm sự xuất hiện của các số tại vị trí số đƣợc xét - Tính tổng liền trƣớc của các phần tử trong dãy số
104
Nhƣng để đảm bảo tận dụng đƣợc khả năng tính toán song song của GPU thì giai đoạn tính dãy tổng liền trƣớc cần có sự thay đổi để có thể song song hóa đƣợc cách thực hiện công đoạn tính tổng liền trƣớc.
Để hiểu rõ hơn thuật toán tính tổng liền trƣớc trên GPU, ta sẽ thực hiện tính tổng liền trƣớc của một dãy số gồm 8 chữ số.
Giai đoạn tính tổng liền trƣớc trên GPU có thể chia thành 2 giai đoạn nhỏ:
Hình 48: Tính tổng liền trƣớc trên GPU – giai đoạn 1
Giai đoạn 1:
o Bƣớc 1: các phần tử ở vị trí 2*n sẽ lấy giá trị từ phần tử 2*n-1 và cộng với giá trị của mình rồi lƣu vào vị trí 2*n.
o Bƣớc 2: các phần tử ở vị trí 4*n sẽ lấy giá trị từ phần tử 2*n và cộng với giá trị của mình rồi lƣu vào vị trí 4*n.
o Bƣớc 3: phần tử ở vị trí 8*n sẽ lấy giá trị từ phần tử 4*n và cộng với giá trị của mình rồi lƣu vào chính nó.
Giai đoạn 2:
o Bƣớc 1: Đặt giá trị thứ 8 bằng 0.
o Bƣớc 2: Đặt giá trị biến tạm thời bằng giá trị thứ 4*n rồi đặt giá trị tại vị trí thứ 4*n bằng giá trị tại phần tử thứ 8*n (bằng 0) và cộng giá trị phần tử thứ 8*n với giá trị biến tạm thời.
105
o Bƣớc 3: Đặt giá trị biến tạm thời bằng giá trị phần tử thứ 2*n rồi đặt giá trị tại phần tử thứ 2*n bằng giá trị tại phần tử thứ 4*n (bằng 0) và cộng giá trị phần tử thứ 4*n với giá trị biến tạm thời.
o Bƣớc 4: Đặt giá trị biến tạm thời bằng giá trị phần tử thứ 1*n rồi đặt giá trị tại phần tử thứ 1*n bằng giá trị tại phần tử thứ 2*n (bằng 0) và cộng giá trị phần tử thứ 2*n với giá trị biến tạm thời.
Hình 49: Tính tổng liền trƣớc trên GPU – giai đoạn 2
Với bài toán tính tổng liền trƣớc, trên CPU cần phép cộng còn đối với thuật toán tính tổng liền trƣớc trên GPU nhƣ trình bày ở trên để trả ra cùng kết quả cần ∑ phép tính.
Rõ ràng ta thấy thuật toán tính tổng liền trƣớc của GPU phức tạp hơn CPU rất nhiều nhƣng bù lại khi triển khai việc tính tổng liền trƣớc trên GPU, ta sẽ tận dụng đƣợc khả năng tính toán song song mạnh mẽ của GPU. Tuy nhiên, ta cũng có thể thấy rằng nếu GPU không đủ mạnh và độ dài của mảng cần sắp xếp không đủ lớn thì hiệu năng của bài toán trên GPU sẽ không đƣợc cao.
Sau đó, bƣớc cuối cùng trong thuật toán là sắp xếp dãy đầu vào theo giá trị dãy tổng liền trƣớc thu đƣợc. Chỉ mục của một số ở vị trí thứ n sau khi sắp xếp có công thức:
106
Trong đó i là chỉ mục tại dãy cục bộ và là độ lệch tại dãy cục bộ và là độ lệch toàn cục của giá trị n xử lý bởi khối luồng m [33]. Ta có thể hiểu rằng khi dãy số đầu vào cần sắp xếp quá lớn, GPU sẽ chia dãy đầu vào thành các dãy nhỏ hơn có kích thƣớc nhỏ hơn hoặc bằng kích thƣớc một khối luồng. Khi đó, từng dãy con sẽ đƣợc sắp xếp theo thuật toán sắp xếp dựa trên cơ số nhƣ hai bƣớc đã trình bày trên rồi bƣớc cuối cùng, các dãy con sẽ đƣợc đƣa vào dãy kết quả với chỉ mục theo công thức trên.
Có một điểm cần chú ý là thuật toán sắp xếp dựa trên cơ số trên GPU luôn xử lý một dãy có phần tử. Do đó khi dãy nhập vào không có dạng phần tử thì ta phải làm thêm động tác tự động thêm vào dãy đầu vào các số lớn nhất có thể để sau khi sắp xếp xong ta chỉ cần loại bỏ phần bên phải số lớn nhất trong dãy đầu vào là ta thu đƣợc dãy kết quả.
107
5.3.2. Thông số cấu hình thử nghiệm
Bài toán này sẽ đƣợc thử nghiệm trên Dell Latitude E6420 nhƣ bài toán 1 và Vaio Fit SVF14217.
Vaio SVF14217 a. CPU
Intel® Core™ i3-3227U Processor Kiến trúc: Ivy Bridge
Số lõi: 2 Số luồng: 4 Tốc độ xung đồng hồ: 1.9 GHz Tốc độ bus DMI: 5 GT/s Bộ nhớ đệm level 1: 64KB (1 x 32 KB bộ đệm chỉ thị lệnh, 1 x 32 KB bộ đệm dữ liệu) Bộ nhớ đệm level 2: 512KB (2 x 256 KB) Bộ nhớ đệm level 3: 3 MB Bộ chỉ thị lệnh: 64 bit
Công suất tiêu thụ điện tối đa: 17W
b. GPU:
NVIDIA® GT 740M Kiến trúc: Kepler
Số lõi CUDA: 384 ( 2 nhân SMX) Khả năng tính toán: 3.5 Tốc độ xung đồng hồ bộ xử lý: 810 MHz Tốc độ xung đồng hồ bộ nhớ: 901-1802 MHz Độ rộng bus bộ nhớ: 128-bit Dung lƣợng bộ nhớ toàn cục: 1024 MB Dung lƣợng bộ nhớ đệm L2: 65536 byte
108
Dung lƣợng bộ nhớ không đổi: 65536 byte
Dung lƣợng bộ nhớ chia sẻ cho một khối: 49152 byte Tổng số thanh ghi khả dụng cho một khối: 65536 Kích cỡ cuộn: 32 luồng
Số lƣợng luồng tối đa trên một lõi đa nhân: 2048 Số lƣợng luồng tối đa mỗi khối: 1024
Kích cỡ tối đa của một khối luồng <x,y,z>: <1024,1024,64>
Kích cỡ tối đa của một lƣới ô luồng <x,y,z>: <2147483647,65535,65535>
c. Các thành phần khác
Mainboard Sony Vaio Intel® HM76
PCI Express phiên bản 2.0x8 dải (tốc độ: 32Gbit/s) Dung lƣợng bộ nhớ RAM: 4 GB
Loại bộ nhớ RAM: DDR3 1333 Hệ điều hành: Windows 8.1 64-bit
Phần mềm biên dịch: Microsoft Visual Studio 2010 NVIDIA CUDA Toolkit 7.0
GPU Intel HD Graphics 4000 (Khi chạy thí nghiệm, máy chạy ở chế độ sử dụng cạc màn hình này và GPU GT 740M chỉ dùng để tính toán chứ không dùng để xử lý đồ họa)
5.3.3. Kết quả thử nghiệm và đánh giá
Ta cho thực hiện bài toán sắp xếp một mảng số nguyên đầu vào đƣợc nhận giá trị tùy ý bằng hàm rand() trong C++ rồi đƣa vào để CPU và CPUGPU lần lƣợt xử lý rồi đo thời gian xử lý trên CPU và CPU-GPU khi thay đổi độ dài mảng đầu vào. Ngoài các thƣ viện sẵn có, chƣơng trình sử dụng thêm thƣ viện Thrust để thực thi sắp xếp dựa trên cơ số trên GPU. Ta thu đƣợc kết quả nhƣ hình 51 và bảng 10, 11.
109
Máy Kích cỡ mảng đầu vào 100,000 500,000 1,000,000 2,000,000 4,000,000
Dell E6420
Thời gian xử lý CPU-
GPU 0.035500 0.155800 0.303600 0.600800 1.194800 Thời gian xử lý CPU 0.017270 0.079670 0.159830 0.317830 0.631500 Tỷ lệ thời gian xử lý
CPU/CPU-GPU 0.486479 0.511361 0.526449 0.529011 0.528540
Vaio SVF14217
Thời gian xử lý CPU-
GPU 0.020200 0.082600 0.154500 0.295400 0.578400 Thời gian xử lý CPU 0.054000 0.251550 0.518550 1.040090 2.023000 Tỷ lệ thời gian xử lý
CPU/CPU-GPU 2.673267 3.045400 3.356311 3.520955 3.497580
Bảng 10: Thời gian xử lý bài toán sắp xếp dựa trên cơ số khi thay đổi số phần tử mảng đầu vào (1)
Hình 51: Thời gian sắp xếp mảng theo thuật toán sắp xếp dựa trên cơ số
0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5 Thời gian xử lý (s) Độ dài mảng xử lý (số phần tử)
Thời gian xử lý CPUGPU - Dell E6420
Thời gian xử lý CPU - Dell E6420
Thời gian xử lý CPUGPU - Vaio SVF14217
Thời gian xử lý CPU - Vaio SVF14217
110
Máy Kích cỡ mảng đầu vào 6,000,000 8,000,000 10,000,000
Dell E6420
Thời gian xử lý GPU 1.791800 2.366670 2.982670 Thời gian xử lý CPU 0.942000 1.131750 1.423000 Tỷ lệ thời gian xử lý
CPU/GPU 0.525728 0.478204 0.477089
Vaio SVF14217
Thời gian xử lý GPU 0.858300 1.141000 1.425000 Thời gian xử lý CPU 3.047360 4.016380 4.743170 Tỷ lệ thời gian xử lý
CPU/GPU 3.550460 3.520053 3.328540
Bảng 11: Thời gian xử lý bài toán sắp xếp dựa trên cơ số khi thay đổi số phần tử mảng đầu vào (2)
Từ đó ta thu đƣợc đồ thị thể hiện tỷ lệ thời gian xử lý bài toán giữa CPU và CPU-GPU ở hai máy tính thử nghiệm.
Hình 52: Tỷ lệ thời gian xử lý CPU/GPU khi thay đổi độ dài mảng xử lý
Trong bài toán sắp xếp này, thông số chạy kernel trên GPU sẽ do chƣơng trình tự quyết định bộ thông số nào đảm bảo hiệu suất của chƣơng trình là cao nhất.
0 0.5 1 1.5 2 2.5 3 3.5 4 Tỷ lệ thời gian xử lý CPU/GPU (lần) Độ dài mảng xử lý (số phần tử) Dell E6420 Vaio SVF14217
111
Trong thử nghiệm thứ hai này, ta sẽ chỉ tập trung vào đi sâu phân tích tỷ lệ thời gian xử lý. Từ hình 52, ta có thể thấy với máy tính Dell E6420 thì thời gian xử lý trên GPU thƣờng lâu gấp đôi so với thời gian xử lý trên CPU máy tính đó đồng thời thời gian xử lý ở GPU của máy tính Vaio SVF14217 lại nhanh gấp 3 lần so với thời gian xử lý trên CPU của máy tính đó. Nguyên nhân vì GPU của E6420 là NVIDIA NVS 4200M chỉ gồm 1 SM kiến trúc Fermi với 48 nhân CUDA (mỗi nhân đều có một đơn vị xử lý dấu phẩy động và số nguyên riêng) còn GPU của SVF14217 là GeForce GT 740M bao gồm 2 SMX kiến trúc Kepler với 384 nhân CUDA [35]. Do đó trong một xung đồng hộ của bộ xử lý SM/SMX thì GT 740M có thể xử lý đồng thời 160 phép tính cộng-nhân trên số nguyên có độ chính xác mở rộng còn với NVS 4200M là 48 phép tính [35]. Ngoài ra, tốc độ đƣờng bus PCIe của cả hai GPU với CPU đều là 32 Gbit/s nhƣng tổng thời gian xử lý trên GT 740M chỉ nhanh gấp đôi so với trên NVS 4200M theo bảng 10, 11. Điều này vì bài toán sắp xếp của ta tƣơng đối phức tạp, trong giai đoạn tính tổng liền trƣớc cần sử dụng tính năng đồng bộ rào chắn đồng thời các luồng trong một khối có sự trao đổi dữ liệu trên bộ nhớ chia sẻ của khối luồng. Do đó, tốc độ xử lý của bài toán còn phụ thuộc vào thời gian truy cập bộ nhớ chia sẻ và tính năng đồng bộ rào chắn của từng kiến trúc, số lƣợng thanh ghi sử dụng mỗi luồng.
5.4. Đánh giá hiệu năng của một nút tính toán trên bài toán tính nhanh biến đổi Fourier biến đổi Fourier
5.4.1. Biến đổi Fourier rời rạc và giải thuật tính nhanh biến đổi Fourier: 5.4.1.1. Biến đổi Fourier rời rạc
Biến đổi Fourier (FT – Fourier Trasform) là một biến đổi tích phân dùng để khai triển một hàm số (một tín hiệu) theo các hàm số sin cơ sở hoặc mũ phức (tín hiệu cơ sở), có nghĩa là dƣới dạng tổng hay một tích phân của các hàm số sin (hoặc mũ phức) đƣợc nhân với các hàm số khác nhau (hay còn gọi là biên độ) [35].
Biến đổi tích phân Fourier của tín hiệu thƣờng đƣợc định nghĩa bởi công thức:
112
∑
Còn biến đổi Fourier ngƣợc đƣợc tính bởi công thức sau:
∫
Biến đổi Fourier đƣợc ứng dụng rất nhiều trong khoa học nhƣ trong số học, xử lý tín hiệu, xác suất thống kê và rất nhiều lĩnh vực khác. Trong xử lý tín hiệu và các ngành liên quan, biến đổi Fourier đƣợc sử dụng để chuyển đổi tín hiệu thành các thành phần tín hiệu cơ sở. Phép biến đổi Fourier rời rạc (DFT – Discrete Fourier
Transform) là biến đổi Fourier cho các tín hiệu thời gian rời rạc. Đầu vào của biến đổi này là một chuỗi hữu hạn các số thực hoặc số phức. Giả sử là tín hiệu rời rạc có chiều dài hữu hạn L. Công thức biến đổi DFT N điểm ( ) của là:
∑
̅̅̅̅̅̅̅̅̅̅̅̅̅̅
Công thức biển đổi DFT ngƣợc:
∑
̅̅̅̅̅̅̅̅̅̅̅̅̅̅
Biến đổi DFT đƣợc sử dụng rộng rãi trong xử lý tín hiệu và các ngành liên quan đến phân tích tần số chứa trong một tín hiệu do biến đổi này có thể đƣợc tính nhanh bằng giải thuật tính nhanh biến đổi Fourier rời rạc (FFT – Fast Fourier Transform).
5.4.1.2. Giải thuật tính nhanh biến đổi Fourier (FFT)
Biến đổi Fourier nhanh là một thuật toán hiệu quả để tính biến đổi DFT và biến đổi ngƣợc lại. Tính trực tiếp DFT của N điểm đòi hỏi phép tính, trong khi FFT cũng trả về cùng kết quả trong phép tính.
113
Có nhiều thuật toán FFT nhƣng phổ biến nhất và cũng đƣợc sử dụng trong thử nghiệm này là thuật toán FFT Cooley-Tukey. Đây là một thuật toán chia để trị dùng đệ quy để chia bài toán tính DFT có kích thƣớc nhỏ hơn. Dạng phổ biến nhất của thuật toán Cooley-Tukey là chia biến đổi thành hai nửa kích thƣớc N/2 ở mỗi bƣớc (vì vậy chỉ dùng đƣợc cho kích thƣớc là lũy thừa của 2) nhƣng bất kì cách phân tích ra thừa số nào cũng đều có thể dùng đƣợc [35]. Đây là dạng cơ số 2 và dạng nhiều cơ số.
Việc tính toán DFT N điểm dùng giải thuật FFT cần có : phép nhân phức
: phép cộng phức
Hình 53: Sơ đồ FFT 8 điểm phân chia theo thời gian
5.4.2. Kết quả thử nghiệm và đánh giá
Ngoài các thƣ viện có sẵn, chƣơng trình sử dụng thêm thƣ viện C FFTW và CuFFT để triển khai FFT trên CPU và GPU. Thƣ viện FFTW là một thƣ viện miễn phí đƣợc phát triển dựa trên thuật toán FFT Cooley-Tukey đã trình bày ở trên. Thƣ viện CuFFT là thƣ viện miễn phí trong bộ CUDA Toolkit của NVIDIA và đƣợc phát triển dựa trên thƣ viện FFTW ở C. Hai thƣ viện này dùng để triển khai thuật
114
toán FFT và đƣợc tối ƣu để triển khai FFT trên các mảng có kích thƣớc là hàm mũ của 2,3,5,7 do đó ta cho máy tính Dell E6420 có cấu hình nhƣ đã trình bày ở phần 3.1.2 lần lƣợt chạy FFT từ miền số phức tới miền số phức với độ chính xác đơn trên tín hiệu đầu vào là các mảng một chiều có kích thƣớc là hàm mũ của 2,3,5,7 và