Mở đầu: khi CPU và GPU thôi tranh giành, chúng chia sẻ

Bài 7Bài 8 mô tả phân cấp bộ nhớ trong mô hình PC truyền thống: CPU có RAM riêng, GPU có VRAM riêng, kết nối qua bus PCIe. Mỗi lần CPU cần GPU xử lý dữ liệu (render đồ hoạ, huấn luyện mô hình AI), dữ liệu phải được SAO CHÉP từ RAM sang VRAM qua PCIe — một bước tốn thời gian, dù chỉ đơn thuần là "chuyển dữ liệu từ nơi này sang nơi khác" chứ không tính toán gì. Apple Silicon đặt câu hỏi ngược: nếu CPU và GPU cùng nằm trên MỘT đế silicon, tại sao không để chúng CHIA SẺ luôn một bể RAM duy nhất?


📚 Điều kiện tiên quyết
Nên đọc Bài 7 (Cache) và Bài 8 (Bộ nhớ ảo) — UMA bài này là một cách tổ chức KHÁC của chính phân cấp bộ nhớ đã học, không phải khái niệm tách biệt.

1. Hệ thống trên chip (SoC) vs Bo mạch truyền thống

PC truyền thống lắp CPU, GPU, RAM, ổ đĩa... là các LINH KIỆN RỜI trên bo mạch chủ, kết nối qua các bus (PCIe, SATA...). Apple Silicon (dòng M) tích hợp CPU, GPU, Neural Engine (NPU), bộ điều khiển bộ nhớ... lên CÙNG một đế silicon — gọi là SoC (System on a Chip). Khoảng cách vật lý giữa các khối cực ngắn, giảm độ trễ và tiêu thụ năng lượng đáng kể so với việc tín hiệu phải đi qua các đường dẫn (traces) dài trên bo mạch giữa các chip rời.

soc_layout.txt (SoC vs bo mạch rời rạc)
A traditional PC (separate components on a motherboard):
  [CPU chip] ---bus--- [discrete GPU chip] ---bus--- [RAM DIMM]
  Signals travel LONG board traces between separate chips

An Apple Silicon SoC (a single piece of silicon):
  +---------------------------------------------------+
  | [CPU: Firestorm x N] [CPU: Icestorm x M] [GPU]    |
  | [Neural Engine (NPU)] [UMA memory controller]     |
  +---------------------------------------------------+
  Physical distance between blocks is VERY SHORT
  -> lower latency and lower energy per transfer
⚠️ Cạm bẫy: SoC đánh đổi khả năng nâng cấp
Vì RAM và các thành phần khác được HÀN CHẾT trên cùng đế silicon với CPU/GPU, người dùng KHÔNG THỂ nâng cấp RAM hay thay thế linh kiện rời rạc khi hỏng hóc — khác hẳn PC truyền thống nơi RAM, GPU đều là các khe cắm (slot) có thể tháo lắp. Đây là đánh đổi CÓ CHỦ ĐÍCH giữa hiệu năng/tiết kiệm năng lượng (SoC) và khả năng sửa chữa/nâng cấp (kiến trúc rời rạc) — không phải giới hạn kỹ thuật ngẫu nhiên.

2. Nhân lớn/nhỏ (big.LITTLE) & UMA

Apple M1 có 2 loại nhân CPU: Firestorm (hiệu năng cao, ăn nhiều điện) và Icestorm (tiết kiệm điện, hiệu năng thấp hơn) — hệ điều hành TỰ ĐỘNG đẩy tác vụ nền (đồng bộ email, quét virus) sang Icestorm để tiết kiệm pin, và tác vụ nặng (biên dịch code, render video) sang Firestorm. Quan trọng hơn cho bài này: CPU (cả 2 loại nhân) và GPU đều truy cập CHUNG một bể RAM LPDDR5 duy nhất — đây là UMA (Unified Memory Architecture).

uma_vs_traditional.txt (so đồ 2 mô hình)
Traditional PC:
  [CPU] --own RAM--     [GPU] --own VRAM--
     |______________PCIe Gen4 x16 (~32 GB/s)_____________|
     Whenever the GPU needs data the CPU holds -> COPY it over PCIe

Apple Silicon (UMA):
  [CPU] ---+
           +--- ONE shared LPDDR5 pool (e.g. 400 GB/s on M1 Max) ---+
  [GPU] ---+                                                        |
     Both read and write it DIRECTLY - no copy step at all.
     But see Section 4: that pool is SHARED, not private to the GPU.
⚠️ Cạm bẫy: lập lịch sai lầm gây hao pin
Nếu bộ lập lịch hệ điều hành (thread scheduler) đẩy NHẦM một tác vụ nền nhẹ lên nhân Firestorm hiệu năng cao (thay vì Icestorm tiết kiệm điện), pin bị tiêu hao một cách VÔ ÍCH — công việc vẫn hoàn thành đúng, nhưng tốn điện hơn hẳn mức cần thiết. Lập lịch big.LITTLE đúng đắn là bài toán liên tục cân bằng giữa "xong việc nhanh" và "xong việc tiết kiệm điện", không có công thức cố định cho mọi tác vụ.

3. Bài toán tính toán băng thông: PCIe vs UMA

Render MỘT khung hình 4K (3840×2160 pixel, 32-bit màu — 4 byte/pixel gồm R/G/B/Alpha) cần đúng:

$$\text{Frame Bytes} = 3840 \times 2160 \times 4 = 33.177.600 \text{ byte}$$

Verified thật: khung hình 4K nặng đúng 33.177.600 byte (31,64 MiB). So sánh thời gian truyền dữ liệu này qua 2 kênh — PCIe Gen 4 x16 (băng thông thực tế ~32 GB/s, cần SAO CHÉP từ RAM sang VRAM) vs UMA trên Apple M1 Max (băng thông RAM 400 GB/s, GPU truy cập TRỰC TIẾP, không sao chép):

bandwidth_compare.js (trích engine dùng chung cpu-core.js)
function frameBytes(width, height, bytesPerPixel) {
  return width * height * bytesPerPixel;
}
function transferTimeSeconds(bytes, bandwidthGBps) {
  return bytes / (bandwidthGBps * 1e9);
}
// Verified: frameBytes(3840, 2160, 4) = 33.177.600 byte
// Verified: transferTimeSeconds(33177600, 32) * 1000  = 1,0368 ms  (PCIe Gen 4 x16)
// Verified: transferTimeSeconds(33177600, 400) * 1000 = 0,0829 ms  (UMA M1 Max)
// UMA beats PCIe by EXACTLY the bandwidth ratio: 400/32 = 12.5x

Ở khung hình 4K này, PCIe mất 1,0368 ms, UMA chỉ mất 0,0829 ms — nhanh hơn đúng 12,5 lần, khớp CHÍNH XÁC tỷ lệ băng thông ($400/32=12,5$), không phải một con số ước lượng mơ hồ. Ở khung hình 60fps (ngân sách mỗi khung hình $1000/60 \approx 16,67$ ms), PCIe chiếm 6,22% ngân sách CHỈ ĐỂ SAO CHÉP dữ liệu (chưa tính thời gian GPU thực sự xử lý), trong khi UMA chưa tới 0,5%.

frame_budget_60fps.js (tỷ trọng thời gian truyền trên ngân sách khung hình)
const frameBudgetMs = 1000 / 60; // ~16.6667 ms per frame at 60fps
const pcieShare = (cmp.pcieTimeMs / frameBudgetMs) * 100; // ~6.22%
const umaShare = (cmp.umaTimeMs / frameBudgetMs) * 100;   // ~0.50%
// PCIe: nearly 1/16 of the frame budget spent JUST copying data
// UMA: negligible - the GPU keeps almost the whole budget for real COMPUTE
⚠️ Đừng so sánh thô xung nhịp CPU/GPU mà bỏ qua băng thông bộ nhớ
Chênh lệch 12,5 lần ở trên đến HOÀN TOÀN từ tỷ lệ băng thông bộ nhớ (400 GB/s vs 32 GB/s) — KHÔNG liên quan gì đến xung nhịp (GHz) của CPU hay GPU. Một GPU xung nhịp cao nhưng bị nghẽn ở khâu truyền dữ liệu (data-starved) vẫn chạy chậm hơn hẳn tiềm năng lý thuyết — đây chính là lý do "thông số xung nhịp" một mình không đủ để so sánh hiệu năng thực tế giữa 2 kiến trúc khác nhau.

4. Cái giá kiến trúc của UMA

Ba mục trên chỉ kể mặt được, và cạm bẫy duy nhất đã nêu — không nâng cấp được RAM — là đánh đổi về ĐÓNG GÓI, không phải về kiến trúc. Nhưng UMA có hai cái giá thuộc chính thiết kế của nó, và cả hai đều nằm ngay trong con số 400 GB/s vừa dùng ở Mục 3.

4.1 Băng thông là CHIA SẺ, không phải cộng dồn

Con số 400 GB/s ở Mục 3 không phải "băng thông của GPU". Đó là băng thông của TOÀN bể RAM — thứ mà CPU, GPU và Neural Engine đều rút từ đó, cùng lúc. Khi CPU đang xử lý nặng, phần còn lại cho GPU ít đi đúng bằng phần CPU lấy:

shared_bandwidth.js (cùng khung 4K, GPU bị CPU lấy bớt băng thông)
const bytes = frameBytes(3840, 2160, 4);            // 33,177,600 bytes
const ms = (bw) => transferTimeSeconds(bytes, bw) * 1000;

// UMA: one pool, so whatever the CPU consumes is taken OFF the GPU's share.
// Verified by running it:
//   CPU idle       -> GPU has 400 GB/s -> 0.0829 ms  (the figure from Section 3)
//   CPU 100 GB/s   -> GPU has 300 GB/s -> 0.1106 ms  (1.33x slower)
//   CPU 200 GB/s   -> GPU has 200 GB/s -> 0.1659 ms  (2.00x slower)

// A DISCRETE PC has the opposite property: the two pools are separate, so their
// bandwidths ADD instead of competing. A GPU reading from its own 320 GB/s VRAM
// gets 0.1037 ms no matter how hard the CPU hammers its own RAM.

Đó là lý do so sánh "32 GB/s vs 400 GB/s" của Mục 3 đúng nhưng chưa đủ. Nó đúng ở chỗ PCIe phải SAO CHÉP còn UMA thì không — mà bước sao chép ấy là thứ biến mất hoàn toàn, nên lợi ích là thật. Nhưng nó chưa đủ ở chỗ 400 GB/s là con số CHIA CHUNG: dưới tải nặng đồng thời, phần GPU thực nhận thấp hơn hẳn, và 2,00 lần chậm hơn ở dòng cuối bảng trên là số đo, không phải phỏng đoán. Kiến trúc rời rạc đổi việc phải sao chép để lấy hai bể băng thông độc lập; UMA đổi ngược lại.

4.2 Chia sẻ bộ nhớ thì phải giữ cache nhất quán

Mục 2 nói CPU và GPU "đọc/ghi TRỰC TIẾP, không cần sao chép gì cả". Câu đó bỏ qua một câu hỏi: cả hai đều có cache riêng (Bài 7). Nếu CPU ghi một giá trị và giá trị đó còn nằm trong cache của CPU chưa xuống RAM, GPU đọc cùng địa chỉ ấy sẽ thấy dữ liệu CŨ.

Thứ ngăn điều đó là cache coherency (tính nhất quán cache): phần cứng theo dõi ai đang giữ bản sao của dòng cache nào, và khi một bên ghi thì các bản sao ở bên kia bị vô hiệu hoá. Đây không phải tính năng phụ — nó là điều kiện để "không cần sao chép" trở nên AN TOÀN thay vì chỉ nhanh. Và nó có giá: mỗi lần ghi vào vùng đang chia sẻ có thể sinh thêm lưu lượng theo dõi trên chip, và tại những điểm giao việc CPU↔GPU, phần mềm vẫn phải đặt mốc đồng bộ để chắc chắn bên kia đã thấy dữ liệu mới.

⚠️ Cạm bẫy: "unified memory" không có nghĩa là "khỏi đồng bộ"
Cái mất đi khi chuyển sang UMA là bước sao chép dữ liệu, KHÔNG phải bước đồng bộ. Người mới thường đọc "zero-copy" thành "cứ ghi rồi bên kia tự thấy" — sai. Chương trình vẫn phải nói rõ "tôi ghi xong rồi" trước khi GPU đọc, và trong Metal của Apple điều đó vẫn là những lệnh tường minh trên command buffer. Bỏ mốc đồng bộ thì lỗi sinh ra thuộc loại tệ nhất: chạy đúng trên máy bạn, sai ngẫu nhiên trên máy khác, vì nó phụ thuộc thời điểm cache được ghi xuống.

5. Thực hành: So sánh băng thông PCIe vs UMA

Đổi kích thước khung hình, số byte/pixel, và băng thông của cả 2 kênh để xem thời gian truyền thay đổi trực tiếp — thanh màu bên dưới trực quan hoá tỷ lệ chênh lệch:

🖥️ So sánh băng thông PCIe vs UMA
PCIe
UMA

Tóm lược

  • ✅ UMA đổi bước sao chép PCIe để lấy một bể RAM chung — nhưng băng thông bể đó là CHIA SẺ: verified, nếu CPU đang dùng 200 GB/s thì cùng khung 4K mất 0,1659 ms thay vì 0,0829 ms, tức chậm đúng 2,00 lần.
  • ✅ "Zero-copy" bỏ được bước SAO CHÉP, không bỏ được bước ĐỒNG BỘ — cache coherency là thứ khiến việc chia sẻ an toàn, và chương trình vẫn phải đặt mốc đồng bộ giữa CPU và GPU.
  • ✅ SoC tích hợp CPU/GPU/RAM lên cùng đế silicon, giảm độ trễ và năng lượng — đổi lại mất khả năng nâng cấp/thay thế linh kiện rời.
  • ✅ big.LITTLE (Firestorm/Icestorm) cân bằng hiệu năng và pin qua lập lịch tác vụ động.
  • ✅ UMA loại bỏ hoàn toàn bước sao chép CPU→GPU của mô hình PC truyền thống — CPU và GPU truy cập TRỰC TIẾP cùng một bể RAM.
  • ✅ Verified: khung hình 4K = 33.177.600 byte; PCIe Gen 4 (32GB/s) = 1,0368ms; UMA (400GB/s) = 0,0829ms — nhanh hơn đúng 12,5 lần, khớp tỷ lệ băng thông.
  • ✅ Pitfall: chênh lệch hiệu năng đến từ BĂNG THÔNG bộ nhớ, không phải xung nhịp CPU/GPU — so sánh thô xung nhịp bỏ qua yếu tố quyết định thực tế.

Trắc nghiệm ôn tập

Câu 1

UMA (Unified Memory Architecture) loại bỏ được bước nào trong luồng xử lý đồ hoạ trên PC truyền thống?

Câu 2

Verified: PCIe Gen 4 (32GB/s) mất 1,0368ms để truyền khung 4K, UMA (400GB/s) chỉ mất 0,0829ms — nhanh hơn đúng 12,5 lần. Con số 12,5 lần này đến từ đâu?

Câu 3

SoC (System on a Chip) tích hợp CPU/GPU/RAM lên cùng đế silicon đánh đổi điều gì so với PC truyền thống?

Câu 4

Vì sao "lập lịch sai lầm" (đẩy tác vụ nền lên nhân Firestorm hiệu năng cao) là một pitfall thực sự của kiến trúc big.LITTLE?

Tải file code thực hành minh họa bài học

File JavaScript CPUJS — thư viện kiến trúc máy tính mini dùng xuyên suốt cả 12 bài, Bài 9 vừa thêm frameBytes(), transferTimeSeconds(), compareTransferMethods() — mô hình dung lượng khung hình và so sánh thời gian truyền PCIe vs UMA, kèm self-test đối chiếu đúng mọi con số trong bài (chạy node cpu-core.js, không cần cài thêm gì):

Tải về cpu-core.js

📖 Tài liệu tham khảo

Bài viết liên quan trong series

Bài 8: Bộ Nhớ Ảo & Khối TLB Bài 10: Tăng Tốc Phần Cứng: GPU, NPU & AMX Quay lại Lộ trình Kiến Trúc Máy Tính

Bình luận