Cách hiểu về GPU
(jax-ml.github.io)- GPU đóng vai trò cốt lõi trong machine learning hiện đại, với cấu trúc kết hợp nhiều Streaming Multiprocessors (SMs) chuyên cho phép toán nhân ma trận tốc độ cao và HBM (bộ nhớ băng thông cao)
- SM của GPU được chia thành Tensor Core (nhân ma trận) và CUDA Core (phép toán vector), hỗ trợ tính toán song song quy mô lớn và lập trình linh hoạt
- GPU và TPU khác nhau về cấu trúc bên trong và cấu hình mạng; GPU có tính đa dụng và khả năng mở rộng cao hơn, nhưng để đạt hiệu năng tối ưu cần cân nhắc nhiều hơn
- Trong node, các GPU có thể giao tiếp siêu tốc qua NVLink và NVSwitch; giữa các node, chúng được kết nối bằng mạng như InfiniBand để phục vụ huấn luyện phân tán quy mô lớn
- Collectives trên GPU (ví dụ: AllReduce, AllGather) có hiệu năng thay đổi đáng kể theo cấu trúc phần cứng và các tầng mạng, và trên thực tế thường thấp hơn băng thông lý thuyết
GPU là gì?
- GPU ML (machine learning) hiện đại (ví dụ: H100, B200) có cấu hình gồm hàng chục đến hàng trăm Streaming Multiprocessor (SM) chuyên cho phép toán nhân ma trận, kết hợp với bộ nhớ HBM tốc độ cao
- Mỗi SM có Tensor Core (nhân ma trận), Warp Scheduler (phép toán vector), SMEM (cache on-chip)
- Khác với TPU, GPU có thể xử lý song song linh hoạt ở quy mô lớn hơn thông qua hơn 100 SM
Cấu trúc chi tiết của SM
- SM được chia thành 4 subpartition, và mỗi subpartition đều có Tensor Core, CUDA Core (phép toán vector), Warp Scheduler, register file riêng
- CUDA Core phụ trách phép toán số học vector (SIMD/SIMT), còn Tensor Core được tối ưu riêng cho nhân ma trận
- FLOPs của Tensor Core vượt trội áp đảo, và với phép toán độ chính xác thấp thì tốc độ xử lý còn cao hơn nữa
- GPU mới nhất (ví dụ: B200) bổ sung TMEM dung lượng lớn để hỗ trợ đầu vào Tensor Core cỡ lớn
Tính linh hoạt của CUDA Core
- CUDA Core của GPU sử dụng mô hình SIMT (Single Instruction Multiple Threads), thực thi song song một lệnh trên nhiều thread
- Mỗi thread có con trỏ lệnh độc lập (program counter), mang lại tính linh hoạt cho các nhánh điều kiện, nhưng nếu có quá nhiều phân kỳ lệnh (divergence) trong warp thì hiệu năng sẽ giảm
- Mỗi CUDA Core có trạng thái riêng và có thể truy cập bộ nhớ một cách linh hoạt (trong khi TPU chỉ có thể xử lý bộ nhớ liên tiếp)
Lập lịch/song song hóa
- SM lập lịch và thực thi đồng thời nhiều warp (tối đa 64), và mỗi warp scheduler chỉ chạy một chương trình tại một thời điểm
- Nhờ cấu trúc này, GPU vừa khá linh hoạt vừa đạt được mức xử lý đồng thời cao
Cấu trúc bộ nhớ của GPU
- GPU có HBM là lớn nhất, ngoài ra còn có hệ phân cấp bộ nhớ gồm L2/L1 (SMEM)/TMEM/register
Tóm tắt thông số GPU hiện đại
- Số lượng SM (Streaming Multiprocessor), xung nhịp, bộ nhớ, FLOPs, băng thông (BW) khác nhau tùy theo từng model
- Dung lượng bộ nhớ (HBM), băng thông và FLOPs (floating-point/số nguyên/độ chính xác thấp) đều tăng qua từng thế hệ
- Trong bảng (lược bỏ), các đặc điểm chính gồm: Blackwell (B200) có HBM 192GB, HBM BW 8.0TB/s, FP8 FLOPs 4.5e15
- Qua từng thế hệ, có thể thấy rõ sự tiến bộ phần cứng như dung lượng register và cache on-chip (SMEM), cùng việc bổ sung TMEM
So sánh GPU/TPU
- GPU có tính đa dụng, được mô-đun hóa bằng nhiều SM nhỏ (đơn vị song song), và do có nhiều cơ chế điều khiển phần cứng nên khó hiểu/tối ưu hơn
- TPU gồm một số ít Tensor Core cỡ lớn và nhiều vector ALU (VPU), sử dụng cơ chế điều khiển đơn luồng nên phần cứng có thể đơn giản hơn và giảm chi phí
- Vì vậy, TPU bắt buộc phải tối ưu bằng compiler, còn GPU có thể chạy nhiều kernel độc lập, giúp việc sử dụng dễ dàng hơn
- Về hiệu năng/giá, GPU H200 gần đây có FLOPs/s gấp 2 lần TPU v5p, HBM gấp 1.5 lần, và giá khoảng gấp 2.5 lần
- TPU có VMEM (cache on-chip) lớn hơn và nhanh hơn, nên có thể mang lại lợi thế lớn trong suy luận mô hình như LLM
Các ý chính từ phần Hỏi & Đáp về phần cứng GPU
- H100 có tổng cộng 16.896 fp32 CUDA core (132 SM x 4 x 32), B200 có 18.944
- FLOPs cho phép toán vector của H100 tối đa khoảng 33.5TFLOPs/s, thấp hơn 30 lần so với FLOPs nhân ma trận của Tensor Core (990TFLOPs/s)
- Tổng dung lượng L1/SMEM và register của H100 là 66MB, còn VMEM của TPU là 120MB
- Tỷ lệ giữa bandwidth (băng thông) và FLOPs (cường độ tính toán theo lý thuyết) ở cả H100/B200 đều khoảng 280-300, tương tự TPU
Mạng GPU (cấu trúc giao tiếp)
Cấu trúc node/cluster
- Node GPU thường gồm 8 GPU, được kết nối trực tiếp ở mức full bandwidth bằng NVLink (siêu tốc) và NVSwitch (switch)
- Giữa các node, có thể scale-out bằng InfiniBand (hoặc Ethernet)
- GPU thế hệ mới nhất (Blackwell) có cấu trúc cho phép mở rộng tới 72 node
Đặc điểm theo từng tầng mạng
- Bên trong node (vùng NVLink): egress trên mỗi GPU là 450GB/s (H100), 900GB/s (B200), và tối đa 1.6TB/s trên mỗi NVSwitch
- Tầng trên của node (InfiniBand Leaf/Spine): cấu trúc Leaf Switch (8) ~ Spine Switch (16), duy trì full bandwidth 400GB/s theo lý thuyết giữa GPU với GPU
- Trong các kiến trúc lớn như SuperPod, có 1024 GPU (128 node), còn GB200 (node 72 GPU) có băng thông được khuếch đại gấp 9 lần (3600GB/s)
Các điểm chính về hiệu năng mạng
- Về lý thuyết, cấu trúc mạng (Full Fat Tree) được thiết kế để cung cấp băng thông tối đa cả giữa node với node
- Khi mở rộng lên 1024~4096 GPU, do giới hạn cổng phần cứng nên sử dụng cấu trúc phân tầng với nhiều Spine/Core Switch hơn
- Việc chuyển từ băng thông trong node (450GB/s) sang băng thông liên node (400GB/s) tạo ra chênh lệch hiệu năng trong các phép collective
Cấu trúc phép toán tập thể (Collectives)
- Hỗ trợ các phép collective mức cao như AllGather, AllReduce (cộng gộp), AllToAll (phân tán)
- Trong node, có thể đạt hiệu năng tối ưu qua NVLink kết nối trực tiếp (theo B/W lý thuyết); giữa node với node thì đi qua InfiniBand
- Sử dụng các thư viện NCCL, NVSHMEM của NVIDIA
Phân tích hiệu năng của collectives
- AllGather/ReduceScatter: được triển khai theo kiểu ring với B/W (450GB/s theo H100), còn với thông điệp nhỏ có thể dùng kiểu tree
- AllToAll: mỗi GPU gửi trực tiếp đến GPU đích, nên ở mức B/W sẽ chia theo N, vì vậy trong node về lý thuyết nhanh gấp 2 lần
- Kết quả đo thực tế cho thấy AllReduce đạt khoảng 370GB/s, chưa chạm mức tối đa của phần cứng
- So với TPU, chỉ khi dữ liệu đủ lớn (vài chục MB đến GB) mới tiến gần peak bandwidth của phần cứng
Tóm tắt tổng thể và insight
- GPU mạnh về tính đa dụng và khả năng mở rộng, nhưng tùy theo cấu trúc phần cứng/mạng mà độ khó tối ưu hiệu năng và mức độ quan sát được cao hơn TPU
- Mạng kết nối (Intra-Node/NVLink/InfiniBand/Leaf/Spine...) là yếu tố cốt lõi của hiệu năng huấn luyện quy mô lớn, và cần lưu ý chênh lệch giữa băng thông thực tế và lý thuyết
- Hiểu rõ collectives và cấu trúc mạng là yếu tố thiết yếu trong huấn luyện/phục vụ mô hình phân tán siêu lớn
- Cần một quy trình dựa trên benchmark thực tế và hiểu biết chi tiết về cấu trúc phần cứng để xác định điểm nghẽn hiệu năng và điều kiện tối ưu
1 bình luận
Ý kiến trên Hacker News
Tôi thấy bài này và nhiều tài liệu khác hơi thiếu rõ ràng, đặc biệt khi giải thích về GPU thì thuật ngữ thường được dùng khá mơ hồ; ví dụ ở hình đầu tiên, “Warp Scheduler” được mô tả như một đơn vị vector SIMD tương tự VPU của TPU và có 32 “CUDA Core”, nhưng lại không giải thích rõ “CUDA core” là gì, nên không truyền tải được đúng đối tượng cốt lõi của phần giải thích. Những lỗi chồng chéo như vậy khiến người mới hoặc người đang cố nắm khái niệm vẫn khó hiểu, còn với những ai đã hiểu phần nào thì lại toàn là điều họ đã biết. Dù chỉ là bản nháp, khi công khai thì từng thuật ngữ cũng cần được xử lý chính xác như phẫu thuật, không nên lẫn lộn hay trộn cách dùng thuật ngữ. Khi dùng phép so sánh cũng cần rất cẩn trọng. Và tôi nghĩ những thuật ngữ như MXU (đơn vị tính toán ma trận) nên có giải thích bổ sung hoặc liên kết để người đọc dễ tra cứu. Dạo này có thể giao việc đó cho AI, nhưng điều này cũng hơi buồn
Tôi trả lời với tư cách tác giả, và nhìn chung đồng ý với góp ý đó. Trong phần giải thích, tôi luôn phải cân bằng giữa việc đảm bảo độ chính xác và “sự thật theo tinh thần”. Ví dụ có thể viết là “một đơn vị tương tự VPU của TPU, gồm 32 ALU là các đơn vị vector SIMD (single instruction, multiple data) mà NVIDIA gọi là CUDA Core”, nhưng như vậy câu sẽ dài ra, và vẫn có thể lại thiếu định nghĩa cho các thuật ngữ như đơn vị vector. Tôi có cố gắng dùng nhiều chú thích, nhưng cũng khó kỳ vọng người đọc sẽ bấm từng cái một; còn sidenote thì khó triển khai trong HTML. Những thuật ngữ như MXU đã được định nghĩa ở chương trước, nhưng tôi nghĩ cũng không thể giả định người đọc sẽ đọc hết mọi chương. “Warp Scheduler” bản thân nó cũng là một thuật ngữ mơ hồ vì trên thực tế có thể chỉ nhiều vai trò khác nhau cùng lúc (scheduler, dispatch unit, SIMD ALU), nhưng đây là hệ quả của việc NVIDIA không đặt tên riêng cho đơn vị phức hợp đó. Tôi sẽ cố cải thiện thêm về sau; đây là một chuỗi thỏa hiệp không hề dễ dàng
LLM là công cụ khá tốt để gỡ những nút thắt về liên kết thuật ngữ kiểu này; khi tra một thuật ngữ mà lại kéo theo hàng loạt thuật ngữ khác chưa biết, nó hướng dẫn khá tốt nên bắt đầu học từ đâu
Gần như mọi thứ đều có trong tài liệu kiến trúc hệ thống Google TPU
Tôi thật sự muốn hỏi nghiêm túc là mức kiến thức nền phù hợp về kiến trúc máy tính nên ở mức nào. Bản thân khái niệm SIMD đã có hơn 50 năm rồi. Phần mở đầu của tài liệu đó mặc định người đọc đã hiểu LLM và kiến trúc Transformer, nhưng lại cho rằng không cần hiểu nguyên lý hoạt động của máy tính; tôi thì nghĩ chẳng phải ít nhất cũng nên biết nguyên lý cơ bản của CPU hay sao?
Nội dung này là một chương trong cuốn sách viết cho những người làm trong lĩnh vực machine learning
Tôi cảm thấy rất khó để biện minh cho thời gian đầu tư vào thứ gì đó nếu nó không phải mã nguồn mở hoặc không phải công nghệ có thể dùng chéo giữa nhiều nhà cung cấp. Việc giỏi tận dụng chip Nvidia khiến tôi liên tưởng đến nghề tư vấn SAP ABAP ngày xưa. Tất nhiên lĩnh vực này kiếm được nhiều tiền, nhưng xét về mặt lịch sử thì kiểu chuyên môn như vậy không hẳn mang lại nhiều lợi ích lâu dài
Tôi cũng từng nghĩ như vậy, đến mức hồi đại học 10 năm trước còn cố tình bỏ qua môn CUDA
CUDA có hai phần: kiến trúc phần cứng và software stack dành cho nó. Software stack thì đóng, nên nếu bạn không định tự tối ưu ở mức thấp thì cũng không cần bận tâm lắm. Nhưng cấu trúc phần cứng thì rất đáng để học. Về cơ bản mọi GPU đều hoạt động theo cách tương tự nhau (triết lý nền tảng của kiến trúc CUDA từ năm 2007 đến nay vẫn vậy), và kiến trúc này ảnh hưởng mạnh đến ngôn ngữ shader cũng như cách trừu tượng hóa GPU. Nếu hiểu các đặc tính chi tiết như thread scheduling, warp, cấu trúc bộ nhớ private/shared, bạn có thể điều chỉnh thuật toán khớp hơn với mô hình thực thi của phần cứng để tận dụng lượng năng lực tính toán khổng lồ đó
Tôi muốn nhấn mạnh rằng các nguyên lý của tính toán song song và cách mọi thứ vận hành ở tầng phần cứng, driver phần lớn đều có tính khái quát. Một số phần là đặc thù nền tảng, nhưng rất nhiều phần có thể áp dụng rộng rãi. Nếu quá ám ảnh với tính phổ quát thuần túy thì đôi khi còn bất lợi. Việc có mã nguồn mở hay không và việc nó là công nghệ phổ dụng hay đặc thù cũng có thể xem là hai chuyện riêng, nên cần một góc nhìn rộng hơn
Việc chuyển đổi không khó đến thế. Với những ai đã từng viết code OpenMP hay MPI thì việc nhập môn CUDA vốn đã khá dễ. Học cách tối ưu hiệu năng trong CUDA cũng giúp code song song trên CPU chạy nhanh hơn, nên về bản chất đây là một phiên bản tiến hóa của các mô hình tính toán hiện có
Tôi cũng học lập trình từ nhỏ với IBM PC/MS-DOS; cả hai đều không phải mã nguồn mở nhưng đến giờ vẫn giúp ích rất nhiều
Tôi nghĩ phần tính toán trong “Quiz 2: GPU nodes” không chính xác. Trên thực tế mỗi GPU hay switch đều bị giới hạn số cổng, nên mức 450GB/s khả dĩ về mặt lý thuyết không thực sự được đảm bảo; đó cũng là lý do các cloud lớn hay hệ thống tham chiếu chỉ cung cấp 3.2TB/s. Nếu 3.6TB/s là khả thi thì với workload distributed ring sẽ xuất hiện nghẽn cổ chai. Nhân tiện, tôi đang tìm việc
Cả series này thực sự rất hay. Nó giải thích các giới hạn lý thuyết của workload AI hiện đại, đồng thời diễn giải dễ hiểu những nguyên lý kỹ thuật như kiến trúc và song song hóa. Dù tập trung vào TPU, phần lớn vẫn áp dụng được sang các lĩnh vực khác nên rất hữu ích
Thứ tự hợp lý là trước tiên tối ưu hết mức có thể code tính toán nặng trong một ngôn ngữ có kiểu dữ liệu chặt chẽ, rồi nếu vẫn cần nhanh hơn thì mới xem xét GPU. Theo kinh nghiệm của tôi, GPU cho tốc độ nhanh hơn khoảng 8 lần. Nếu có thể giảm thời gian phản hồi web từ 4 giây xuống còn 0,5 giây thì đó là thay đổi cực lớn. Nhưng trên thực tế, dùng websocket để hiển thị độ trễ (spinner) hoặc dùng cache nền lại thường dễ hơn. Và cũng cần tính đến việc chạy GPU trên cloud rất tốn kém
Thật thú vị khi nvshmem lại được ML ưu ái đến vậy. Trong khi đó, MPI với chức năng tương tự ngày xưa lại không đem đến nhiều hài lòng trong thế giới mô phỏng khoa học. Nói thêm là trước đây tôi chủ yếu làm những bài toán khó như tính lực tầm xa trên nhiều node
Tôi thắc mắc vì sao Nvidia không tự phát triển TPU
Họ không cần. Họ đã ở vị thế thống trị cả phần cứng lẫn thị trường mô hình lập trình rồi, mà TPU còn khó lập trình hơn
Trên thực tế, đúng như bài viết này mô tả, 90% hiệu năng GPU của Nvidia đến từ các đơn vị tính toán ma trận nên cấu trúc của nó gần như đã là TPU rồi. Họ đánh đổi một ít hiệu năng để có được hệ sinh thái compiler linh hoạt hơn nhiều
Tôi ngạc nhiên là đến giờ Nvidia vẫn chưa chính thức cung cấp tài nguyên ở mức này. Cuối cùng lại thành ra bên thứ ba phải reverse engineer phần cứng rồi hệ thống hóa thành các sơ đồ khái niệm thực sự dùng được. Tôi tò mò động cơ thật sự của Nvidia là gì. Nếu chỉ nghĩ về marketing thì có thể xem là họ đã thành công, nhưng tôi vẫn có nghi vấn về engineering culture của họ
Từ góc nhìn của một kỹ sư render thời gian thực thì chuyện này luôn là vậy. NV giấu gần như mọi thông tin để đối thủ khó nắm được các thay đổi giữa các thế hệ; các vendor khác cũng chẳng khác mấy. Trong game thì sau khi ký NDA họ có cung cấp thông tin kiến trúc chi tiết hơn, nhưng ngoài ra tôi chưa thấy trường hợp nào công khai đầy đủ, trừ Intel
Nvidia thực ra có rất nhiều tài liệu chính thức rất tốt so với các hãng khác
Tôi tò mò vì sao bạn lại có cảm giác đó, vì thật ra phần lớn nội dung trong bài này có vẻ gần như lấy nguyên từ tài liệu chính thức của Nvidia. Ví dụ sơ đồ H100 thực chất được chép từ H100 whitepaper mà không ghi nguồn. Thông tin về lượng phép tính và băng thông cũng đều đã có trong whitepaper chính thức và chương 5, 6, 7 của CUDA C++ Guide. Việc bên ngoài tóm tắt ngắn gọn hơn và thêm diễn giải thì có giá trị, nhưng nếu không có tài liệu chính thức của Nvidia thì bản thân những bài như thế này cũng khó mà tồn tại, nên các suy đoán hay nghi ngờ vô căn cứ như vậy hơi quá đà
Nvidia chỉ công bố tài liệu ở mức bình thường, khiến chỉ các thư viện đóng như cuBLAS, cuDNN mới thực sự nhanh, từ đó làm khóa chặt vendor. Nhờ vậy các hãng khác cũng khó đuổi kịp bằng reverse engineering
Nhìn vào nhiều dấu hiệu thì có vẻ Nvidia chỉ cung cấp tài liệu được “đo ni đóng giày” cho người ký NDA và nhóm VIP, còn tài liệu chính thức công khai cho công chúng thì cố tình làm sơ sài vì điều đó có lợi cho họ về mặt thương mại. Ngay cả tài liệu API chính thức, nếu họ dựng rào cản thì lập trình viên bình thường cũng khó tiếp cận; nhưng vì họ tập trung bán cả hệ sinh thái AI, GPU, phần mềm và tài liệu cho VIP, nên có vẻ họ ít quan tâm hơn đến lập trình viên phổ thông
Khi nhìn vào sơ đồ kiến trúc, chúng ta nhất định phải nhớ rằng nó không phản ánh hoàn hảo phần cứng thực tế. Nvidia không đảm bảo rằng các khối hay thành phần trong sơ đồ thực sự tồn tại; chúng chỉ được đưa ra như một mô hình tư duy tham khảo để hình dung GPU và cấu trúc SM. Ví dụ, chính thức mà nói thì ta không biết trong một SM thực sự có bao nhiêu functional unit, liệu “tensor core” có phải phần cứng độc lập hay chỉ là kết quả phối hợp của nhiều unit, hay chi tiết hành vi ở mức nhỏ hơn warp hoạt động ra sao
Đây thực sự là một tài nguyên tuyệt vời, nhờ đó tôi học thêm được nhiều điều hay