CHƢƠNG 1 : GIỚI THIỆU
2.6. Các chiến lƣợc tối ƣu hóa trên GPU
Không cân nhắc trƣớc khi sử dụng GPU có thể dẫn đến kết qủa không nhƣ ý muốn. Trong trƣờng hợp xấu nhất có thể cho kết quả sai hoặc tiêu tốn quá nhiều thời gian. Ví dụ, sẽ không hiệu quả nếu chạy thuật toán sử dụng một thread. Trong trƣờng hợp này phải thực hiện sao chép dữ liệu vào device, thực thi thuật toán trên device và sao chép dữ liệu trở lại host. Dữ liệu di chuyển giữa host và device là tốn nhất trong quá trình này, mặc dù với công nghệ ngày nay có thể cung cấp băng thông dữ liệu rất cao. Chúng ta cần nhận thấy rằng băng
thông trên device cũng nhƣ trên host lớn hơn nhiều so với băng trong kết nối giữa host và device.
Trƣớc khi viết một chƣơng trình GPU, cần phải xem xét các khía cạnh kết quả từ kiến trúc GPU. Kiểu lập trình GPU yêu cầu cách tiếp cận khác với lập trình CPU. Đó là do kiến trúc phần cứng và mô hình thực thi chƣơng trình. GPU hoạt động nhƣ một bộ xử lý song song với CPU. CPU rất mạnh trong thực thi mã tuần tự, trữ dữ liệu và xử lý luồng. Trong chƣơng trình GPU, CPU đóng vai trò nhƣ là đối tƣợng giám sát mã GPU. Nghĩa là CPU chỉ đảm nhận các hoạt động bộ nhớ cơ bản (cấp phát, giải phóng bộ nhớ GPU, chuyển dữ liệu giữa host và device) và gọi kernel. Các tính toán khác đƣợc thực hiện trong bộ nhớ GPU.
Có 4 chiến lƣợc thực thi chính để đạt đƣợc lợi ích thời gian lớn nhất từ GPGPU [3]:
- Tối đa hóa thực thi song song, - Tối ƣu hóa sử dụng bộ nhớ, - Tối ƣu hóa thực thi thread, - Tối ƣu hóa sử dụng chỉ lệnh.
2.6.1. Tối đa hóa thực thi song song
Tối đa hóa thực thi song song là chiến lƣợc cơ bản nhất, và chiến lƣợc trừu tƣợng nhất trong nhiều trƣờng hợp trong tính toán song song. Có hai cách để song song hiệu quả bài toán. Đầu tiên bao gồm phân rã vấn đề thành các vấn đề con và ánh xạ chúng vào các thực thi nguyên thủy (các khối thread, thread). Tiếp theo ánh xạ các thực thi nguyên thủy vào cấu trúc dữ liệu trong bộ nhớ. Chiến lƣợc thứ hai là ngƣợc lại của chiến lƣợc thứ nhất. Cần phải tìm cách ánh xạ dữ liệu vào các thực thi nguyên thủy để giải quyết bài toàn. Tùy thuộc vào bài toán đƣa ra để chọn chiến lƣợc cụ thể.
Nói chung, thuật toán bằng cách nào đó phản ánh đƣợc thực hiện phần cứng của thiết bị để đạt đƣợc hiệu quả lớn nhất, hơn nữa phải chắc chắn rằng thuật toán đƣợc ánh xạ vào hiệu quả phần cứng.
2.6.2. Tối ƣu hóa sử dụng bộ nhớ
Chiến lƣợc đầu tiên của việc tối ƣu hóa sử dụng bộ nhớ là giảm thiểu việc chuyển dữ liệu giữa host và device. Băng thông chuyển giữa host và device nhỏ hơn rất nhiều so với chuyển dữ liệu trong device và host. Tiếp đến là việc tối ƣu
Bộ nhớ chia sẻ làm việc giống L1cache trong một bộ đa xử lý và hầu nhƣ có chi phí truy cập bằng không, vì thế rất nhanh. Mỗi khối thread truy cập bộ nhớ chia sẻ của nó. Tối ƣu gồm chuyển dữ liệu từ bộ nhớ toàn cục sang bộ nhớ chia sẽ, thực hiện các tính toán trên dữ liệu của bộ nhớ chia sẽ, sau đó chuyển kết quả ngƣợc lại bộ nhớ toàn cục. Một điều quan trọng là, truy cập đến bộ nhớ chia sẻ phải đƣợc tổ chức hợp lý để tránh xung đột, vì bộ nhớ chia sẻ có thể truy cập song song bởi nhiều thread. Xung đột truy cập giữa các thread có thể dẫn đến thực thi tuần tự các yêu cầu bộ nhớ và làm mất hiệu suất tính toán.
Truy cập đến bộ nhớ toàn cục độ trễ rất lớn (hàng trăm chu kỳ đồng hồ), vì thế phải cẩn thận khi làm việc với dữ liệu trên bộ nhớ này. Hợp nhất truy cập bộ nhớ nghĩa là đọc từ một tập địa chỉ liên tục phải tƣơng ứng với tổ chức thread (số định danh thread). Hợp nhất truy cập bộ nhớ là vấn đề phụ thuộc thiết bị và không có chiến lƣợc chung.
Kỹ thuật tối ƣu bộ nhớ tiếp theo là sử dụng bộ nhớ constant và texture. Bộ nhớ constant và texture là bộ nhớ chỉ đọc (từ thiết bị-device), có thể bộ nhớ đệm, nên truy cập loại bộ nhớ này tƣơng đối nhanh. Ví dụ, để tiết kiệm bộ nhớ chia sẽ, chúng ta lƣu trữ một số đối số của kernel vào trong bộ nhớ constant. Bộ nhớ texture dùng cho các thao tác đồ họa.
2.6.3. Tối ƣu hóa thực thi các thread
Thread đƣợc tổ chức trong khối (block), đƣợc thực thi trên bộ đa xử lý. Mỗi khối của các thread đƣợc phân chia thành từng phần gồm 32 thread bởi đơn vị chỉ dẫn trong bộ đa xử lý và đƣợc thực thi trên bộ xử lý vô hƣớng. Việc đầu tiên để cải thiện hiệu suất là tạo khối thread (chứa số lƣợng thread là bội của 32). Điều này sẽ cung cấp hiệu quả tính toán tối ƣu và sẽ tạo điều kiện hợp nhất truy cập bộ nhớ.
Chiến lƣợc tối ƣu quan trọng nhất là tránh các đƣờng thực thi khác nhau trong cùng một warp (warp là một nhóm gồm 32 thread). Nếu một đƣờng thực thi của thread phân rã ở nhánh phụ thuộc dữ liệu, tất cả các thread không ở trên đƣờng này đƣợc dừng lại cho đến khi tất cả các đƣờng hội tụ lại cùng đƣờng thực hiện.
Hình 9: Phân rã tại nhánh phụ thuộc dữ liệu
Tất cả các lệnh điểu khiển (nhánh, lặp) có thể làm cho warp đang hoạt động phân rã.
2.6.4. Tối ƣu hóa sử dụng chỉ lệnh
Tối ƣu hóa các chỉ lệnh sử dụng trong hầu hết các trƣờng hợp là kỹ thuật tối ƣu có độ ƣu tiên thấp nhất và đƣợc thực hiện sau khi xong các tối ƣu trên. GPU đƣợc tối ƣu hóa cao cho các phép toán dấu phẩy động. Vì thế cần cân nhắc việc ƣu tiên cho tốc độ hay cho độ chính xác. Hiện nay GPU hỗ trợ số dấu phẩy động độ chính xác kép, nên có thể cung cấp chính tính toán chính xác hơn với chi phí thực hiện.
Nên cẩn thận khi chuyển đổi số chính xác đôi sang số chính xác đơn. Tránh dùng phép chia, phép chia lấy dƣ, thay vì thế nên dùng phép dịch chuyển.