CPU làm việc như thế nào ( phần 3 )
[10/07/2006 03:06]
(Phần 2)
(Phần 3)
Quá trình phân nhánh
Như đã đề cập phần trước , một vấn đề chính của CPU là có quá nhiều Cache "miss" , bởi vì Fetch Unit phải truy cập trực
tiếp tới bộ nhớ hệ thống RAM chậm , như vậy sẽ làm hệ thống chậm đi .
Thông thường sử dụng bộ nhớ Cache để tránh vấn đề trên , nhưng có một tình huống hay xảy ra ở đó phần điều khiển
Cache sẽ bị "miss" : bị phân nhánh . Nếu trong khoảng giữa của chương trình có lệnh gọi là JMP ( lệnh Jump hoặc Go to )
gửi chương trình tới một vị trí hoàn toàn khác . trong tình huống này không thể tải ở trong bộ nhớ Cache L2 , nó làm cho
Fetch Unit phải truy cập trực tiếp vào bộ nhớ hệ thống RAM . Trong lệnh để giải quyết tình huống này , phần điều khiển
Cache của CPU phân tích khối bộ nhớ mà nó tải về để tìm xem lệnh JMP nằm ở đâu và nó sẽ tải khối bộ nhớ đó vào trong
Cache L2 trước khi CPU yêu cầu lệnh những JMP .này .
Hình dưới đây mô tả tình huống rẽ nhánh không điều kiện
Đây là vấn đề dễ giải quyết , còn một vấn đề là kh ichương trình rẽ nhánh có điều kiện , có nghĩa là chương trình sẽ chạy
tuỳ thuộc vào điều kiện có hay không biết trước . Lấy ví dụ : nếu a=<b thì chạy tới địa chỉ 1 hoặc nếu a>b chạy tới địa chỉ 2 .
Chúng ta sẽ xem hình dưới đây:
Trong tình huống trên dễ xảy ra tình trạng Cache "miss" bởi vì giá trị a , b chưa biết trước mà phần điều khiển Cache chỉ tìm
được lệnh JMP .
Giải pháp như sau : phần điều khiển Cache sẽ tải cả hai điều kiện vào trong bộ nhớ Cache . Sau cùng khi CPU xử lí lệnh rẽ
nhánh nó sẽ đơn giản huỷ bỏ một điều kiện không được chọn tới . Đó là tốt nhất để tải bộ nhớ Cache còn hơn là truy cập
trực tiếp dữ liệu bên trong bộ nhớ hệ thống RAM .
Quá trình xử lí các lệnh
Fetch Unit sẽ tải những lệnh từ bộ nhớ . Đầu tiên nó sẽ tìm những lệnh mà CPU yêu cầu bên trong Cache chỉ dẫn ( lệnh )
L1 , nếu không có nó sẽ tới bộ nhớ Cache L2 . Nếu lệnh cũng không có nó sẽ tải trực tiếp từ bộ nhớ của hệ thống RAM .
Khi chúng ta bất máy tính tất cả bộ nhớ Cache hoàn toàn rỗng , khi hệ thống bắt đầu tải chương trình hệ thống , CPU sẽ
bắt đầu xử lí những lệnh đầu tiên được tải từ ổ cứng và phần điều khiển cache bắt đầu tải vào bộ nhớ Cache , và quá trình
làm việc bắt đầu .
Sau khi Fetch Unit lấy những lệnh được CPU yêu cầu để xử lí , nó sẽ gửi chúng tới Decode Unit ( phần giải mã ) .
Decode Unit sẽ tính ra những lệnh thông thường để làm . Nó làm bằng một chương trình trong bộ nhớ ROM tồn tại bên
trong CPU gọi là Microcode . Mỗi một lệnh để cho CPU hiểu được đặt trong microcode . Microcode sẽ "dạy" cho CPU phải
làm những gì . Nó như là hướng dẫn từng bước một cho mọi lệnh . Nếu lệnh được tải , ví dụ , a+b , microcode sẽ nói cho
Decode Unit rằng nó cần hai tham số a và b . Decode Unit sẽ yêu cầu Fetch Unit lấy dữ liệu ở trong hai ô nhớ mà giá trị bên
trong là a và b . Sau đó Decode Unit sẽ "dịch" lệnh này và lấy tất cả dữ liệu yêu cầu để thực hiện lệnh . Nó sẽ lấy dữ liệu
một cách từng bước một để tới phần thực hiện lệnh ( Execute Unit ) và cho biết lệnh đó thực hiện như thế nào .
Execute Unit cuối cùng sẽ thực hiện lệnh đó . Trong nhiều kiểu CPU chúng ta sẽ thấy có một vài Execute Unit làm việc song
song với nhau . Điều này sẽ làm tăng hiệu suất của quá trình xử lí lệnh . Ví dụ : một CPU có sáu Excute Unit có thể thực
hiện sáu lệnh song song với nhau , do đó về mặt lí thuyết nó có thể đạt được như là sáu bộ vi xử lí bên trong một Execute
Unit . Cấu trúc như vậy gọi là cấu trúc Superscalar .
Thông thường CPU không có vài Execute Unit riêng biệt , chúng có Execute Unit chuyên để thực hiện một loại lệnh nào đó .
Ví dụ là FPU , Float Point Unit, được sử dụng để thực hiện những phép toán phức tạp .
Bình thường giữa Decode Unit và Execute Unit có một phần gọi là Dispatch ( hoặc Schedule Unit ) để gửi lệnh tới đúng
Execute Unit mà nó cần , có nghĩa là nếu lệnh là phép toán nó sẽ được gửi tới FPU nếu không phải nó sẽ gửi tới Execute
Unit chung . Những Execute Unit chung đó gọi là ALU, Arithmetic and Logic Unit .
Cuối cùng khi quá trình xử lí kết thúc , kếy quả được gửi tới Cache dữ liệu L1 . Kết quả này có thể dược gửi quay trở lại bộ
nhớ hệ thống RAM hoặc gửi tới một chỗ khác , ví dụ như card màn hình . Nhưng điều này sẽ phụ thuộc vào lệnh tiếp theo
mà trong quá trình xử lí tiếp diễn ( lệnh tiếp theo có thể là " in kết quả ra màn hình ").
Một đặc điểm cần quan tâm khác mà tất cả bộ vi xử lí có một thời gian dài gọi là "pipeline" , khả năng có vài lệnh khác nhau
ở những tầng ( stage ) khác nhau của CPU trong cùng một thời gian .
Sau khi Fetch Unit gửi lệnh tới Decode Unit , nó sẽ tạm nghỉ không làm gì có phải không ? Do đó nó sẽ phải làm gì để thay
thế thời gian không làm gì , có yêu cầu Fetch Unit lấy lệnh tiếp theo không ? . Khi lệnh đầu tiên tới Execute Unit , Fetch Unit
có thể gửi lệnh tiếp theo tới Decode Unit và tiếp tục lấy tiếp lệnh thứ ba , cứ như thế .
Trong kiểu CPU có 11 stage ( stage là tên khác của mỗi thành phần - unit - bên trong CPU ) , có sẽ có thể có 11 lệnh bên
trong liên tục trong cùng một lúc . Trên thực tế tất cả kiểu CPU đều có cấu trúc Superscalar , có nhiều lệnh thực hiện liên tục
bên trong CPU .
Như trên đã nói CPU có Pipeline 11-stage , thì một lệnh để thực hiện đầy đủ sẽ phải qua 11 phần ( unit) . Số tầng càng cao
thì thời gian trễ để thực hiện một lệnh đầy đủ càng lớn .
Có một vài mẹo nhỏ được sử dụng trong một vài kiểu CPU để tăng hiệu suất . Chúng ta sẽ giải thích hai trong số chúng đó
là Out-Of-Order execution (OOO) và thực hiện suy đoán Speculative Execution.