1. Trang chủ
  2. » Luận Văn - Báo Cáo

Lập trình song song dữ liệu trên GPU OpenCL

35 1,6K 12

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 35
Dung lượng 2,01 MB

Nội dung

Lập trình song song dữ liệu trên GPU OpenCL

Trang 1

ĐẠI HỌC QUỐC GIA TP HỒ CHÍ MINH TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN

Trang 2

Mục lục

I Giới thiệu về OpenCL 4

1 Tổng quan 4

2 Lịch sử hình thành 5

3 Đặc điểm 5

3.1 OpenCL, một chuẩn lập trình mở 5

3.2 Tận dụng tối đa các tài nguyên có thể có của máy tính 5

4 Ngôn ngữ 6

5 Hạ tầng (Platform) 6

6 Tầm vực của OpenCL 7

II Kiến trúc OpenCL trên nền hệ điều hành Mac OS X 8

1 Sơ lược về Mac OS X 8

2 Framework & Runtime 8

3 Compiler 9

4 Operation Model 9

4.1 Platform Model 9

4.2 Execution Model 10

4.3 Memory Model 11

4.4 Programming Model 12

III Workflow phát triển chương trình OpenCL 13

1 Các bước viết một chương trình OpenCL 13

1.1 Xác định những nhiệm vụ nào có thể thực hiện song song 13

1.2 Viết các kernel và các hàm bổ trợ 13

1.3 Setup context 13

1.4 Viết mã lệnh để biên dịch và build chương trình OpenCL 13

1.5 Khởi tạo các đối tượng memory object 14 1.6 Lập hàng đợi lệnh có thứ tự (enqueue command) để điều khiển việc thực thi liên tục và đồng bộ các kernel, đọc và ghi dữ liệu, và thao tác trên các memory object 14

Trang 3

1.7 Đọc giá trị trả về 14

2 Viết Kernel 14

3 Truy vấn thiết bị 16

4 Khởi tạo OpenCL Context 16

5 Khởi tạo Program Object 17

6 Build Program Executable 19

7 Khởi tạo Kernel Object 22

8 Khởi tạo Memory Object 22

9 Thực thi các kernel 22

9.1 Xác định số chiều của dữ liệu: 23

9.2 Xác định số lượng work-item 23

9.3 Chọn kích thước cho work-group 23

9.4 Enqueue Kernel Execution 25

10 Nhận kết quả trả về 28

10.1 Chờ cho đến khi các kernel hoàn tất thực thi 28

10.2 Đọc kết quả 29

11 Giải phóng bộ nhớ 29

12 Debug chương trình OpenCL 29

IV Performance 31

1 GPGPU Performance 31

1.1 Số thực 31

1.2 Bandwidth 32

1.3 Nhận xét 32

2 CPU Performance 33

2.1 Số học 33

2.2 Bandwidth 34

2.3 Nhận xét 34

IV Tài liệu tham khảo 35

Trang 4

I Giới thiệu về OpenCL

1 Tổng quan

OpenCL (Open Computing Language) là chuẩn mở (công bố vào 12/2008) hỗ trợ lập trình song song trên các thiết bị (bao gồm cả GPU), được đề xuất bởi Apple và nhượng lại quyền phát triển cho Khronos Group Dù chỉ mới ra đời nhưng OpenCL lại nhận được rất nhiều sự hỗ trợ từ các nhà sản xuất phần cứng

Danh sách các nhà sản xuất phần cứng ủng hộ OpenCL

Trang 5

2 Lịch sử hình thành

OpenCL ban đầu được đề xuất và phát triển bởi Apple sau này được phát triển thêm với

sự hợp tác của AMD, IBM, Intel,và nVidia Sau đó Apple nhượng lại quyền phát triển cho Khronos Group (tổ chức đang nắm giữ các chuẩn mở khác như OpenGL, OpenAL…)

• 16/06/2008: Nhóm Khronos Compute Working được thành lập với các đại diện

đến từ các công ty CPU, GPU, thiết bị nhúng và các vi xử lý khác

• 18/11/2008: đưa ra đặc tả kĩ thuật OpenCL 1.0

• 08/12/2008: bản OpenCL 1.0 chính thức được phát hành

• 20/04/2009: nVidia ra mắt OpenCL driver và SDK để phát triển trong chương

trình OpenCL Early Access

• 05/08/2009: AMD giới thiệu công cụ phát triển đầu tiên cho nền tảng OpenCL như là một phần của chương trình ATI Stream SDK v2.0 Beta

sự ủng hộ của rất nhiều các nhà sản xuất

OpenCL được phát triển theo xu hướng tận dụng được tất cả các thiết bị tính toán

có thể thực thi song song Điều đó có nghĩa là nếu ta có một CPU đa nhân với OpenCL thì có thể lập trình để thực thi các tác vụ song song trên CPU đó Hơn nữa, OpenCL hỗ trợ lập trình song song tác vụ (task-parallel programming) và cả lập trình song song dữ liệu (data-parallel programming)

Trang 6

4 Ngôn ngữ

OpenCL sử dụng ngôn ngữ OpenCL-C dựa trên chuẩn C99 cho lập trình kernel và

IEEE-754 (chuẩn dấu chấm động cho số học) vì thế nên cú pháp hoàn toàn giống với C/C++

5 Hạ tầng (Platform)

Do được phát triển theo hướng độc lập với hạ tầng phần cứng nên OpenCL tự xây dựng một lớp phần cứng trừu tượng cho bản thân mình và độc lập hoàn toàn với hạ tầng phần cứng của thiết bị

Mô hình hạ tầng:

• Một host bao gồm nhiều Compute Device (Core – CPU / SM – GPU / …)

• Một Compute Device (CPU / GPU / …) bao gồm nhiều Compute Unit

• Một Compute Unit có thể được phân chia thành một hoặc nhiều Processing Element (vd: 1 SP trong SM GPU)

Trang 7

ATI:

• Radeon 4850

• Radeon 4870

Đối với CPU, OpenCL hỗ trợ các chip thuộc cả hai hãng lớn hiện nay là Intel và AMD

Do OpenCL vẫn còn khá mới cho nên chưa nhiều các hãng thiết kế phần cứng hỗ trợ chuẩn này Nhưng tương lai rất hứa hẹn khi OpenCL là chuẩn được nhiều “ông lớn” trong ngành công nghiệp phần cứng hỗ trợ nhất Và dù mới chỉ ra đời không lâu nhưng các đại gia này đã chính thức hỗ trợ OpenCL trong loạt sản phẩm hiệu năng cao của mình

Về nền tảng hệ điều hành: OpenCL có thể chạy được trên cả Mac OS X, Windows và

Linux

Trang 8

II Kiến trúc OpenCL trên nền hệ điều hành Mac OS X

1 Sơ lược về Mac OS X

Hệ máy Macintosh của Apple nổi tiếng vì thiết kế đẹp và tinh tế, hệ thống phần cứng cao cấp, sự tối đồng bộ tối ưu giữa phần cứng với phần mềm Hệ điều hành Mac OS X góp phần không nhỏ vào thành công đó nhờ vào tính đơn giản ổn định, hệ màu chuẩn, ít bị tổn hại cùng với các công nghệ tiên tiến (Grand Central Dispatch, 64-bit,…) trong đó có OpenCL, và có thể nói Mac OS X Snow Leopard 10.6 là hệ điều hành đầu tiên trực tiếp đưa OpenCL vào “Core” của mình

2 Framework & Runtime

OpenCL framework trong Mac OS X cung cấp

đầy đủ các headers cần thiết để dễ dàng thực

hiện biên dịch mã nguồn OpenCL cũng như

giao tiếp với OpenCL Runtime Chỉ đơn giản

với một dòng lệnh #include

<opencl.h>, ta có thể sử dụng các API của

OpenCL mà không cần phải khai báo gì thêm

trong chương trình

Theo hình vẽ minh họa bên, mô hình làm việc

của OpenCL cũng tương tự như CAL của ATI

hay CUDA của nVidia

Một điều dễ thấy là OpenCL runtime làm việc

trực tiếp với driver của phần cứng, vì thế một

số ý kiến cho rằng OpenCL chỉ là một chuẩn về

ngôn ngữ lập trình song song nên không thể chạy nhanh hơn CAL/CUDA là hoàn toàn sai lệch Vì làm việc trực tiếp với driver của phần cứng nên OpenCL runtime có thể coi như tương đương với CAL/CUDA và việc hiệu năng có thể cao hơn CAL/CUDA là bình thường

Một số hãng phần cứng như ATI đưa OpenCL vào bộ công cụ lập trình song song của mình, nhưng ở mức nào đó chỉ về mặt cú pháp hình thức chứ không sử dụng OpenCL

Trang 9

runtime và tầng giao tiếp với driver vẫn giữ CAL mà ko sử dụng OpenCL runtime Đó là

lý do STREAM chạy chậm hơn OpenCL vì một số nguyên nhân nào đó

3 Compiler

OpenCL compiler trong Mac OS X sử dụng LLVM Khi biên dịch một chương trình OpenCL, trước hết các chỉ thị trong chương trình đó sẽ được dịch sang một dạng biểu diễn trung gian (Intermediate Representation – IR) Sau đó, LLVM sẽ dịch và tối ưu hóa

IR sang mã phù hợp với thiết bị mà chương trình sẽ thực thi Điểm nhấn nằm ở chỗ: chương trình chỉ cần viết một lần nhưng vẫn có thể chạy trên nhiều kiến trúc phần cứng khác nhau Và ứng với mỗi hệ thống phần cứng, lần đầu tiên biên dịch của chương trình

sẽ được “cache” lại để tránh việc biên dịch trùng lặp không cần thiết

4 Operation Model

Sự vận hành của OpenCL được mô tả bởi cụm các model có mối liên hệ với nhau, bao gồm Platform Model (mô hình hạ tầng), Execution Model (mô hình thực thi), Memory Model (mô hình bộ nhớ), và Programming Model (mô hình lập trình)

Như đã nói ở trên, OpenCL

device sẽ làm việc với host

device – là device điều khiển

chương trình hoạt động Khi

chương trình thực thi, host sẽ

tạo ra một môi trường trừu

tượng hay còn gọi là môi

trường ảo (context) và cung

cấp các thiết bị tính toán (compute device) cùng với khoảng vùng nhớ nhất định

mà chương trình sẽ sử dụng Bên cạnh đó một “hàng đợi lệnh có thứ tự” (command queue) cũng sẽ được tạo ra để chương trình có thể điều phối các lệnh trong kernel và thực hiện các thao tác truy xuất tới bộ nhớ

Trang 10

Lưu ý: tốc độ truy xuất giữa các device sẽ chậm hơn rất nhiều so với tốc độ giao

tiếp nội bộ của các thành phần trong device đó và bản thân host device (vd: CPU) cũng có thể là một OpenCL device

Kernel: là một tập các lệnh được viết ra để thực thi trên một thiết bị hỗ trợ

OpenCL (OpenCL device) Tập các kernel và các hàm bổ trợ (helper function)

được gọi là Program

Khi biên dịch chương trình, các kernel được biên dịch thành kernel object và tương tự với program ta có program object

Việc thực thi một chương trình OpenCL bao gồm nhiều thực thi một cách đồng thời các instance của một kernel trên một hoặc nhiều OpenCL device trên command queue được điều phối bởi ứng dụng host (host application) Mỗi

instance của một kernel gọi là một work-item Mỗi work-item thực thi cùng một

đoạn mã lệnh nhưng trên các vùng dữ liệu khác nhau và mỗi một work-item chạy trên một single-core của multiprocessor Khi ấn định thực thi chương trình trên một device nào đó, ta xác định số lượng work-item cần thiết để hoàn tất việc xử lý

dữ liệu mà ta sẽ gọi là index space (không gian chỉ mục) OpenCL hỗ trợ index

space tối đa là 3 chiều

Các work-item có thể nhóm lại thành những work-group OpenCL cũng có cơ chế

đồng bộ hóa tính toán giữa các work-item trong một work-group nhưng không hỗ trợ tương tự giữa các work-group với nhau

Mỗi work-item trong chương trình có một định danh duy nhất - global ID để hỗ

trợ truy xuất trong index space Ví dụ, một work-item trong không gian chỉ mục 2 chiều có giá trị X là 23 và Y là 6 sẽ mang global ID (23, 6) Tương tự, mỗi work-

Trang 11

group cũng sẽ có một định danh duy nhất work-group ID, để xác định vị trí của

work-group trong index space

OpenCL cũng cho phép định vị trí của một work-item trong work-group thông qua

local ID

Ta có thể hình dung sự tương tự giữa OpenCL với CUDA, mỗi work-item tương

đương một thread, và mỗi work-group tương đương với một thread block

Memory object: là một handle tới vùng nhớ global (xem 4.3) được sử dụng để

lưu dữ liệu từ ứng dụng vào vùng nhớ của thiết bị để thao tác Có 2 loại chính:

buffer object và image object, với buffer object có thể chứa bất cứ loại dữ liệu

nào và image object được sử dụng đặc thù cho các dữ liệu ảnh Host application dùng command-queue để thực hiện thao tác đọc và ghi lên memory object

OpenCL phân chia tầm vực bộ nhớ vào bốn loại sau:

- Global memory: có thể đọc và ghi

bởi tất cả các work-item trong các

work-group Đây chính là vùng nhớ

được cấp phát đã mô tả trong Platform

Model

- Constant memory: là một vùng trên

global memory chỉ hỗ trợ việc đọc bởi

các work-item và giữ giá trị không đổi

suốt quá trình thực thi của một kernel

Giá trị trên constant memory được

cung cấp bởi host application

- Local memory: có thể được đọc ghi bởi một work-group đặc thù và giữ giá trị

chia sẻ bởi các work-item trong work-group đó

- Private memory: chỉ có thể truy xuất bởi một work-item duy nhất

Việc sử dụng bộ nhớ hiệu quả và tốc độ phụ thuộc rất nhiều vào cách dùng bốn loại bộ nhớ trên Trong đó private memory và local memory cho tốc độ cao nhất, vùng nhớ cho tốc độ truy xuất chậm chính là global memory

Trang 12

Các khái niệm về tầm vực của vùng nhớ trong OpenCL cũng tương tự với CUDA:

OpenCL hỗ trợ hai mô hình lập trình song song chính: song song dữ liệu

(data-parallel) và song song tác vụ (task-(data-parallel)

Các tiến trình song song dữ liệu thực thi nhiều instance có cùng kernel một cách đồng thời, mỗi instance xử lý một tập dữ liệu riêng biệt Mỗi tập dữ liệu liên kết với một điểm trong không gian chỉ mục một, hai hay ba chiều

Song song tác vụ lại tương tự như những tiến trình thực thi đa luồng có tính chất độc lập nhau, mỗi process thực hiện những nhiệm vụ khác nhau Trong OpenCL, lập trình song song tác vụ bao gồm việc lập hàng đợi nhiều kernel, và để OpenCL thực hiện chúng một cách song song sử dụng các thiết bị tính toán có thể có

Trang 13

III Workflow phát triển chương trình OpenCL

1 Các bước viết một chương trình OpenCL

Tiến trình phát triển một chương trình OpenCL bao gồm các bước dưới đây

Để chương trình đạt được hiệu quả cao nhất, trước tiên ta phải xác định những gì

có thể thực hiện đồng thời từ đó dễ dàng suy ra cách tổ chức bộ nhớ cũng như chi phí phù hợp cho chương trình

Để thực hiện tính toán song song trên OpenCL device, bắt buộc phải viết các kernel Các kernel được đóng gói và biên dịch khi chương trình thực thi

Sử dụng các hàm có trong OpenCL framework để tìm và quyết định thiết bị nào sẽ dùng trong chương trình Sau đó khởi tạo môi trường ảo bao gồm memory object

và command queue

Sau khi đã xác định được OpenCL device và setup context, chúng ta sẽ viết mã lệnh cho host application để biên dịch mã nguồn chương trình và sử dụng các kernel object

từ mã nguồn đã biên dịch Các lệnh sau được thực hiện liên tục theo thứ tự:

a Hàm clCreateProgramWithSource để khởi tạo chương trình từ mã nguồn OpenCL-C cho trước, hoặc nếu có sẵn đoạn mã đã được biên dịch trước đó (được

“cache” từ lần thực thi trước, ví dụ chương trình ngoài như các thư viện), gọi hàm clCreateProgramWithBinary Các hàm này sẽ liên kết các kernels và các

hàm bổ trợ vào một chương trình và trả về một program object

Trang 14

b Gọi hàm clBuildProgram để biên dịch program object phù hợp với các thiết

bị đặc thù đang có của hệ thống

clCreateKernelsInProgram để tạo các kernel object trong một chương trình OpenCL, hay nói khác đi, ta extract các đối tượng kernel đã được biên dịch

từ một program object cho trước

Để giữ các dữ liệu nhập xuất và trả về giá trị cho các đối số đầu vào (input object), memory object tham gia vào nhiệm vụ thao tác vùng nhớ giữa host device và OpenCL device

Để thực thi một kernel, ta phải tuân theo các bước sau:

a Gọi hàm clSetKernelArg để truyền các tham số đầu vào (parameter value) vào kernel

b Xác định kích thước work-group và lập index space để thực thi kernel

c Đưa lệnh thực thi kernel vào command queue

Enqueue command để đọc giá trị xuất từ work-item và đưa nó vào host memory

2 Viết Kernel

Kernel được viết bằng ngôn ngữ OpenCL-C có cú pháp giống với C với một số điểm riêng biệt Một kernel có dạng như sau:

Trang 15

Lưu ý:

1 Một kernel luôn được khai báo với tiết đầu tố kernel

2 Khi thực thi một kernel, ta dùng hàm clSetKernelArg để truyền giá trị vào các tham số được định nghĩa ở trên

3 Các hàm get_global_id và get_local_size để lấy thông tin về item khi thực thi kernel

work-4 mul24 là hàm toán học có sẵn trong OpenCL-C, và có rất nhiều hàm có khả năng tính toán hiệu suất cao được hỗ trợ sẵn cho cả dữ liệu có hướng lẫn vector

5 Kernel có thể được gọi từ một kernel khác trong cùng một chương trình OpenCL

Trang 16

3 Truy vấn thiết bị

Mỗi chương trình OpenCL đòi hỏi phải có một context, bao gồm danh sách các OpenCL device tồn tại trên hệ thống Sử dụng hàm clGetDeviceIDs để truy vấn danh sách thiết bị trên máy hỗ trợ OpenCL Ta có thể giới hạn việc truy vấn dựa vào đặc thù của loại thiết bị hoặc kết hợp các thiết bị (vd: chỉ dùng GPU, CPU hay kết hợp cả 2), bên cạnh đó ta cũng có thể giới hạn số lượng thiết bị muốn sử dụng

Ví dụ: giả sử chúng ta muốn thực thi code trên GPU và không quan tâm có bao nhiêu GPU sử dụng được vì ta chỉ cần một Ta gán CL_DEVICE_TYPE_GPU vào tham số device_type trong hàm clGetDeviceIDs và gán num_entires = 1, OpenCL sẽ trả về ID của GPU đầu tiên mà nó tìm thấy

4 Khởi tạo OpenCL Context

Một khi đã xác định được sẽ sử dụng OpenCL device nào để tính toán và có ít nhất một thiết bị sử dụng được, chúng ta bắt tay vào khởi tạo OpenCL context nhằm phục vụ cho việc nhónm các thiết bị lại với nhau để có thể chia sẻ vùng nhớ giữa các compute device, hoặc chúng ta cũng có thể khởi tạo context từ một OpenGL context đã tồn tại trước đó

Trang 17

nếu có nhu cầu kết hợp OpenGL và OpenCL với nhau Việc chia sẻ bộ nhớ giữa 2 context hoàn toàn có thể thực hiện được

Để khởi tạo một context, trước tiên ta phải xác định thiết bị nào sẽ dùng (kết quả trả về từ hàm clGetDeviceIDs), và truyền nó vào hàm clCreateContext

5 Khởi tạo Program Object

Một chương trình OpenCL bao gồm một tập các kernel, các hàm bổ trợ có thể gọi từ kernel (các kernel luôn phải bắt đầu bằng từ khóa kernel) Tuy nhiên, những hàm

bổ trợ này có thể không thực thi đúng vai trò như một entry point từ OpenCL API Có nghĩa là, ta chỉ có thể enqueue các kernel đã thông báo như trên Một program object đóng gói chương trình nguồn OpenCL, đi kèm với phiên bản thực thi được build lần trước của chương trình, cũng như build options, build log, và danh sách các thiết bị mà chương trình đã biên dịch để dùng trước đó

Ta có thể khởi tạo một program object trực tiếp từ mã nguồn của chương trình OpenCL

và biên dịch nó trực tiếp vào thời điểm thực thi ứng dụng (application runtime) Thêm vào đó, ta cũng có thể build program object sử dụng mã nhị phân của lần build thành công trước đó để tránh phải build khi thực thi ứng dụng

Ngày đăng: 28/05/2016, 10:29

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w