Chương 4: Môi trường phát triển (Development environment / 開発環境) & Nguyên lý hoạt động (Operating principle / 動作原理) của lập trình GPU

Estimated reading: 32 minutes 25 views

Từ lý do có thể sử dụng OpenCL trên Raspberry Pi đến những kiến thức cơ bản cần biết trước khi lập trình.

_____________________

Trong Phần 2, với tư cách là môi trường lập trình (Programming environment / プログラミング環境) dành cho GPU trên Raspberry Pi 4/5, chúng ta sẽ sử dụng OpenCL, một công cụ cũng thường xuyên được dùng trong lập trình xử lý song song (Parallel processing / 並列処理).

Bài viết này sẽ giải thích về những kiến thức cơ bản bạn cần biết trước khi bắt tay vào viết chương trình thực tế, chẳng hạn như môi trường phát triển phần mềm cho GPGPU, lý do tại sao Raspberry Pi có thể dùng được OpenCL, và cơ chế hoạt động của một chương trình trên GPU.

1. Kiến thức cơ bản về môi trường phát triển (Development environment / 開発環境) phần mềm cho GPGPU

● Các loại môi trường phát triển

Bảng 1 trình bày các môi trường phát triển phần mềm được sử dụng khi tiến hành lập trình GPGPU.

Hạng mụcWindows (CUDA)Windows (DirectX *1)Linux (CUDA)Linux (OpenCL)Linux (OpenGL ES)
GPU của NVIDIA
GPU của AMD××
GPU tích hợp trong SoC×→○ *2

*1: Sử dụng DirectCompute API được bao gồm trong DirectX 11.

*2: Bằng cách sử dụng clvk, khả năng hỗ trợ OpenCL chuyển thành ○ (Áp dụng cho Raspberry Pi 4/5).

Bảng 1: Môi trường phát triển phần mềm dành cho GPGPU

Raspberry Pi hiện cũng đã có thể sử dụng OpenCL

CUDAOpenCL là 2 nền tảng chủ đạo

Khi sử dụng GPU của hãng NVIDIA, việc dùng CUDA (Compute Unified Device Architecture) là phổ biến nhất. CUDA có ưu điểm là cung cấp sẵn nhiều thư viện (Library / ライブラリ) tiện lợi và chạy tốc độ cao (như tính toán ma trận / FFT / Học máy (Machine learning / 機械学習) v.v.), cộng với lượng người dùng đông đảo nên rất dễ tiếp cận với đa dạng các thông tin kỹ thuật về cách khai thác GPU.

Trong khi đó, khi sử dụng GPU của AMD hoặc Intel, việc sử dụng OpenCL (Open Computing Language) – chuẩn API dành cho GPGPU – lại là điều phổ biến.

OpenCL cũng có thể xài được trên Raspberry Pi!

Đối với loại GPU tích hợp trong SoC như trên Raspberry Pi, từ trước đến nay chúng ta không có lựa chọn nào khác ngoài việc sử dụng OpenGL ES chuyên trị xử lý đồ họa, hoặc sử dụng Vulkan vốn rất khó hiểu và khó tiếp cận. Lần này, bằng cách tận dụng phần mềm clvk được giới thiệu, hệ thống sẽ trở nên tương thích với OpenCL.

● OpenCL…API điện toán song song hỗ trợ đa dạng thiết bị

▶ Có thể dùng trên Nền tảng chéo (Cross-platform / クロス・プラットフォーム)

Ngôn ngữ lập trình Java từng lấy việc hiện thực hóa thế giới “Write once, run everywhere (Viết chương trình 1 lần, chạy được ở mọi nơi)” làm mục tiêu. Phiên bản phần cứng (Hardware / ハードウェア) kế thừa tư tưởng đó của Java chính là OpenCL.

OpenCL nhắm tới việc hiện thực hóa lý tưởng “Chỉ cần viết mã nguồn (Source code / ソースコード) một lần là chạy được trên bất kỳ phần cứng nào”. Bảng 2 thể hiện tổng quan về OpenCL. Mặc dù các thiết bị mục tiêu phát triển của OpenCL rất rộng, nhưng thiết bị tận dụng OpenCL nhiều nhất có lẽ là GPU. Như đã chỉ ra ở Bảng 1, trong khi CUDA là chuẩn độc quyền chỉ dùng được trên GPU của NVIDIA, thì điểm mạnh của OpenCL nằm ở chỗ nó là một tiêu chuẩn (Standard / 標準規格) được định ra bởi một hiệp hội công nghiệp. Do đó, ví dụ như một mã nguồn được phát triển cho Raspberry Pi hầu như không cần phải chỉnh sửa gì mà vẫn có thể đem chạy trơn tru trên GPU của hãng AMD.

Bảng 2: Tổng quan về OpenCL

API dành cho điện toán song song (Parallel computing / 並列コンピューティング) với mục tiêu hiện thực hóa khẩu hiệu “Chỉ cần viết mã nguồn (Source code / ソースコード) một lần là chạy được trên mọi phần cứng (Hardware / ハードウェア)”. Có thể dùng trên Nền tảng chéo (Cross-platform / クロス・プラットフォーム).

Hạng mụcDiễn giải
Mục đíchDùng một API duy nhất để lập trình cho nhiều loại bộ tăng tốc (Accelerator / アクセラレータ) khác nhau nhằm tăng tốc (Acceleration / 高速化) quá trình tính toán. Viết tắt của Open Computing Language.
Thiết bị mục tiêuGPU / CPU / DSP / FPGA v.v.
Ngôn ngữ viết mãC / (C++)
Đặc điểm

○ Nhờ tiến hành biên dịch (Compile / コンパイル) mã nguồn ngay tại thời điểm chạy chương trình*, một chương trình duy nhất có thể hoạt động trên nhiều thiết bị khác nhau (ngoại trừ một số ngoại lệ như FPGA).

× Có đôi chút khiên cưỡng khi xử lý các thiết bị có số lượng tài nguyên và đặc tính tính toán khác nhau bằng cùng một API thống nhất (Ví dụ: mã nguồn đã được tối ưu hóa cho GPU sẽ không hoạt động một cách hiệu quả trên FPGA).

*: Cơ chế biên dịch lúc chạy chương trình cũng mang lại một nhược điểm là làm cho việc viết mã chương trình trở nên rườm rà phức tạp hơn.

▶ Lợi ích khi sử dụng OpenCL

① Hiệu suất phát triển chương trình cao hơn so với Vulkan (Tóm lại là phát triển phần mềm nhàn hơn)

② Dễ dàng thu thập thông tin tham khảo và mã mẫu (Sample code / サンプル・コード) hơn Vulkan

③ Mở rộng dung lượng dữ liệu có thể cấp phát một lần trên các địa chỉ liên tiếp (Từ 64 MByte → 1023 MByte)

④ Hỗ trợ tính toán số dấu phẩy động (Floating point calculation / 浮動小数点演算)

⑤ Hiện thực hóa tính năng xử lý không sao chép (Zero-copy processing / ゼロ・コピー処理)

※ Các mục ③, ④, ⑤ là những lợi ích khi đem so sánh với OpenGL ES API.

2. Môi trường phát triển phần mềm của GPU trên Raspberry Pi

● Các API mà GPU Raspberry Pi hỗ trợ

▶ 2 loại là OpenGL ESVulkan

Các API được hỗ trợ bởi nhân VideoCore VI/VII tích hợp trên Raspberry Pi 4/5 chỉ có OpenGL ESVulkan – những API vốn dành cho mục đích đồ họa. Bằng cách tận dụng chức năng Compute Shader (コンピュート・シェーダ) mà cả 2 API này cung cấp, dù có cảm giác hơi miễn cưỡng, nhưng về cơ bản chúng ta vẫn có thể khai thác GPU trên Raspberry Pi 4/5 cho mục đích lập trình GPU đa dụng (GPGPU).

Tuy nhiên, vì OpenGL ES suy cho cùng là một API có nghề chính là lập trình đồ họa, nên nó khá khó xài khi đưa vào mục đích GPGPU, và có nhiều ràng buộc (Constraint / 制約事項) khiến phạm vi ứng dụng bị thu hẹp (Ví dụ như không xử lý được dữ liệu dấu phẩy động).

Vulkan có hiệu năng cao nhưng lại khó sử dụng

Vulkan là một API tương đối mới và được quảng bá với hiệu năng cao (tức là Overhead (Tổn hao tài nguyên / オーバヘッド) thấp), nhưng nó lại mang thông số kỹ thuật ở mức rất thấp (Low-level). Vì lý do đó, số lượng dòng mã nguồn (Source code / ソースコード) phải viết để thực hiện một ý đồ nào đó trở nên cực kỳ lớn, kéo theo nhược điểm là hiệu suất phát triển phần mềm tương thích không được tốt cho lắm.

Nói một cách dễ hiểu về mức độ khó xài của Vulkan thì nó sẽ như thế này: Giả sử bạn có 100 dòng mã nguồn được viết theo chuẩn OpenGL ES, nếu bạn muốn tạo một chương trình làm được y hệt như vậy bằng Vulkan, số lượng dòng mã nguồn sẽ phình to ra thành cỡ 300 ~ 400 dòng. Do đó, nếu xét theo tiêu chí muốn phát triển chương trình một cách thoải mái cho các ứng dụng (Application / アプリケーション) thông thường, thì không thể nói Vulkan API là một môi trường lập trình (Programming environment / プログラミング環境) thích hợp.

▶ Dùng chung phần mềm nguồn mở (OSS) để xài được OpenCL API vừa xịn vừa dễ

Thật may mắn, bằng cách sử dụng kết hợp một phần mềm mã nguồn mở (Open source / オープンソース), chúng ta có thể tiến hành lập trình GPGPU thông qua việc tận dụng OpenCL API, một công cụ dễ lập trình hơn hẳn so với Vulkan.

● Phần mềm chuyển đổi OpenCL/Vulkan mang tên “clvk”

Trên GitHub (https://github.com/), một nền tảng nơi các nhà phát triển phần mềm trên toàn thế giới đăng ký/quản lý mã nguồn và thực hiện các công việc cộng tác, có một phần mềm mang tên clvk đang được công bố. Giải thích về clvk trong một câu, nó chính là trình giả lập (Emulator / エミュレータ) OpenCL API hoạt động trên nền tảng Vulkan API. Khi một ứng dụng gọi OpenCL API, clvk sẽ dịch các yêu cầu công việc từ ứng dụng đó thành các lời gọi Vulkan API và thực thi chúng.

Bằng cách sử dụng clvk, OpenCL sẽ được bổ sung thêm vào danh sách các APIGPU Raspberry Pi 4/5 hỗ trợ. Chỉ cần cài đặt mỗi một phần mềm, bạn sẽ sở hữu ngay trong tay một môi trường OpenCL hỗ trợ lập trình GPGPU chuyên sâu, vừa dễ học vừa có hiệu suất phát triển cao. Nhân tiện, nguồn gốc cái tên phần mềm clvk này có lẽ được suy ra từ “(open) CL to V(ul)K(an)”.

● Lý do có thể sử dụng OpenCL trên Raspberry Pi

▶ Mấu chốt nằm ở phiên bản của Trình điều khiển GPU (GPU Driver / GPUドライバ)

Theo các thông tin chính thức lúc phát hành Raspberry Pi 5, nhân VideoCore VII (Broadcom) tích hợp trong SoC hỗ trợ OpenGL ES 3.1Vulkan 1.2. Tuy nhiên, đây mới chỉ đơn thuần là việc trang bị sẵn các chức năng cần thiết để hỗ trợ những API này ở cấp độ phần cứng (Hardware / ハードウェア). Trên thực tế, nếu không xài đúng cái Driver (Trình điều khiển / ドライバ) hỗ trợ các API đó thì bạn sẽ không thể xài được.

Tại thời điểm viết bài này, khi tôi kiểm tra nội dung bản phát hành mới nhất của Raspberry Pi OS (ngày 19/11/2024), đúng như Bảng 3 đã chỉ ra, GPU Driver đi kèm trong hệ điều hành này hơi cũ so với bản mới nhất và người ta phát hiện ra nó chưa hỗ trợ cho hoạt động của clvk (Chú thích 1).

Chú thích 1: Để sử dụng clvk, bạn cần có phần mở rộng VK_KHR_storage_buffer_storage_class (https://raspberrypi.stackexchange.com/questions/143316/opencl-on-rpi-400).

Bảng 3: Kết quả kiểm tra thông tin phiên bản GPU Driver trên từng hệ điều hành đối với Raspberry Pi 4/5

Nếu sử dụng Ubuntu 24.10, bạn có thể dùng được phiên bản Driver hỗ trợ cho hoạt động của clvk

OSHạng mụcRaspberry Pi 4Raspberry Pi 5
Ubuntu 24.10 Kernel: 6.11.0-1009-raspiapiVersion1.2.2891.2.289
 driverVersion24.2.824.2.8
 deviceNameV3D 4.2.14.0V3D 7.1.7.0
 Hoạt động của clvk
Raspberry Pi OS 2024/11/19 Kernel: 6.6.51+rpt-rpi-2712apiVersion1.2.2551.2.255
 driverVersion23.2.123.2.1
 deviceNameV3D 4.2.14V3D 7.1.7
 Hoạt động của clvk××

▶ Dùng Ubuntu 24.10 sẽ xài được phiên bản GPU Driver mới

Sau đó, tôi đã tiến hành điều tra về tình hình của các bản phân phối Linux (Distribution) khác tương thích với Raspberry Pi. Kết quả là tôi phát hiện ra: nếu sử dụng Ubuntu 24.10, chúng ta có thể xài được một phiên bản GPU Driver mới hơn, có hỗ trợ cho hoạt động của clvk.

Vì vậy trong bài viết này, chúng ta sẽ sử dụng môi trường cài đặt Ubuntu 24.10 trên Raspberry Pi 4/5 làm môi trường phát triển chương trình (Program development environment / プログラム開発環境) dành cho GPU tích hợp trên Raspberry Pi.

3. Cơ chế hoạt động của chương trình trên GPU

● Quy trình chạy một chương trình bằng GPU

Bảng 4 trình bày tuần tự các giai đoạn khi một chương trình hoạt động bằng GPU.

Bảng 4: Cách chương trình hoạt động bằng GPU

Bước (Step)Luồng dữ liệu (Data flow)Xử lý phía CPUXử lý phía GPU
1

CPU ⇔ GPU

Bộ nhớ chính [Sao chép dữ liệu cần xử lý của GPU] ⇔ VRAM

① Chỉ thị cho GPU truyền dữ liệu② Thực hiện quá trình sao chép dữ liệu từ Bộ nhớ chính sang VRAM
2

CPU ⇔ GPU

Bộ nhớ chính [Các xử lý GPU đa dạng] ⇔ VRAM

Biên dịch (Compile / コンパイル) chương trình GPU

④ Chỉ thị cho GPU chạy chương trình

⑤ Thực thi chương trình GPU

(Mã thiết bị / Mã hạt nhân)

3

CPU ⇔ GPU

Bộ nhớ chính [Sao chép kết quả xử lý của GPU] ⇔ VRAM

⑥ Chỉ thị cho GPU truyền kết quả xử lý về

(Mã máy chủ)

⑦ Thực hiện quá trình sao chép dữ liệu từ VRAM về Bộ nhớ chính

▶ Bắt buộc phải sao chép dữ liệu giữa Bộ nhớ chínhVRAM

Dữ liệu đầu vào cần xử lý bằng GPU có thể là dữ liệu hình ảnh được chụp từ camera, hoặc dữ liệu hình ảnh được đọc từ file; trong mọi trường hợp, chúng đều nằm trên Bộ nhớ chính (Main memory / メイン・メモリ) ở phía CPU. Mặt khác, về cơ bản GPU chỉ có thể truy cập vào những dữ liệu nằm trên VRAM.

Do đó, khi muốn giao việc cho GPU, điều đầu tiên phải làm là sao chép dữ liệu đối tượng từ Bộ nhớ chính sang VRAM. Tiếp theo, phía CPU chính sẽ biên dịch (Compile / コンパイル) mã nguồn của chương trình GPU, đem cái Mã máy trần GPU (GPU Native code / GPU向けネイティブ・コード) thu được chép vào VRAM, rồi ra lệnh cho GPU chạy chương trình, khi đó việc thực thi chương trình ở phía GPU mới được bắt đầu. Đơn giản hóa quá trình xử lý ở phía GPU, nó sẽ theo luồng: Đọc dữ liệu đầu vào từ VRAM, tiến hành xử lý tính toán, rồi ghi lại kết quả xử lý vào VRAM. Cuối cùng, kết quả xử lý của GPU trên VRAM sẽ được sao chép trả về Bộ nhớ chính, lúc này phần việc giao phó cho GPU mới được xem là hoàn tất.

GPU… Tuy cách xài hơi cồng kềnh nhưng lại vô cùng xuất sắc

Như vậy, khi tiến hành lập trình GPGPU, nếu bạn không trải qua hàng loạt thủ tục rườm rà vòng vo thì sẽ không thể nào hiện thực hóa được quá trình xử lý GPU. Nếu việc gửi yêu cầu công việc từ CPU sang GPU không được thực hiện một cách hiệu quả, rất có thể sẽ phát sinh tình trạng giống như một người sếp cảm thấy tự mình làm luôn cho nhanh còn hơn là giao việc cho cấp dưới. Tuy nhiên, cậu cấp dưới khó chiều (= GPU) này lại sở hữu năng lực tính toán xuất chúng hơn người, do đó dưới tư cách là một người sếp, để tối đa hóa hiệu suất của toàn công ty (= Toàn bộ hệ thống), bạn bắt buộc phải học cách sử dụng nhuần nhuyễn cậu cấp dưới này.

● Mã máy chủ (Host code) và Mã thiết bị (Device code)

Khi lập trình GPGPU, bạn cần phải tạo ra cả hai thứ: chương trình chạy trên CPU chính (Mã máy chủ – Host code) và chương trình chạy trên GPU (Mã thiết bị – Device code). Giữa các nhà nghiên cứu và lập trình viên chuyên về phần mềm GPU, họ thường gọi cái “Mã thiết bị” này bằng thuật ngữ “Mã hạt nhân” (Kernel code), vì vậy trong Phần 2 này, chúng ta sẽ quy ước gọi các chương trình chạy trên GPU là Mã hạt nhân (Kernel code / カーネル・コード).

▶ Mã máy chủ (Host code / ホスト・コード) chạy trên CPU

Đối với các phần mềm thông thường chạy trên PC, tức là các chương trình hoạt động trên CPU chính (nếu nói theo ngôn ngữ của OpenCL thì nó tương ứng với Host code), thông thường người ta sẽ biên dịch & liên kết (Compile & Link / コンパイル&リンク) mã nguồn của chương trình đó để tạo ra các file thực thi (Executable file) từ trước khi mang ra chạy. Việc biên dịch sẵn mã nguồn trước khi chạy như vậy được gọi là Biên dịch ngoại tuyến (Offline Compile / オフライン・コンパイル).

▶ Mã hạt nhân (Kernel code / カーネル・コード) cho GPU thực thi

Trái lại, đối với Kernel code của OpenCL hoạt động trên GPU, mã nguồn sẽ được biên dịch động (Dynamic / 動的) ngay tại thời điểm chương trình chạy nhằm sinh ra các đoạn mã nhị phân (Binary code / バイナリ・コード) có khả năng thực thi trên thiết bị mục tiêu (Target device). Việc tiến hành biên dịch mã nguồn vào lúc runtime như thế này được gọi là Biên dịch trực tuyến (Online Compile / オンライン・コンパイル).

Bằng cách áp dụng cơ chế này, một đặc tính Nền tảng chéo (Cross-platform / クロス・プラットフォーム) tuyệt vời được tạo ra: một chương trình có chung một mã nguồn (Source code / ソースコード) có thể hoạt động trơn tru trên nhiều thiết bị đa dạng có hỗ trợ OpenCL.

● Ngôn ngữ lập trình cho GPGPU… Cơ bản là ngôn ngữ C

Bảng 5 chỉ ra các ngôn ngữ phát triển được sử dụng khi lập trình GPGPU. Về cơ bản, cho dù bạn sử dụng môi trường phát triển nào, điểm chung cốt lõi vẫn là phát triển các chương trình dựa trên ngôn ngữ C. Tuy nhiên về phía Mã máy chủ (Host code), ví dụ như bằng cách xài thêm gói PyOpenCL, bạn hoàn toàn có thể viết các ứng dụng OpenCL bằng Python. Trong khuôn khổ bài viết này, để giải thích tường tận những điều cơ bản và cơ chế của OpenCL, chúng ta sẽ theo hướng viết Mã máy chủ bằng ngôn ngữ C cốt lõi.

Bảng 5: Ngôn ngữ lập trình được sử dụng trong các môi trường phát triển dành cho GPGPU

Trong bài viết này, chúng tôi sử dụng ngôn ngữ C cơ bản nhất để viết Mã máy chủ (Host code)

Môi trường phát triểnMã máy chủ (Host code)Mã hạt nhân (Kernel code)
OpenCLCó rất nhiều như C/C++/PythonC/C++
CUDACó rất nhiều như C/C++/PythonC/C++ (chỉ một phần cú pháp)

4. Cơ chế thực thi Mã hạt nhân (Kernel code) của OpenCL trên Raspberry Pi

● Quy trình từ lúc bắt đầu cho đến khi Mã hạt nhân (Kernel code) được thực thi

Hình 1 minh họa luồng quá trình diễn ra trên Raspberry Pi 4/5, sử dụng phần mềm lớp tương thích OpenCL clvk, từ lúc Kernel code của OpenCL được biên dịch cho đến lúc nó được thực thi trên GPU.

Nhìn từ phía các chương trình của người dùng xài OpenCL API, clvk trông giống như là libOpenCL, một thư viện thời gian chạy (Runtime Library / ランタイム・ライブラリ) dành cho các ứng dụng OpenCL. Để thực thi Kernel code trên GPU, các chương trình người dùng cần truyền mã nguồn của Kernel sang cho clvk, sau đó phải ra chỉ thị biên dịch đoạn mã đó thành Mã máy trần GPU (Mã máy / GPU Native code / GPUネイティブ・コード – tức là dạng chương trình ngôn ngữ máy mà các Phần tử xử lý bên trong GPU có khả năng chạy được) và thực thi chúng.

Hình 1: Luồng xử lý từ lúc sử dụng phần mềm lớp tương thích OpenCL clvk cho đến khi thực thi Mã hạt nhân trên GPU

Chương trình người dùng OpenCL (Mã máy chủ / Mã hạt nhân)

— [Mã C] –>

Thư viện thời gian chạy (Runtime Library) [clvk –(Mã SPIR-V*)–> Vulkan Driver]

— [Mã máy trần GPU (GPU Native code)] –>

GPU

*: SPIR-V (Standard Portable Intermediate Representation for Vulkan) là một ngôn ngữ trung gian (Intermediate language / 中間言語) được phát triển bởi Khronos Group, với mục đích sử dụng cho Vulkan – API đồ họa thế hệ tiếp theo.

● Cách hoạt động của clvk

Khi nhận được yêu cầu biên dịch và thực thi Kernel code, clvk sẽ thực hiện các xử lý sau ở bên trong:

① Chuyển đổi mã C sang mã SPIR-V – một ngôn ngữ trung gian (Intermediate language).

② Trình điều khiển Vulkan (Vulkan Driver) sẽ biên dịch mã SPIR-V đó thành Mã máy trần GPU (GPU Native code) và thực thi nó trên GPU.

Trong các môi trường chạy OpenCL truyền thống, phương pháp gộp một phát biên dịch (Compile / コンパイル) thẳng từ Mã hạt nhân (được viết bằng ngôn ngữ C) ra thành Mã máy trần GPU là điều phổ biến. Nhưng trong những năm gần đây, một cấu trúc 2 giai đoạn (2段構え / Two-stage) đang trở thành tiêu chuẩn chung: Mã C trước hết sẽ được chuyển đổi sang mã SPIR-V, một dạng ngôn ngữ trung gian sử dụng chung cho nhiều dòng máy, độc lập với phần cứng GPU (Đây là Xử lý Front-end / フロントエンド処理). Sau đó, các trình biên dịch chuyên biệt được chuẩn bị sẵn cho từng loại GPU ở phía sau sẽ đón lấy đoạn mã SPIR-V này và tiếp tục dịch nó thành Mã máy trần GPU (Đây là Xử lý Back-end / バックエンド処理).

Lý do người ta đi đến quyết định áp dụng cấu trúc này là vì muốn chia tách trình biên dịch thành “phần độc lập với phần cứng” và “phần phụ thuộc phần cứng”, qua đó giúp cho việc phát triển bản thân trình biên dịch trở nên dễ dàng hơn.

Phần độc lập phần cứng (Hardware-independent part): Chịu trách nhiệm phân tích mã nguồn ngôn ngữ C và thực hiện tối ưu hóa.

Phần phụ thuộc phần cứng (Hardware-dependent part): Chuyển đổi ngôn ngữ trung gian đã được tối ưu hóa sang Mã máy trần GPU (GPU Native code).

Tuy nhiên, dưới tư cách là những người chỉ xài clvk đơn thuần, người dùng không cần thiết phải thấu hiểu quá chi tiết về hoạt động ngầm bên trong clvk. Bạn chỉ cần viết chương trình ứng dụng tuân thủ theo những quy tắc của OpenCL API, phần còn lại clvk sẽ tự thân nỗ lực xoay xở để hiện thực hóa các hoạt động của Kernel trên GPU Raspberry Pi giúp bạn.

● Môi trường thực thi của chương trình OpenCL

Hình 2 minh họa cấu trúc môi trường thực thi của chương trình OpenCL. Điều này là điểm chung đối với cả OpenCL và CUDA: Khi bạn cài đặt toàn bộ gói Driver (Trình điều khiển) do các hãng sản xuất GPU cung cấp, ngoài phần Driver GPU hoạt động ở Kernel mode (Chế độ hạt nhân hệ điều hành / カーネル・モード), nó cũng sẽ cài đặt luôn các Thư viện thời gian chạy (Runtime Library / ランタイム・ライブラリ) hoạt động ở không gian người dùng (User space / ユーザ・ランド).

Trong trường hợp phần mềm clvk chúng ta sử dụng lần này, libOpenCL.so (Lớp tương thích OpenCL) và clspv (Trình biên dịch OpenCL sang SPIR-V) sẽ được cài đặt. Ngoài ra, thứ tương đương với Vulkan Driver thực ra cũng được triển khai như một thư viện chia sẻ (Shared Library) thông thường chạy trên User space (mang tên libvulkan_broadcom.so). Cả cái thư viện chia sẻ cung cấp Vulkan API này lẫn trình biên dịch SPIR-V sang GPU đều được phát triển như một phần của dự án mã nguồn mở Mesa 3D graphics library.

Hình 2: Cấu trúc môi trường thực thi của chương trình OpenCL

Chương trình ứng dụng (Application program) [Ứng dụng OpenCL]

↓↑

libOpenCL.so [Lớp tương thích OpenCL (clvk)]

↓↑

clspv [Trình biên dịch OpenCL sang SPIR-V (clvk)]

↓↑

libvulkan_broadcom.so [Thư viện cung cấp Vulkan API (Mesa)]

↓↑

Trình biên dịch SPIR-V [Trình biên dịch SPIR-V sang GPU (Mesa)]

↓↑

v3d.ko [Trình điều khiển GPU (Linux Kernel)]

↓↑

GPU (VideoCore VI/VII) [Phần cứng GPU]

Cột thông tin (Column / コラム): Báo trước loạt bài ngắn kỳ… Bắt tay làm Ứng dụng GPU với Raspberry Pi x OpenCL

Bắt đầu từ số báo tháng 7 năm 2025, chúng tôi dự kiến sẽ đăng tải một loạt bài viết ngắn hướng dẫn cách phát triển các chương trình ứng dụng thực tế, sử dụng môi trường lập trình GPGPU thông qua Raspberry Pi 4/5 và clvk đã được giới thiệu trong Phần 2.

Cụ thể, chúng tôi sẽ giới thiệu các tình huống phát triển chương trình ứng dụng như sau:

・Chuyển đổi ảnh RGB sang Grayscale

・Chuyển đổi ảnh RGB sang ảnh nhị phân (Binary image)

・Các phép tính Bộ lọc (Filter calculation / フィルタ演算)

・Giới hạn hiệu năng của GPU trên Raspberry Pi, v.v.

Trong thực tế, bạn sẽ không chỉ cắm cúi viết chương trình, mà chúng tôi còn giải thích thêm về cách tăng tốc xử lý thông qua việc áp dụng các kỹ thuật tối ưu hóa đã được đề cập từ Chương 6 của Phần 2 trở đi. Chỉ với 1 chiếc Raspberry Pi, bạn có thể học được các kỹ thuật tăng tốc cực kỳ hữu dụng trong thực tiễn.

Khác

Bảng so sánh tổng hợp các môi trường phát triển.

Tiêu chíKhả năng tương thíchBản chấtLĩnh vực thống trịƯu điểm lớn nhấtNhược điểm lớn nhất
OpenGLĐa nền tảng (Win, Mac, Linux, Mobile)Tiêu chuẩn MởĐồ họa 3D cơ bản, hệ thống cũDễ học, chạy được trên hầu hết mọi thiết bị từ cũ đến mớiKiến trúc lỗi thời, gây nghẽn cổ chai CPU (overhead cao)
DirectX 12Chỉ Windows, XboxĐộc quyền (Microsoft)Game PC AAA, Game XboxTối ưu hóa đỉnh cao cho phần cứng và hệ sinh thái WindowsKhông thể mang code sang Mac hay Linux
VulkanĐa nền tảng (Win, Linux, Android, Mac)Tiêu chuẩn MởGame đa nền tảng, Giả lập, Mobile GamingHiệu năng vô địch (ngang DX12), tận dụng tối đa CPU đa nhân, không bị khóa vào hệ điều hành nàoCode vô cùng phức tạp và dài dòng, đòi hỏi trình độ lập trình rất cao
CUDAChỉ chạy trên GPU NVIDIAĐộc quyền (NVIDIA)AI, Deep Learning, Render 3DHiệu năng tính toán song song số 1, hệ sinh thái thư viện cực kỳ mạnh và dễ dùngBị khóa chặt (vendor lock-in) vào phần cứng của NVIDIA
OpenCLMọi thiết bị (NVIDIA, AMD, Intel, ARM…)Tiêu chuẩn MởTính toán khoa học trên phần cứng Non-NVIDIAChạy được tính toán trên cả CPU, GPU và FPGA của nhiều hãngCode phức tạp, hiệu năng thực tế thường kém hơn CUDA trên cùng cấu hình

Leave a Comment

Chia sẻ:

Chương 4: Môi trường phát triển (Development environment / 開発環境) & Nguyên lý hoạt động (Operating principle / 動作原理) của lập trình GPU

Or copy link

CONTENTS