CPU tìm một byte giữa hàng tỷ byte như thế nào?
Chương trình chỉ nói score. Làm sao CPU tìm đúng dữ liệu đó giữa hàng tỷ byte trong RAM?
Ở bài trước, ta thấy RAM chia hàng tỷ ô nhớ thành nhóm chip, bank, hàng và cột.
Nhưng chương trình không nói:
bank 1, hàng 2, cột 3
Nó chỉ có:
int score = 42;
Vài dòng sau, chương trình cần score.
CPU nói gì với RAM để tìm lại đúng dữ liệu đó?
Câu trả lời là: một địa chỉ.
RAM không biết tên biến
Với người viết chương trình, dữ liệu có những cái tên như:
score
health
playerName
RAM không biết những cái tên đó. Nó chỉ cần biết dữ liệu nằm ở chỗ nào.
Vì vậy từng byte trong bộ nhớ được đánh số:
100 → một byte
101 → một byte
102 → một byte
103 → một byte
...
Mỗi số là một địa chỉ (address).
Một int thường chiếm 4 byte, nên score có thể bắt đầu ở 0x5300 và chiếm:
0x5300
0x5301
0x5302
0x5303
0x… chỉ là cách viết số bằng hệ mười sáu. Địa chỉ thật dài hơn; bài này rút gọn cho dễ nhìn.
Cuối cùng CPU chỉ cần một yêu cầu kiểu:
đọc 4 byte từ 0x5300
Tên score không đi tới RAM.
Nhưng CPU nhìn bộ nhớ như một dãy địa chỉ liền nhau, còn RAM lại chia thành:
nhóm chip → bank → hàng → cột
Ai nối hai cách nhìn đó với nhau?
Memory controller giải mã địa chỉ
Đó là việc của memory controller, mạch điều khiển bộ nhớ nằm ngay trên chip CPU. Nó nhận địa chỉ rồi tách ra xem dữ liệu thuộc bank nào, hàng nào, cột nào:
0x5300
↓
bank 1
hàng 2
cột 3
Yêu cầu đi tiếp qua kênh (channel), đường dây nối CPU với khe cắm RAM.
Nhưng biết hàng và cột vẫn chưa xong. DRAM không chọc thẳng vào một ô rồi lấy đúng byte đó ra.
RAM phải mở cả hàng
Đọc lần lượt 0x5300, 0x5340 rồi 0x9180, và để ý RAM phải làm gì với hàng.
Đọc lần lượt cả ba địa chỉ. Để ý bước mở hàng.
Với 0x5300, bank mở hàng 2, giữ cả hàng trong row buffer, rồi mới chọn cột.
0x5340 cũng nằm trong hàng 2. Hàng đó còn nguyên trong row buffer nên bank không phải mở lại, chỉ chọn cột khác. Đây gọi là row hit.
0x9180 nằm ở hàng 5. Bank phải đóng hàng (precharge) hàng 2, đưa các đường bit về mức chờ, rồi mới mở được hàng mới.
Vì vậy hai lần đọc cùng lấy vài byte mà tốn công khác hẳn nhau.
DRAM không nhặt riêng một byte từ lưới ô nhớ. Nó mở cả một hàng vào row buffer rồi chọn phần cần đọc.
Nhưng dù gặp row hit, đi tới RAM vẫn là một chuyến khá xa:
CPU
↓
memory controller
↓
kênh
↓
thanh RAM → bank → row buffer
↓
quay về CPU
Suốt chuyến đó, CPU đứng chờ.
Vì vậy CPU có cache
Ngay trong chip CPU có những vùng nhớ nhỏ làm bằng SRAM, gọi là cache:
nhân CPU
↓
L1
↓
L2
↓
L3
↓
RAM
Cần một địa chỉ, CPU hỏi cache trước. Có bản sao thì dùng luôn. Không có, gọi là cache miss, yêu cầu mới đi tới memory controller rồi tới thanh RAM.
Khi đã phải đi cả chuyến, RAM không gửi về đúng 4 byte của score. Nó gửi về cả một khối gọi là cache line, thường gặp là 64 byte:
CPU cần
↓
[ ][ ][ ][ ][X][ ][ ][ ]
cache nhận về
[████████████████████████]
64 byte
Mất công đi cả đường rồi thì mang thêm một ít gần như không tốn gì, mà byte bên cạnh thường cũng sắp được dùng tới.
Với RAM, một biến cuối cùng chỉ là một địa chỉ. Địa chỉ được đổi thành bank, hàng và cột; DRAM mở cả hàng để đọc; còn cache giữ bản sao gần CPU để khỏi đi lại chuyến đó.
Cache nhanh, nhưng nhỏ. RAM lớn hơn, nhưng chậm hơn. SSD còn lớn và rẻ hơn nữa, nhưng chậm hơn rất nhiều.
Vậy sao phải chia bộ nhớ thành nhiều lớp? Sao không làm một loại bộ nhớ vừa nhanh như cache, vừa lớn như RAM, vừa rẻ như SSD?