Báo cáo chi tiết tìm hiểu vi xử lý AMD athlon II
Trang 1HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG
Khoa Công Nghệ Thông Tin
- -BÁO CÁO
BÀI TẬP LỚN KĨ THUẬT VI XỬ LÝ Chủ đề : Tìm hiểu kiến trúc VXL AMD Athlon II Giảng viên: TS.Hoàng Xuân Dậu
Hà nội, 9-10-2013
Trang 2A.Lời mở đầu
Báo cáo tiểu luận Vi xử lý AMD Athlon II đã cố gắng tổng hợp và phân tích các vấn đề liên quan một cách tốt nhất Tuy vậy, sẽ không tránh khỏi những thiếu sót trong quá trình thu thập và trình bày Chúng em
mong sẽ nhận được sự góp ý tốt nhất để nhóm có thể hoàn thiện và trưởng thành hơn
Chúng em xin chân thành cảm ơn!
B.Nội dung
1 Tập đoàn AMD và các dòng sản phẩm
AMD hay Advanced Micro Devices là nhà sản xuất linh kiện tích hợp bán dẫn đa quốc gia có trụ sở tại
Sunnyvale, California, Hoa Kỳ AMD là nhà sản xuất bộ vi xử lý (CPU) x86 lớn thứ hai thế giới sau Intel
và là một trong những nhà sản xuất bộ nhớ flash hàng đầu trên thế giới; ngoài ra AMD còn sản xuất
chipset và các linh kiện điện tử bán dẫn khác
AMD thành lập năm 1969 từ một nhóm kỹ sư thành viên tách ra từ Fairchild Semiconductor; ngày nay
AMD trở thành một công ty đa quốc gia với hàng chục ngàn nhân viên tại châu Âu, Nhật Bản, Hoa Kỳ
AMD nổi tiếng với dòng sản phẩm Phenom, Sempron cho thị trường cao cấp, Athlon cho thị trường trung
cấp và Duron cho thị trường cấp thấp giá rẻ Một số linh kiện của các thế hệ đời trước của máy tính
Apple cũng do AMD cung cấp Thế hệ vi xử lý mới nhất của hãng hiện nay hỗ trợ tập lệnh mở rộng
AMD64 cho điện toán 64 bit là AMD Athlon 64 cho thị trường máy tính để bàn và AMD Opteron cho thị
trường máy chủ và trạm làm việc
AMD đem đến các sản phẩm và công nghệ máy tính với các giải pháp an toàn, sức mạnh, độ tin cậy và
sự nhanh nhẹn “Enjoy a better experience gaming, cloud computing or editing home videos with the best
AMD product for you” - Thưởng thức một trải nghiệm chơi game tốt hơn, điện toán đám mây hay chỉnh
sửa video gia đình với sản phẩm AMD tốt nhất cho bạn
2 VXL Athlon II
2.1 VXL Athlon II
Athlon II là dòng VXL đa lõi dành cho máy tính để bàn, được
AMD bắt đầu giới thiệu vào nửa cuối năm 2009, dựa trên bộ vi
kiến trúc AMD K10 có nguồn gốc từ các dòng Phenom II Tuy
nhiên, không giống như Phenom II, nó không chứa bộ nhớ cache Thời gian sản xuấtThiết kế Từ 2009 đến hiện tạiAMD
Sản xuất tại GlobalFoundriesXung nhịp CPU 1,6 GHz đến 3,5 GHzTốc độ HyperTransport 1,8 GHz đến 2 GHzKích thước 45 nm đến 32 nmTập lệnh hỗ trợ X86 – AMD64
Vi kiến trúc AMD K10
Trang 3L3, mà chỉ dừng lại ở 2 mức cache L1 và L2 Như vậy, có thể coi AMD Athlon II là một phiên bản rút gọn của dòng Phenom II, hướng tới đối tượng tầm trung.
Dòng Athlon II không tích hợp card đồ họa vào nhân CPU như dòng APU của AMD, nhằm giảm giá thành
và phục vụ những người cần card đồ họa rời, giá rẻ
VXL AMD Athon II là sự cân đối hợp lý giữa giá thành và hiệu năng, đảm bảo đem đến những trải nghiệm đầy đủ cho người dùng nhưng vẫn rất tiết kiệm
2.2 Các bộ VXL thuộc dòng Athlon II
AMD Athlon II có tất cả 6 dòng từ thấp đến cao cho các dòng Regor, Rana, Propus và LIano
2.2.1 AMD Athlon II x2 series
Đây là dòng sản phẩm đạt danh số bán hàng cao nhất của AMD, thuộc phân khúc bình dân, hướng đến nhu cầu giải trí giá thành thấp, film HD, game online và tác vụ văn phòng, AMD Athlon II x2 đã làm rất tốt công việc của mình
o Tên mã: Regor
o Xử lí lõi kép: 2 lõi AMD K10
o L1 cache: 64MB + 64MB (data+Intructions) mỗi lõi
o L2 cache: 1024KB mỗi lõi
o Tập lệnh hỗ trợ: MMX, Extended 3DNow!, SSE, SSE2, SSE3, SSE4a, AMD64, Cool'n'Quiet, NX bit, AMD-V
o Memory support: DDR2-1066 (Socket AM2+) và DDR3-1333 (Socket AM3)
o Đại diện: Athlon II X2 210e - 270
2.2.2 AMD Athlon II x3 series
Những VXL này khá mạnh mẽ, chạy rất tốt và đáp ứng rất tốt nhu cầu của đại đa số người dùng Game
và đồ họa cũng rất ổn AMD đã tạo ra một phân khúc người dùng mới bằng bộ VXL này
o Tên mã: Rana
o Xử lí 3 lõi: 4 lõi AMD K10, trong đó 1 lõi bị vô hiệu hóa
o L1 cache: 64MB + 64MB (data+Intructions) mỗi lõi
o L2 cache: 512KB mỗi lõi
o Tập lệnh hỗ trợ: MMX, Extended 3DNow!, SSE, SSE2, SSE3, SSE4a, AMD64, Cool'n'Quiet, NX bit, AMD-V
o Memory support: DDR2-1066 (Socket AM2+) và DDR3-1333 (Socket AM3)
o Tốc độ HyperTransport: 2GHz
o Xung nhịp CPU: 2,2 – 3,4 GHz
Trang 4o Công nghệ sản xuất: 45 nm ( SOI ), bán dẫn
o Các Kích thước: 169 mm ²
o Công suất tiêu thụ: 45W hoặc 95W
o Phát hành: 10/2009
o Đại diện: Athlon II X3 400e – 460
2.2.3 AMD Athlon II x4 Series
Bộ VXL tầm trung đa nhân giá rẻ, đó là mục đích chính AMD giới thiệu bộ VXL này đến người dùng Dựatrên các nhân Deneb đã bỏ bớt Cache L3, hiệu năng giảm không đáng kể và khá mạnh mẽ, đa tác vụ tốt
và hiệu năng cao, giá thành hợp lý Những BXL này đã đáp ứng nhu cầu rất nhiều người dùng muốn hướng đến hiệu năng/giá cả tốt Về hiệu năng CPU thì dòng này dưới Core i3 2100 một chút, người dùng
đã mua hoàn toàn có thể yên tâm sử dụng tiếp vì hiệu năng vẫn rất ổn định Và AMD đã dừng dòng này
o Tên mã: Propus
o Xử lí 4 lõi: 4 lõi AMD K10
o L1 cache: 64MB + 64MB (data+Intructions) mỗi lõi
o L2 cache: 512KB mỗi lõi
o Tập lệnh hỗ trợ: MMX, Extended 3DNow!, SSE, SSE2, SSE3, SSE4a, AMD64, Cool'n'Quiet, NX bit, AMD-V
o Memory support: DDR2-1066 (Socket AM2+) và DDR3-1333 (Socket AM3)
o Đại diện: Athlon II X4 600E - 645
2.2.4 AMD Athlon II x4 (Llano Core)
Công nghệ 32nm mang đến cho AMD nhiều cải tiến, nhưng quy trình sản xuất nhân đồ họa trên quy trìnhmới tích hợp vào nhân CPU đã gặp những khó khăn nhất định Hiệu xuất không cao nên AMD đã quyết định dựa vào những nhân lỗi card đồ họa, tung ra bộ VXL Athlon II x4 mới Hướng đến người dùng muốndùng 1 card đồ họa rời với giá thành thấp, hiệu năng tốt, AMD Athlon II x4 đã phải cạnh tranh với chính APU của AMD, tuy nhiên ở thị trường nước ngoài dòng này cũng đã có những thành công
o Tên mã: Llano
o Tập lệnh hỗ trợ: MMX, SSE, SSE2, SSE3, SSE4a, Extended 3DNow!, NX bit, AMD64,
Cool'n'Quiet, AMD-V, Turbo Core
o Memory support: DDR3-1600 hoặc DDR-1866 tùy dòng (Socket FM1)
o Công nghệ sản xuất: 32 nm ( SOI ), bán dẫn
o Công suất tiêu thụ ( TDP ): 100 W
o Ngày phát hành: tháng 9 năm 2011
o Xung nhịp CPU: 2,6-3,0 GHz
Trang 5II Kiến trúc VXL Athlon II
1 Sơ đồ khối và các bộ phận chính
1.1 Giới thiệu về AMD K10
AMD đã cho ra mắt bộ xử lý đầu tiên dựa trên công nghệ này là chip máy chủ Opteron, dựa trên nhân có mật danh là Barcelona năm 2007
- K10 là kiến trúc mà các vi xử lí của AMD đang sử dụng như: Athlon II, Phenom và Opteron dựa trên cơ sở nhiều nhân “Barcelona” Trên thực tế nhiều người nhầm kiến trúc K10 với “Barcelona”,trong khi Barcelona chỉ là một trong những CPU sẽ sử dụng kiến trúc này
- Kiến trúc K10 được dựa trêm (AMD64) K8 với một số cải tiến
Một số điểm được nâng cao:
+ Khối dữ liệu được nạp có kích thước 32byte (256 bit) trên mỗi chu kì đồng hồ từ cache L1 – đây là CPU kép dựa trên kiến trúc K8 có thể nạp trên mỗi chu kì đồng hồ CPU Intel dựa trên kiến trúc Core, như Core 2 Duo, cũng nạp 32byte trên mỗi chu kỳ đồng hồ
+ Sử dụng đúng 128 bit trong đường truyền dữ liệu Trong các CPU trước được xây dựng trên kiến trúc K8 đường truyền dữ liệu chỉ là 64 bit Đây là một vấn đề cho tập lênh SSE, các thanh ghi của SSE đã được gọi là MMX khi có chiều dài 128 bit Vì vậy khi thực hiện một lệnh mà xử lí dữ liệu 128 bit, hoạt động này phải được chia ra thành hai hoạt động 64 bit Đường dữ liệu 128 bit mới làm cho vi kiến trúc K10 xử lí nhanh hơn các lệnh SSE thao tác dữ liệu 128 bit so với K8 Bộ vi xử lí Intel dựa trên kiến trúc Core, cũng có đường dữ liệu 128 bit, trong khi bộ VXL Intel dựa trên kiến trúc Netburst (Pentium 4 vàPentium D) có 64 bit AMD gọi tính năng mới này là “AMD Wide Floating Point Accelerator”
1.2 Chi tiết mô hình, các thành phần và hoạt động của kiến trúc K10
1.2.1 Sơ đồ khối K10
AMD Athlon II sử dụng vi kiến trúc K10, tuy nhiên bị lược bỏ đi bộ phận L3 Cache
Trang 6Sơ đồ khối vi kiến trúc AMD K10
Thành phần:
1 Instructions Fetch
2 Brach Prediction
3 Decoding
4 Interger Execution Unit
5 Floating Point Unit
6 Bộ nhớ trong
7 Prefetch
Trang 71.2.2 Các bộ phận chính
Tìm nạp dòng lệnh – Instructions Fetch
Bộ xử lý bắt đầu quá trình mã hoá bằng việc tìm nạp dòng lệnh từ cache lệnh L1 và giải mã chúng.Độ dài của lệnh x86 thường không ổn định nên rất khó xác định giới hạn của chúng trước khi quá trình giải
mã bắt đầu Để đảm bảo rằng việc xác định độ dài lệnh không ảnh hưởng đến tốc độ giải mã, các bộ xử
lý K8/K10 sẽ giải mã dòng lệnh trong khi chúng đang được nhập vào cache L1 Thông tin về quá trình giải mã được chứa trong những vùng đặc biệt bên trong cache L1 (3bit thông tin trước khi giải mã cho một byte lệnh) Bằng cách giải mã trước (predecoding) trong khi đang tải lệnh vào cache, phạm vi nhữnglệnh có thể được xác định trong quá trình giải mã, cho phép đảm bảo tốc độ giải mã ổn định không phụ thuộc vào dạng thức và độ dài của lệnh
Các bộ xử lý tải các khối dòng lệnh từ cache và lấy ra các dòng lệnh mà nó cần gửi cho giải mã Một chiếc CPU sử dụng công nghệ vi cấu trúc K10 sẽ tìm nạp lệnh từ cache L1 theo các khối 32-byte, còn các bộ xử lý K8 và Core 2 thì nạp lệnh trong các khối 16-byte Khi đó, tốc độ nạp lệnh đủ nhanh để bộ xử
lý K8 và Core 2 có thể gửi được ba dòng lệnh với tốc độ giải mã trung bình là 5 byte mỗi xung nhịp Tuy nhiên, một số dòng lệnh x86 có thể dài 16 byte và theo một số thuật toán, độ dài của một số dòng lệnh cạnh đó có thể lớn hơn 5 byte Do đó, không thể giải mã ba dòng lệnh trong một xung nhịp (Hình 1)
Hình1: Một số dòng lệnh dài liền nhau làm hạn chế tốc độ giải mã trong quá trình tìm nạp dòng lệnh trong
khối 16 byte
Cụ thể, SSE2 – một dòng lệnh đơn giản với những phép toán dạng thanh ghi-thanh ghi (ví dụ, movapd xmm0, xmm1 ) – dài 4 byte Tuy nhiên, nếu dòng lệnh tạo lập bộ nhớ xác định bằng cách sử dụng thanh ghi cơ sở và Offset trống như movapd xmm0, [eax+16] , thì độ dài của nó tăng lên 6 đến 9 byte tùy thuộc vào khoảng Offset Nếu có các thanh ghi bổ sung trong chế độ 64 bit, vẫn có một REX-prefix một byte thêm vào mã dòng lệnh Khi đó, độ dài của dòng lệnh SSE2 trong chế độ 64 bit có thể tăng lên thành 7-
10 byte Các lệnh SSE1 thì ngắn hơn 1 byte nếu như đó là lệnh vector (nói cách khác là làm việc với 4 trị
số 32 bit) Nhưng nếu nó là một dòng lệnh SSE1 vô hướng (chỉ có một toán hạng), chiều dài của nó cũng
có thể tăng đến 7-10 byte trong cùng điều kiện
Trong trường hợp này, việc tìm nạp các khối 16 byte không phải là giới hạn của bộ xử lý K8, bởi nó không thể giải mã dòng lệnh vector quá 2 lần mỗi xung nhịp Tuy nhiên, đối với dòng lệnh K10, một xung nhịp 16 byte là giới hạn cuối cùng, vì thế việc tăng kích thước khối lên 32 byte là việc rất cần thiết
Trang 8Hơn nữa, các bộ xử lý Core 2 tìm nạp các khối lệnh 16- byte giống như bộ xử lý K8, đó là lý do tại sao chúng có thể giải mã 4 dòng lệnh trong mỗi xung nhịp nếu như độ dài trung bình của dòng lệnh không vượt quá 4 byte Nếu không, bộ phận giải mã sẽ không thể xử lý 4, thậm chí là 3 dòng lệnh mỗi xung nhịp Tuy nhiên, các bộ xử lý Core 2 lại có một bộ nhớ đệm trong 64 byte đặc biệt chứa các khối 16 byte được xử lý cuối cùng Các dòng lệnh được tìm nạp từ bộ nhớ đệm này với tốc độ 32 byte mỗi xung nhịp
Bộ nhớ đệm này cũng giúp thời gian cache ngắn hơn, vượt giới hạn tốc độ thông thường và có thể tiết kiệm đến 1 xung nhịp mỗi lần Mặc dù mỗi chu kì không thể chứa quá 18 dòng lệnh, 4 nhánh điều kiện
và không chứa được một dòng lệnh RET nào cả
Dự đoán rẽ nhánh – Brach Prediction
Nếu như chuỗi lệnh móc xích tới nhiều nhánh, CPU sẽ cố dự đoán xa hơn hướng của chương trình để tránh việc đứt đoạn trong quá trình giải mã và chọn lựa giải mã nhánh chắc chắn nhất Trong trường hợpnày, các thuật toán dự đoán nhánh sẽ được sử dụng để tìm nạp khối lệnh tiếp theo Các bộ xử lý K8 sử dụng thuật toán thích ứng bậc hai để dự đoán nhánh Thuật toán này xem xét quá trình dự đoán không chỉ trong dòng lệnh hiện thời, mà cả 8 dòng lệnh trước đó Nhược điểm chính của các thuật toán dự đoán nhánh K8 là chúng không có khả năng dự đoán nhánh gián tiếp có địa chỉ không cố định
Nhánh gián tiếp là các nhánh sử dụng một con trỏ (Pointer) được tính toán động trong suốt quá trình xử
lý mã chương trình Các nhánh động này thường được thêm vào các lệnh Case trong chương trình dịch
và được sử dụng trong suốt quá trình để gọi hàm địa chỉ vàhàm ảo trong việc lập trình hướng tới đối tượng Các bộ xử lý K8 thường cố sử dụng địa chỉ nhánh cuối cùng để tìm nạp một nhóm mã Nếu như địa chỉ đó đã thay đổi thì Pipe giải mã sẽ hoàn toàn trống rỗng Còn nếu địa chỉ nhánh thường xuyên thayđổi thì hệ điều hành sẽ liên tục mắc lỗi Việc dự đoán địa chỉ không cố định đối với nhánh gián tiếp được
sử dụng lần đầu tiên trong bộ xử lý Pentium M Do trong CPU K8 không có những thuật toán như vậy nên những CPU này cũng hoạt động kém hiệu quả hơn trong các mã định hướng đối tượng
K10 có những thuật toán dự đoán nhánh được cải tiến như sau:
Nó có những thuật toán dành cho địa chỉ nhánh không cố định Thuật toán này sử dụng một bảng gồm 512 yếu tố
Thanh ghi sự kiện tăng từ 8 lên 12 bit Nó có nhiệm vụ xác định tính kế tiếp cho những lệnh rẽ nhánh trước đó
Kích cỡ Ngăn xếp (Stack) địa chỉ trả về tăng từ 12 lên 24 vị trí Stack này dùng để nhanh chóng thu nhận các địa chỉ trả về để việc tìm nạp diễn ra liên tục và không cần phải đợi lệnh RET nhận địa chỉ trả về Stack nữa
Các cải tiến trên có thể giúp K10 xử lý chương trình viết bằng mã định hướng đối tượng bậc cao nhanh chóng hơn Nhưng rất khó để tính toán một cách khách quan hiệu quả của việc dự đoán nhánh 10K Theo một số dữ liệu, hiệu quả của chúng có thể thấp hơn bộ xử lý của Intel trong một số trường hợp
Trang 9 Giải mã - Decoding
Các khối lệnh nhận được từ cache lệnh được sao chép vào bộ nhớ đệm tạm thời Predecode/Pick , nơi các dòng lệnh được chọn ra từ các khối, định dạng, và chuyển vào các bộ phận ( Pipe ) giải mã tương ứng Các lệnh đơn giản có thể được giải mã chỉ bằng một hoặc hai vi lệnh ( Micro-Operation hay được
ghi Micro-Ops ) sẽ được gửi đến một bộ phận giải mã đơn giản có tên DirectPath Còn các dòng lệnh
phức tạp hơn, yêu cầu từ 3 phép toán trở lên, sẽ được gửi vào bộ phận giải mã vi chương trình được gọi
là VectorPath
Bộ phận giải mã
Cứ mỗi xung nhịp, có tối đa 3 Macro-Operation (MOP) được ra khỏi bộ phận giải mã Trong mỗi xung nhịp, bộ phận giải mã DirectPath có thể xử lý 3 lệnh 1-MOP đơn giản hoặc một lệnh 2-MOP và một lệnh1-MOP, hoặc 1.5 lệnh 2-MOP (ba lệnh 2 MOP trong hai xung nhịp) Nhưng việc giải mã các lệnh phức tạp phải cần đến hơn 3 MOP, đó chính là lý do tại sao phải cần đến vài xung nhịp mới giải mã đầy đủ được chúng Để tránh xung đột khi rời Pipe giải mã , K8 và K10 những lệnh đơn giản và phức tạp có thể được gửi liên tục để giải mã
Các MOP gồm hai vi lệnh ( Micro-Ops ) : một phép tính số nguyên hay một phép tính số học dấu phẩy động và một yêu cầu địa chỉ bộ nhớ Các vi lệnh được lấy ra từ các MOP bằng một bộ phận phân phát ( Scheduler ) , sau đó chúng được gửi để thực hiện một cách độc lập
Các MOP rời khỏi bộ giải mã trong một xung nhịp lại được kết hợp vào các nhóm ba, đôi khi là hai, hoặc thậm chí chỉ có 1 MOP bởi các lệnh DirectPath và VectorPath hay các khoảng thời gian trễ khác nhau trong việc chọn lệnh để giải mã Một nhóm không hoàn thiện như vậy cần phải bổ sung thêm các MOP rỗng để đủ 3 MOP, sau đó sẽ được chuyển đi xử lý
Các lệnh vector SSE, SSE2 và SSE3 trong bộ xử lý K8 được chia làm các cặp MOP chuyên xử lý riêng
rẽ nửa trên và nửa dưới 64 bit trong thanh ghi SSE 128 bit bằng thiết bị 64 bit Điều này làm thời gian hoàn thành quá trình giải mã tăng lên gấp đôi, và giảm số dòng lệnh chờ xuống 1 nửa
Trang 10Nhờ FPU 128 bit trong các bộ xử lý K10, không cần phải chia các lệnh vector SSE thành 2 MOP nữa Phần lớn các dòng lệnh SSE mà K8 sử dụng để giải mã như DirectPath Double đều đã được giải mã trong K10 như DirectPath Single trong 1 MOP Hơn nữa, một số lệnh SSE thường được giải mã bằng bộ phận giải mã VectorPath của K8, giờ đã có thể giải mã trong K10 với bộ giải mã đơn giản DirectPath và ítMOP hơn: chỉ có 1 hoặc 2 MOP tuỳ theo phép toán
Việc giải mã lệnh stack cũng đã được đơn giản hoá Phần lớn các lệnh stack thường được dùng trong hàm CALL-RET và PUSH-POP giờ đây đều có thể được xử lý bởi một bộ phận giải mã đơn giản với 1
MOP Không chỉ có vậy, phương pháp Sideband Stack Optimizer đặc biệt đã chuyển hoá các lệnh này
thành một chuỗi các vi lệnh mà có thể thực hiện song sông với nhau
Sideband Stack Optimizer
Các bộ phận giải mã trong các bộ xử lý K10 kiểu mới có một khối đặc biệt có tên Sideband Stack Optimizer Nguyên tắc hoạt động của nó cũng tương tự như Stack Pointer Tracker trong bộ xử lý Core.
Vậy tại sao chúng ta cần đến nó? Hệ thống x86 sử dụng lệnh CALL, RET, PUSH và POP để lập hàm, xoá hàm, chuyển tham số và giữ lại những nội dung liên quan tới những thanh ghi Tất cả những lệnh này sử dụng thanh ghi ESP để gián tiếp xác định giá trị Stack-Pointer hiện thời Khi bạn sử dụng một hàm trong bộ xử lý K8, bạn có thể thực hiện quá trình xử lý lệnh bằng cách thiết lập quá trình giải mã nhưmột chuỗi các phép tính đơn giản
Lệnh Phép tính tương ứng
// hàm (x, y, z);
push Xpush Ypush Zcall func
sub esp, 4; mov [esp], Xsub esp, 4; mov [esp], Ysub esp, 4; mov [esp], Zsub esp, 4; mov [esp], eip; jmp func
push esipush edimov eax, [esp+16]
pop edi,pop esiret
sub esp, 4; mov [esp], esisub esp, 4; mov [esp], edimov eax, [esp+16]
mov edi, [esp]; add esp, 4mov esi, [esp]; add esp, 4jmp [esp]; add esp, 4
add esp, 12 add esp, 12
Trang 11Trong ví dụ trên, khi sử dụng một hàm nào đó, các lệnh sẽ không ngừng thay đổi thanh ghi ESP, vì vậy mỗi lệnh tiếp theo chỉ đơn giản là dựa trên kết quả của lệnh trước đó Các lệnh trong chuỗi này không thể
được sử dụng lại, đó là lý do tại sao hàm mở đầu bằng mov eax, [esp+16] không thể bắt đầu trừ khi
lệnh PUSH trước đó đã được thực hiện Sideband Stack Optimize sẽ lần theo sự thay đổi trạng thái Stack ( Ngăn xếp ) và biến đổi chuỗi lệnh thành một chuỗi độc lập bằng cách điều chỉnh khoảng trống Stack đối với mỗi lệnh và đặt các phép tính MOP đồng bộ (phần cuối cùng của quá trình đồng bộ hoá stack) trước các lệnh làm việc trực tiếp với thanh ghi stack Bằng cách này, các lệnh làm việc trực tiếp với Stack có thể được sử dụng lại vô giới hạn
Lệnh Phép tính tương ứng
// hàm (x, y, z);
push Xpush Ypush Zcall func
mov [esp-4], Xmov [esp-8], Ymov [esp-12], Zmov [esp-16], eip; jmp func
push esipush edi
mov eax, [esp+16]
pop edi,pop esiret
mov [esp-20], esimov [esp-24], edisub esp, 24mov eax, [esp+16]
mov esi, [esp]
mov edi, [esp+4]
Trang 12Lệnh mov eax, [esp+16] bắt đầu bằng việc tính toán hàm trong ví dụ trên phụ thuộc vào phép tính MOP đồng bộ Giờ đây các phép tính này có thể được thực hiện đồng thời sau các lệnh trước đó Như vậy, việc giải quyết các tham số và tiết kiệm thanh ghi diễn ra nhanh hơn và hàm số có thể bắt đầu tải các tham số trên rồi xử lý chúng trước cả khi tất cả đã được chuyển đổi thành công và việc tiết kiệm thanh ghi đã hoàn tất
Vì vậy, với việc giải mã phép tính nhanh hơn, Sideband Stack Optimizer, stack địa chỉ trả về lớn hơn và việc dự đoán thành công nhánh động khiến cho K10 hoạt động tốt hơn nhiều trong việc xử lý mã nhiều hàm số
Bộ phận giải mã trong K10 sẽ không thể giải mã 4 lệnh trong mỗi xung nhịp giống như trong bộ xử lý Core 2 trong điều kiện thuận lợi, nhưng đây không phải là vấn đề lớn trong việc xử lý chương trình Tốc
độ xử lý lệnh trung bình hiếm khi đạt đến con số ba trong mỗi xung nhịp, vì thế bộ phận giải mã của K10 cũng đủ hiệu quả cho các thiết bị điện toán bởi chúng không thiếu bất kỳ lệnh nào, và vì thế có thể hoạt động liên tục
Bộ phận điều khiển lệnh - Instruction Control Unit (ICU)
Bộ ba MOP đã được giải mã sẽ đến Bộ phận điều khiển lệnh (ICU) để chuyển đến bộ nhớ đệm sắp xếp lại (ROB- ReOrder Buffer ) Bộ nhớ đệm này bao gồm 24 dòng, mỗi dòng có 3 MOP Mỗi bộ ba MOP được viết trong một dòng Vì vậy, ROB cho phép bộ phận quản lý lệnh nắm được trạng thái của tối đa 72MOP cho đến khi chúng ngừng hoạt động
Từ bộ nhớ đệm ROB này, những MOP được gửi nhanh đến Bộ phận cấp phát ( Scheduler ) của những
Bộ phận xử lí số nguyên và dấu phẩy động sắp hàng theo đúng thứ tự như vậy Đến lúc này, MOP sẽ ngưng hoạt động trong bộ phận giải mã Các bộ ba MOP sẽ được lưu trữ trong ROB cho đến khi tất cả các phép tính cũ hơn đều đã được xử lý và chấm dứt hoạt động Khi ngừng hoạt động, những trị số cuối cùng sẽ được ghi lại trong những thanh ghi cấu trúc và bộ nhớ Còn thứ tự chương trình, cách sắp xếp phép tính trong ROB, vẫn được giữ nguyên khi các phép tính đã chấm dứt, dữ liệu của chúng bị xoá khỏiROB nhưng các trị số cuối cùng vẫn được giữ lại Việc đảm bảo rằng kết quả của tất cả các phép tính sau này được hoàn thành trước thời hạn có thể bị xoá trong một số trường hợp ngoại lệ hoặc ngắt
Bộ phận xử lý số nguyên – Interger Execution Unit
Bộ phận xử lý số nguyên của các bộ xử lý K8 và K10 gồm ba Pipe số nguyên đối xứng Mỗi Pipe này có
bộ phận Scheduler riêng với một hàng đợi 8-MOP, một bộ đơn vị số học và logic (ALU – Arithmetic and Logical Unit ), một đơn vị tạo địa chỉ (AGU – Address Generation Unit ) và một đơn vị dự đoán rẽ nhánh Ngoài ra, còn có một đơn vị nhân nối với Pipe 0, còn Pipe 2 thì được nối với đơn vị xử lý các phép tính mới: LZCNT và POPCNT mà chúng ta sẽ tìm hiểu kỹ hơn trong phần sau của bài báo này
Trang 13Bộ phậnxử lý số nguyên
Trang 14Lựa chọn hàng đợi cho mỗi MOP tuỳ thuộc vào vị trí cố định của lệnh trong bộ ba Mỗi Macro-Operation trong bộ ba lại được gửi đến Bộ đệm sắp xếp lại (ROB) để xử lý trong đó Một mặt, nó giúp đơn giản hoáviệc quản lý lệnh, nhưng mặt khác, nó có thể dẫn đến việc hàng đợi bị mất cân bằng nếu như một chuỗi phép tính độc lập được xếp đặt không thích hợp trong mã chương trình (trong thực tế điều này hiếm khi xảy ra và cũng ít ảnh hưởng đến hiệu quả làm việc) Bộ phận giải mã sẽ sắp đặt phép nhân và mở rộng các phép tính Bit mở rộng trong nhóm bộ ba tương ứng để chúng được chuyển đến Pipe thích hợp
Trang 15Như đã đề cập từ trước, các MOP sẽ được tách làm các phép tính số nguyên và phép tính địa chỉ bộ nhớ trong hàng đợi Scheduler của Pipe số nguyên Dựa vào từng dữ liệu, Scheduler có thể chuyển một phép tính số nguyên sang ALU và một phép tính địa chỉ sang AGU từ mỗi hàng đưọi Có tối đa hai yêu cầu bộ nhớ đồng thời Vì vậy, nhiều nhất là ba phép tính số nguyên và 2 phép tính bộ nhớ (64 bit được đọc/viết) được xử lý trong mỗi xung nhịp Còn các Micro-Operation từ nhiều MOP khác nhau có thể được
xử lý không theo thứ tự mà tuỳ thuộc vào dữ liệu sẵn sàng Ngay khi phép tính vi lệnh ( Micro-Ops ) số học và MOP đã được xử lý, MOP sẽ rời khỏi hàng đợi lập Scheduler nhường chỗ cho các phép tính khác
Các bộ xử lý K8 sẽ chọn phép tính Micro-Ops đòi hỏi địa chỉ bộ nhớ theo mức độ chương trình Các yêu cầu bộ nhớ xuất hiện sau trong mã chương trình không thể được xử lý trước những phép tính trước đó
Vì thế, nếu như các phép tính trước chưa được thực hiện, tất cả những phép tính địa chỉ sau đó cũng không thể tiến hành ngay cả khi các toán hạng đã sẵn sàng
Ví dụ:
add ebx, ecx
mov eax, [ebx+10h] – Phép tính nhanh địa chỉ
mov ecx, [eax+ebx] – địa chỉ phụ thuộc vào kết quả của lệnh trước đó
mov edx, [ebx+24h] – lệnh này sẽ không được gửi đi thực hiện cho đến khi tất cả địa chỉ của các lệnh trước đó đã được tính toán xong.
Việc này có thể ảnh hưởng đến tốc độ xử lý của K8 do bị “thắt nút cổ chai” Do đó, mặc dù bộ xử lý K8
có thể tiến hành hai lệnh mỗi xung nhịp, trong một số mã nhất định, nó có thể thực hiện đòi hỏi bộ nhớ kém hiệu quả hơn bộ xử lý Core 2, chỉ đọc được một lệnh mỗi xung nhịp, nhưng lại áp dụng quy tắc xử lýlệnh không theo thứ tự và có thể đọc hoặc ghi trước các lệnh trước đó
Các CPU sử dụng công nghệ vi cấu trúc K10 sẽ không gặp phải tình trạng này nữa Giờ đây các bộ xử lýK10 không chỉ có khả năng đọc lệnh không theo thứ tự, mà còn có thể viết lệnh trước khi đọc nếu như CPU chắc chắn rằng không có xung đột địa chỉ xảy ra giữa việc viết lệnh và đọc lệnh Bằng cách viết lệnh trước khi đọc, bộ xử lý có thể tăng đáng kể tốc độ xử lý một số loại mã, ví dụ như bắt đầu quá trình đọc bằng một dữ liệu đọc từ bộ nhớ, và kết thúc bằng việc viết kết quả tính toán vào bộ nhớ
Trong những trường hợp như thế này, bộ xử lý không thể đọc dữ liệu trước khi viết hay bắt đầu quá trình
xử lý tiếp theo trước khi kết quả của quá trình hiện tại vẫn chưa được ghi hết vào bộ nhớ Loại CPU hỗ
Trang 16trợ việc sắp xếp lại dữ liệu đọc có thể bắt đầu tải dữ liệu mới cho vòng xử lý tiếp theo mà không phải đợi lần xử lý này kết thúc
Không may là bộ xử lý K10 lại không thể bắt đầu quá trình tải trước dữ liệu khi chưa hoàn thành việc viết
dữ liệu nếu như vẫn chưa biết được địa chỉ như bộ xử lý Core 2 Mặc dù việc này có thể gây ra một số lỗi, nhưng việc này rất hiếm khi xảy ra trong mã chương trình thực tế (chỉ khoảng 5%) Dó là lý do tại sao việc tải trước dữ liệu rất thích hợp cho việc tăng tốc độ làm việc của bô xử lý
Ngoài ra, một cải tiến khác của đơn vị số nguyên K10 là sự tối ưu hoá thuật toán chia số nguyên Hiện tại, tốc độ của các phép tính chia số nguyên tuỳ thuộc vào bit lớn nhất của số chia và số bị chia Ví dụ, nếu số bị chia bằng 0, phép chia sẽ thực hiện mất khoảng 1 nửa thời gian Thực ra, phép chia số nguyên
là một phép tính rất ít dùng bởi chúng thực hiện khá chậm, nên mã lập trình thường tránh sử dụng chúng Phép chia thường được thay thế bằng phép nhân nghịch đảo, đó là lý do tại sao việc tối ưu hoá này thường không ảnh hưởng nhiều tới tốc độ xử lý chung của ứng dụng
Nói chung, đơn vị số nguyên của K10 cũng không phải là hoàn hảo Sau khi thêm vào quá trình xử lý đòi hỏi bộ nhớ không theo thứ tự, chúng sẽ không gặp phải những vẫnđề như trên nữa Mặc dù K10 không
có hàng chờ lớn như Core 2, nó lại có khả năng đọc file thanh ghi cũng như lập biểu vô giới hạn, điều màCore 2 không thể thực hiện được với tốc độ tối đa
Bộ phận dấu phẩy động – Floating Point Unit
Bộ phận Scheduler đơn vị dấu phẩy động (FPU) của các bộ xử lý K8 và K10 được tách riêng khỏi bộ phận Scheduler đơn vị số nguyên và có thiết kế khác đi một chút Bộ nhớ đệm của Scheduler có thể cung cấp tối đa 12 nhóm, mỗi nhóm gồm 3 MOP (theo lý thuyết là 36 phép tính dấu phẩy động) Khác với
Bộ phận số nguyên có các Pipe đối xứng, FPU gồm có ba phần khác nhau: FADD cho phép cộng dấu phảy động , FMUL cho phép nhân dấu phảy động và FMISC (còn được gọi là FSTORE) cho các phép tính lưu trong bộ nhớ và phép tính bổ trợ Do đó, bộ nhớ đệm Scheduler không cố định rõ các MOP vào từng nhóm trong một khác nhau ( theo hình dưới )
Đơn vị dấu phẩy động
Mỗi xung nhịp, K8 và K10 có thể gửi một phép tính đến đơn vị dấu phẩy động để xử lý Bộ xử lý K8 sử dụng đơn vị dấu phẩy động 80 bit Tại phần giải mã, các lệnh vector SSE 128 bit sẽ được tách làm hai
Trang 17MOP xử lý hai nửa 64 bit của một toán hạng 128 bit Các MOP này sẽ được xử lý lần lượt tại các xung nhịp khác nhau Điều này không chỉ làm chậm tiến độ xử lý lệnh vector, mà còn làm giảm kích thước của
bộ nhớ đệm Scheduler FPU xuống một nửa, và do đó giảm hiệu quả việc xử lý lệnh không theo thứ tự Chiếu rộng của đơn vị bộ nhớ đệm trong bộ xử lý K10 được tăng lên tới 128 bit K10 có thể xử lý các toán hạng vector 128 bit trong một phép tính đơn, giúp tăng gấp đôi (theo lý thuyết) tốc độ xử lý lệnh vector SSE so với K8 Hơn nữa, do lượng MOP hiện giờ đã giảm xuống một nửa, độ dài của hàng đợi Scheduler sẽ tăng lên, giúp tăng hiệu quả của việc xử lý không theo thứ tự ( OOO : Out-Of- Order ) đượcsâu hơn
Bộ xử lý K8 thực hiện tải những lệnh SSE bằng cách sử dụng Bộ phận FSTORE Một mặt, nó không cho phép xử lý cùng lúc bất kỳ lệnh nào khác cần sử dụng Bộ phận này Mặt khác, nó chỉ cho phép một lần tải lệnh cùng lúc K8 chỉ có thể đọc song song hai lệnh cùng lúc nếu một trong số các lệnh đó kết hợp một phép tính bộ nhớ và một phép tính dữ liệu (còn gọi là lệnh Load-Execute), ví dụ như ADDPS xmm1, [esi].
Các bộ xử lý K10 sẽ cải thiện quá trình tải những lệnh SSE
Đầu tiên, các lệnh tải dữ liệu sẽ không sử dụng tài nguyên trong FPU nữa Bằng cách này, cổng
FSTORE sẽ trống và có thể dùng để thực hiện các lệnh khác Hai lệnh đã tải hiện tại đã có thể xử lý trong một xung nhịp
Thứ hai, nếu như dữ liệu trong bộ nhớ được xết trong khối 16 byte, thì việc tài dữ liệu tự do (MOVU**) cũng hiệu quả như việc tải dữ liệu đã sắp xếp (MOVA**) Vì vậy, việc sử dụng MOVA** không còn là lợi thế đối với các bộ xử lý K10 nữa
Thứ ba, các bộ xử lý K10 giờ đã có thể tiến hành tải dữ liệu tự do ngay cả đối với lệnh Load-Execute Nếu vẫn chưa rõ dữ liệu trong bộ nhớ đã được xếp vào từng khối chưa, người lập trình thường sử dụng lệnh MOVU** để đọc dữ liệu vào thanh ghi để xử lý thêm Bằng cách tải dữ liệu tự do cùng với lệnh Load-Execute, họ có thể giảm đáng kể số lệnh đã tải trong mã chương trình, và do đó, tăng tốc độ xử lý Tính năng này sẽ rất có ích cho các lập trình viên Thực ra, Intel cho rằng một yêu cầu từ lệnh Load-Execute chuyển đến một địa chỉ chưa được sắp xếp vào khối 16 byte là trường hợp ngoại lệ Để giữ vững tính tương thích, các dữ liệu tự do và lệnh Load-Execute nên được gắn dấu hiệu đặc biệt trong mã chương trình được thiết kế và xếp vào các tính năng xử lý mới
Thứ 4, hai bus dữ liệu từ cache L1 của bộ xử lý K10 đã được tăng lên thành 128 bit Do đó, CPU có thể đọc hai khối dữ liệu 128 bit trong mỗi xung nhịp Đây là điều rất đặc biệt bởi 2 lệnh lại cần 4 toán hạng mới có thể được xử lý song song cùng một lúc (hai toán hạng mỗi lệnh), và trong một số thuật toán xử lý
dữ liệu, thường thì hai trong số bốn toán hạng sẽ được đọc từ RAM Trái lại, hai bus viết dữ liệu trong bộ
xử lý K10 vẫn rộng 64 bit lại được chia làm hai gói 64 bit khi ghi vào bộ nhớ Vì vậy, trong mỗi xung nhịp, CPU chỉ có thể viết hoặc đọc 128 bit, hay đọc 128 bit và viết 64 bit Tuy nhiên, do số dữ liệu đọc thường gấp ít nhất hai lần dữ liệu viết, nên giới hạn này không ảnh hưởng đến hiệu quả của bộ xử lý đối với dữ liệu 128 bit