You are on page 1of 84

Translated from English to Vietnamese - www.onlinedoctranslator.

com

4 Hướng dẫn khai thác


Mức độ song song với
Phương pháp tiếp cận phần mềm 4

Các bộ vi xử lý đang được sản xuất với tiềm năng cho rất nhiều hoạt động song
song trên cấp độ lệnh .... Các cực trị lớn hơn nhiều trong chế độ song song cấp
độ lệnh đang ở trên đường chân trời.

J. Fisher [1981], trong bài báo mở đầu thuật ngữ


"song song mức hướng dẫn"

Một trong những điều ngạc nhiên về IA-64 là chúng tôi không nghe thấy tuyên bố nào
về tần số cao, mặc dù tuyên bố rằng bộ xử lý EPIC ít phức tạp hơn bộ xử lý siêu thanh.
Thật khó để biết tại sao điều này lại như vậy, nhưng người ta có thể suy đoán rằng sự
phức tạp tổng thể liên quan đến việc tập trung vào CPI, như IA-64, khiến cho việc đạt
được megahertz cao là khó.

M. Hopkins [2000], trong một bài bình luận về kiến trúc IA-64, sự
phát triển chung của HP và Intel được thiết kế để đạt được sự gia
tăng đáng kể trong việc khai thác ILP trong khi vẫn giữ được một
kiến trúc đơn giản, cho phép hiệu suất cao hơn.
4.1 Các kỹ thuật biên dịch cơ bản để hiển thị ILP 221

4.2 Dự đoán nhánh tĩnh 231

4.3 Nhiều vấn đề tĩnh: Phương pháp tiếp cận VLIW 234

4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 238

4.5 Hỗ trợ phần cứng để hiển thị nhiều song song hơn tại thời gian biên dịch 260

4.6 Các vấn đề về cắt ngang 270

4.7 Kết hợp tất cả lại với nhau: Kiến trúc Intel IA-64 và Bộ xử lý Itanium 271

4.8 Góc nhìn khác: ILP trong Thị trường Nhúng và Di động 283

4.9 Những sai lầm và cạm bẫy 292

4.10 Nhận xét kết luận 293

4.11 Quan điểm lịch sử và tài liệu tham khảo 295

Bài tập 299

4.1Các kỹ thuật biên dịch cơ bản để hiển thị ILP


Chương này bắt đầu bằng cách xem xét việc sử dụng công nghệ trình biên dịch để cải
thiện hiệu suất của các đường ống và bộ xử lý nhiều vấn đề đơn giản. Các kỹ thuật này
là chìa khóa ngay cả đối với bộ xử lý đưa ra quyết định vấn đề động nhưng sử dụng
lập lịch tĩnh và rất quan trọng đối với bộ xử lý sử dụng vấn đề tĩnh hoặc lập lịch tĩnh.
Sau khi áp dụng các khái niệm này để giảm thiểu các nguy cơ dữ liệu trong các đường
ống dẫn sự cố đơn lẻ, chúng tôi kiểm tra việc sử dụng các kỹ thuật dựa trên trình biên
dịch để dự đoán nhánh. Được trang bị công nghệ trình biên dịch mạnh mẽ hơn này,
chúng tôi kiểm tra thiết kế và hiệu suất của bộ xử lý nhiều vấn đề bằng cách sử dụng
lập lịch hoặc phát hành tĩnh. Phần 4.4 và 4.5 kiểm tra các kỹ thuật phần mềm và phần
cứng nâng cao hơn, được thiết kế để cho phép bộ xử lý khai thác song song mức lệnh
hơn. Đặt tất cả cùng nhau kiểm tra kiến trúc IA-64 và triển khai đầu tiên của nó,
Itanium. Hai bộ xử lý kiểu VLIW tĩnh, khác nhau được đề cập trong Chế độ xem khác.
222 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Lập lịch đường ống cơ bản và mở vòng lặp


Để giữ cho một đường ống luôn đầy đủ, phải khai thác tính song song giữa các
lệnh bằng cách tìm chuỗi các lệnh không liên quan có thể chồng lên nhau trong
đường ống. Để tránh bị đình trệ đường ống, một lệnh phụ thuộc phải được tách
biệt với lệnh nguồn một khoảng cách trong chu kỳ đồng hồ bằng với độ trễ
đường ống của lệnh nguồn đó. Khả năng của trình biên dịch để thực hiện việc lập
lịch này phụ thuộc cả vào lượng ILP có sẵn trong chương trình và độ trễ của các
đơn vị chức năng trong đường dẫn. Trong suốt chương này, chúng ta sẽ giả định
các độ trễ đơn vị FP được hiển thị trong Hình 4.1, trừ khi các độ trễ khác nhau
được nêu rõ ràng. Chúng tôi giả sử đường ống số nguyên 5 giai đoạn tiêu chuẩn,
do đó các nhánh có độ trễ là một chu kỳ đồng hồ. Chúng tôi giả định rằng các
đơn vị chức năng được tạo đường ống hoặc tái tạo hoàn toàn (nhiều lần so với độ
sâu đường ống),

Hướng dẫn tạo ra kết quả Hướng dẫn sử dụng kết quả Độ trễ trong chu kỳ đồng hồ

FP ALU op Một op ALU FP khác 3


FP ALU op Cửa hàng gấp đôi 2
Tải gấp đôi FP ALU op 1
Tải gấp đôi Cửa hàng gấp đôi 0
HÌNH 4.1 Độ trễ của các hoạt động FP được sử dụng trong chương này.Cột đầu tiên hiển
thị loại lệnh bắt đầu. Cột thứ hai là loại lệnh tiêu thụ. Cột cuối cùng là số chu kỳ đồng hồ can
thiệp cần thiết để tránh tình trạng ngừng hoạt động. Những con số này tương tự như độ trễ
trung bình mà chúng ta sẽ thấy trên một đơn vị FP. Độ trễ của tải điểm thực đối với một cửa
hàng bằng 0, vì kết quả của tải có thể được bỏ qua mà không làm đình trệ cửa hàng. Chúng
tôi sẽ tiếp tục giả định độ trễ tải số nguyên là 1 và độ trễ hoạt động ALU số nguyên là 0.

Trong tiểu mục này, chúng ta xem xét cách trình biên dịch có thể tăng số lượng ILP có
sẵn bằng cách mở các vòng lặp. Ví dụ này vừa để minh họa một kỹ thuật quan trọng vừa để
thúc đẩy các phép biến đổi chương trình mạnh mẽ hơn được mô tả ở phần sau của chương
này. Chúng ta sẽ dựa vào một ví dụ tương tự như ví dụ chúng ta đã sử dụng trong chương
trước, thêm một đại lượng vô hướng vào một vectơ:

vì(i = 1000; i> 0; i = i – 1)


x [i] = x [i] + s;

Chúng ta có thể thấy rằng vòng lặp này là song song bằng cách nhận thấy rằng phần thân của mỗi lần lặp
là độc lập. Chúng tôi sẽ chính thức hóa khái niệm này ở phần sau của chương này và mô tả cách chúng tôi
có thể kiểm tra xem các lần lặp vòng lặp có độc lập tại thời điểm biên dịch hay không. Đầu tiên, chúng ta
hãy xem xét hiệu suất của vòng lặp này, cho thấy cách chúng ta có thể sử dụng song song để cải thiện
hiệu suất của nó cho một đường ống MIPS với độ trễ được hiển thị ở trên.
Bước đầu tiên là dịch đoạn trên sang hợp ngữ MIPS. Trong đoạn mã
sau,R1ban đầu là địa chỉ của phần tử trong mảng
4.1 Các kỹ thuật biên dịch cơ bản để hiển thị ILP 223

với địa chỉ cao nhất, vàF2chứa giá trị vô hướng,S.Đăng kýR2được tính toán
trước, do đó8 (R2)là phần tử cuối cùng để hoạt động.
Mã MIPS đơn giản, không được lập lịch cho đường dẫn, trông giống như sau:

Vòng: LD F0,0 (R1) ; F0 = phần tử mảng


ADD.D F4, F0, F2 ; thêm vô hướng trong
SD F4,0 (R1) F2; lưu trữ kết quả
DADDUI R1, R1, # - 8 ; con trỏ giảm
; 8 byte (mỗi DW);
BNE R1, R2, Vòng lặp nhánh R1! = Không

Hãy bắt đầu bằng cách xem vòng lặp này sẽ chạy tốt như thế nào khi nó được lập lịch
trên một đường dẫn đơn giản cho MIPS với độ trễ từ Hình 4.1.

THÍ DỤ Cho biết vòng lặp sẽ trông như thế nào trên MIPS, cả theo lịch trình và không theo lịch trình,
bao gồm bất kỳ sự cố hoặc chu kỳ đồng hồ không hoạt động nào. Lập lịch cho cả sự chậm
trễ từ hoạt động dấu phẩy động và từ nhánh bị trì hoãn.

CÂU TRẢ LỜI Nếu không có bất kỳ lịch trình nào, vòng lặp sẽ thực thi như sau:

Chu kỳ đồng hồ được phát hành

Vòng lặp: LD F0,0 (R1) 1


quầy hàng 2
ADD.D F4, F0, F2 3
quầy hàng 4
quầy hàng 5
SD F4,0 (R1) 6
DADDUI R1, R1, # - 8 7
quầy hàng số 8
BNE R1, R2, Vòng lặp 9
quầy hàng 10

Mã này yêu cầu 10 chu kỳ xung nhịp cho mỗi lần lặp.

Vòng: LD F0,0 (R1)


DADDUI R1, R1, # - 8
ADD.D F4, F0, F2
quầy hàng

BNE R1, R2, Vòng lặp ; chi nhánh bị trì hoãn


SD F4,8 (R1) ; đã thay đổi & hoán đổi với
DADDUI

Thời gian thực thi đã giảm từ 10 chu kỳ đồng hồ xuống còn 6 chu kỳ đồng hồ
ADD.Dlà để sử dụng bởiSD N
224 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Lưu ý rằng để lên lịch cho nhánh bị trì hoãn, trình biên dịch phải xác định
rằng nó có thể hoán đổiDADDUIvàSDbằng cách thay đổi địa chỉ màSD
được lưu trữ: địa chỉ là0 (R1)và bây giờ là8 (R1).Thay đổi này không phải là nhỏ,
vì hầu hết các trình biên dịch sẽ thấy rằngSDhướng dẫn phụ thuộc vào
DADDUIvà sẽ từ chối trao đổi chúng. Một trình biên dịch thông minh hơn, có
khả năng tối ưu hóa biểu tượng hạn chế, có thể tìm ra mối quan hệ và thực
hiện trao đổi. Chuỗi các hướng dẫn phụ thuộc từLDđếnADD.Dvà sau đó đến
SDxác định số chu kỳ xung nhịp cho vòng lặp này. Chuỗi này phải mất ít nhất 6
chu kỳ vì sự phụ thuộc và độ trễ của đường ống.
Trong ví dụ trên, chúng ta hoàn thành một lần lặp vòng lặp và lưu trữ lại một phần
tử mảng sau mỗi 6 chu kỳ đồng hồ, nhưng công việc thực tế của hoạt động trên phần
tử mảng chỉ mất 3 (tải, thêm và lưu trữ) trong số 6 chu kỳ đồng hồ đó. 3 chu kỳ đồng
hồ còn lại bao gồm chi phí vòng lặp —DADDUIvàBNE—và một quầy hàng. Để loại bỏ 3
chu kỳ xung nhịp này, chúng ta cần nhận được nhiều hoạt động hơn trong vòng lặp
liên quan đến số lượng lệnh trên đầu.
Một sơ đồ đơn giản để tăng số lượng các lệnh liên quan đến các lệnh
nhánh và chi phí làmở vòng lặp. Việc hủy cuộn chỉ cần sao chép nội dung
vòng lặp nhiều lần, điều chỉnh mã kết thúc vòng lặp.
Bỏ cuộn vòng lặp cũng có thể được sử dụng để cải thiện việc lập lịch. Bởi vì nó loại bỏ nhánh,
nó cho phép các lệnh từ các lần lặp khác nhau được lên lịch cùng nhau. Trong trường hợp này,
chúng ta có thể loại bỏ tình trạng ngừng sử dụng dữ liệu bằng cách tạo thêm các hướng dẫn độc
lập trong phần thân của vòng lặp. Nếu chúng ta chỉ sao chép các hướng dẫn khi chúng ta mở vòng
lặp, thì việc sử dụng các thanh ghi giống nhau có thể ngăn chúng ta lập lịch vòng lặp một cách
hiệu quả. Do đó, chúng ta sẽ muốn sử dụng các thanh ghi khác nhau cho mỗi lần lặp, làm tăng số
lượng thanh ghi cần thiết.

THÍ DỤ Hiển thị vòng lặp của chúng tôi chưa được cuộn để có bốn bản sao của
phần thân vòng lặp, giả sửR1ban đầu là bội số của 32, có nghĩa là số lần
lặp vòng lặp là bội số của 4. Loại bỏ mọi phép tính thừa rõ ràng và
không sử dụng lại bất kỳ thanh ghi nào.

CÂU TRẢ LỜI Đây là kết quả sau khi hợp nhấtDADDUIhướng dẫn và bỏ những thứ không
cần thiếtBNEcác thao tác bị trùng lặp trong quá trình hủy cuộn. Lưu ý rằng
R2bây giờ phải được thiết lập để32 (R2)là địa chỉ bắt đầu của bốn phần tử
cuối cùng.

Vòng: LD F0,0 (R1)


ADD.D F4, F0, F2
SD F4,0 (R1) ; bỏ DADDUI & BNE
LD F6, -8 (R1)
ADD.D F8, F6, F2
SD F8, -8 (R1) ; bỏ DADDUI & BNE
LD F10, -16 (R1)
4.1 Các kỹ thuật biên dịch cơ bản để hiển thị ILP 225

ADD.D F12, F10, F2


SD F12, -16 (R1) ; bỏ DADDUI & BNE
LD F14, -24 (R1)
ADD.D F16, F14, F2
SD F16, -24 (R1)
DADDUI R1, R1, # - 32
BNE R1, R2, Vòng lặp

Chúng tôi đã loại bỏ ba nhánh và ba nghị định củaR1.Các địa chỉ trên tải
và cửa hàng đã được bù đắp để cho phép DADDUIhướng dẫn vềR1để
được hợp nhất. Tối ưu hóa này có vẻ tầm thường, nhưng nó không phải
là; nó đòi hỏi sự thay thế và đơn giản hóa biểu tượng.

Nếu không có lịch trình, mọi hoạt động trong vòng lặp chưa được thực hiện đều được
theo sau bởi một hoạt động phụ thuộc và do đó sẽ gây ra tình trạng đình trệ. Vòng lặp này sẽ
chạy trong 28 chu kỳ đồng hồ — mỗi chu kỳLDcó 1 gian hàng, mỗiADD.D2,DADDUI1, nhánh 1,
cộng với 14 chu kỳ phát lệnh — hoặc 7 chu kỳ đồng hồ cho mỗi phần tử trong số bốn phần tử.
Mặc dù phiên bản chưa được đăng ký này hiện chậm hơn phiên bảnlên kế hoạchphiên bản
của vòng lặp ban đầu, điều này sẽ thay đổi khi chúng tôi lập lịch cho vòng lặp chưa được
cuộn. Việc giải nén vòng lặp thường được thực hiện sớm trong quá trình biên dịch, do đó các
tính toán thừa có thể được trình bày và loại bỏ bởi trình tối ưu hóa.
N

Trong các chương trình thực, chúng ta thường không biết giới hạn trên của vòng lặp. Giả
sử nó làNvà chúng tôi muốn mở vòng lặp để làm chokcác bản sao của cơ thể. Thay vì một
vòng lặp chưa được cuộn, chúng tôi tạo một cặp vòng lặp liên tiếp. Lần thực thi đầu tiên (N
modk) lần và có phần thân là vòng lặp ban đầu. Thứ hai là phần thân chưa được cuộn được
bao quanh bởi một vòng lặp bên ngoài lặp lại (N/k) lần. Đối với các giá trị lớn củaN, hầu hết
thời gian thực thi sẽ được sử dụng trong phần thân của vòng lặp chưa được cuộn.
Trong Ví dụ trên, việc bỏ cuộn cải thiện hiệu suất của vòng lặp này bằng cách loại
bỏ các lệnh trên đầu, mặc dù về cơ bản nó làm tăng kích thước mã. Vòng lặp chưa
được cuộn sẽ hoạt động như thế nào khi nó được lập lịch cho đường ống được mô tả
trước đó?

THÍ DỤ Hiển thị vòng lặp chưa được cuộn trong ví dụ trước sau khi nó đã được lên
lịch cho đường ống với độ trễ được hiển thị trong Hình 4.1 trên trang 222.

CÂU TRẢ LỜI Vòng: LD F0,0 (R1)


LD F6, -8 (R1)
LD F10, -16 (R1)
LD F14, -24 (R1)
ADD.D F4, F0, F2
226 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

ADD.D F8, F6, F2


ADD.D F12, F10, F2
ADD.D F16, F14, F2
SD F4,0 (R1)
SD F8, -8 (R1)
DADDUI R1, R1, # - 32
SD F12,16 (R1)
BNE R1, R2, Vòng lặp
SD F16,8 (R1) ; 8-32 = -24

Thời gian thực hiện của vòng lặp chưa được cuộn đã giảm xuống tổng cộng 14 chu kỳ
đồng hồ, hoặc 3,5 chu kỳ đồng hồ cho mỗi phần tử, so với 7 chu kỳ cho mỗi phần tử
trước khi lập lịch và 6 chu kỳ khi được lập lịch nhưng không được hủy cuộn.
N

Lợi ích từ việc lập lịch trên vòng lặp không được cuộn thậm chí còn lớn hơn so với vòng
lặp ban đầu. Sự gia tăng này phát sinh do việc mở vòng lặp cho thấy nhiều tính toán hơn có
thể được lên lịch để giảm thiểu các gian hàng; mã trên không có gian hàng. Lên lịch cho
vòng lặp theo kiểu này đòi hỏi bạn phải nhận ra rằng các tải hàng và cửa hàng là độc lập và
có thể thay đổi cho nhau.

Tóm tắt về Ví dụ về Mở vòng lặp và Lập lịch


Trong suốt chương này, chúng ta sẽ xem xét một loạt các kỹ thuật phần cứng và phần mềm
cho phép chúng ta tận dụng tính song song mức hướng dẫn để sử dụng đầy đủ tiềm năng
của các đơn vị chức năng trong một bộ xử lý. Chìa khóa của hầu hết các kỹ thuật này là biết
khi nào và như thế nào thứ tự giữa các hướng dẫn có thể được thay đổi. Trong ví dụ của
chúng tôi, chúng tôi đã thực hiện nhiều thay đổi như vậy, mà đối với chúng tôi, với tư cách là
con người, rõ ràng là có thể cho phép. Trong thực tế, quá trình này phải được thực hiện một
cách bài bản bằng trình biên dịch hoặc bằng phần cứng. Để có được mã chưa được cuộn
cuối cùng, chúng tôi phải thực hiện các quyết định và chuyển đổi sau:

1. Xác định rằng việc di chuyểnSDsauDADDUIvàBNE,và tìm số tiền để điều


chỉnhSDbù lại.
2. Xác định rằng việc hủy cuộn vòng lặp sẽ hữu ích bằng cách nhận thấy rằng các
lần lặp vòng lặp là độc lập, ngoại trừ mã duy trì vòng lặp.

3. Sử dụng các thanh ghi khác nhau để tránh các ràng buộc không cần thiết có thể bị ép buộc bằng cách
sử dụng các thanh ghi giống nhau cho các tính toán khác nhau.

4. Loại bỏ kiểm tra bổ sung và hướng dẫn rẽ nhánh và điều chỉnh mã kết thúc
vòng lặp và lặp lại.

5. Xác định rằng các tải và lưu trữ trong vòng lặp không được cuộn có thể được hoán đổi cho
nhau bằng cách quan sát rằng các tải và lưu trữ từ các vòng lặp khác nhau là độc lập. Sự
chuyển đổi này yêu cầu phân tích các địa chỉ bộ nhớ và nhận thấy rằng chúng không
tham chiếu đến cùng một địa chỉ.
4.1 Các kỹ thuật biên dịch cơ bản để hiển thị ILP 227

6. Lập lịch cho mã, bảo toàn bất kỳ phụ thuộc nào cần thiết để mang lại kết
quả giống như mã gốc.

Yêu cầu quan trọng cơ bản của tất cả các phép biến đổi này là sự hiểu biết về cách một lệnh
phụ thuộc vào một lệnh khác và cách các lệnh đó có thể được thay đổi hoặc sắp xếp lại với
các phụ thuộc. Trước khi kiểm tra cách các kỹ thuật này hoạt động đối với các đường ống có
tỷ lệ sự cố cao hơn, chúng ta hãy kiểm tra kỹ thuật lập lịch và hủy cuộn vòng lặp ảnh hưởng
như thế nào đến sự phụ thuộc dữ liệu.

THÍ DỤ Cho thấy quá trình tối ưu hóa chi phí vòng lặp bằng cách mở vòng lặp thực sự loại bỏ
sự phụ thuộc dữ liệu như thế nào. Trong ví dụ này và những ví dụ được sử dụng
trong phần còn lại của chương này, chúng tôi sử dụng các nhánh nondelayed để đơn
giản hóa; có thể dễ dàng mở rộng các ví dụ để sử dụng các nhánh bị trễ.

CÂU TRẢ LỜI Đây là mã chưa được cuộn nhưng chưa được tối ưu hóa với phần bổ sungDADDUI
hướng dẫn, nhưng không có các chi nhánh. (Loại bỏ các nhánh là một kiểu chuyển đổi
khác, vì nó liên quan đến kiểm soát chứ không phải dữ liệu.) Các mũi tên hiển thị các
phụ thuộc dữ liệu nằm trong phần thân chưa được cuộn và liên quan đếnDADDUI
hướng dẫn. Các thanh ghi được gạch chân là các mục đích sử dụng phụ thuộc.

Vòng: LD F0,0 (R1)


ADD.D F4, F0, F2
SD F4,0 (R1)
DADDUI R1, R1, # - 8 ; thả BNE
LD F6,0 (R1 )
ADD.D F8, F6, F2
SD F8,0 (R1 )
DADDUI R1,R1 ,#-số 8 ; thả BNE
LD F10,0 (R1 )
ADD.D F12, F10, F2
SD F12,0 (R1 )
DADDUI R1,R1 ,#-số 8 ; thả BNE
LD F14,0 (R1 )
ADD.D F16, F14, F2
SD F16,0 (R1 )
DADDUI R1,R1 ,#-số 8
BNE R1, R2, LOOP

Khi các mũi tên hiển thị,DADDUIcác hướng dẫn tạo thành một chuỗi phụ
thuộc liên quan đếnDADDUI, LD,vàSDChuỗi này buộc phần thân phải thực
hiện theo thứ tự, cũng như làm choDADDUIhướng dẫn cần thiết, làm tăng
số lượng lệnh. Trình biên dịch loại bỏ sự phụ thuộc này bằng cách tính toán
một cách tượng trưng các giá trị trung gian củaR1và gấp lại-
228 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

nhập tính toán vào phần bù củaLDvàSDhướng dẫn và bằng cách thay
đổi cuối cùngDADDUIgiảm xuống 32. Sự biến đổi này làm cho ba
DADDUIkhông cần thiết và trình biên dịch có thể loại bỏ chúng. Có các
loại phụ thuộc khác trong mã này, như một vài ví dụ tiếp theo cho thấy.
N

THÍ DỤ Bỏ cuộn vòng lặp ví dụ của chúng tôi, loại bỏ chi phí vòng lặp dư thừa, nhưng sử
dụng cùng các thanh ghi trong mỗi bản sao vòng lặp. Cho biết cả dữ liệu và tên
phụ thuộc trong phần thân. Chỉ ra cách đổi tên loại bỏ sự phụ thuộc tên làm giảm
tính song song.

CÂU TRẢ LỜI Đây là vòng lặp chưa được cuộn nhưng có cùng các thanh ghi được sử dụng cho
mỗi bản sao. Các phần phụ thuộc dữ liệu được hiển thị bằng các mũi tên màu xám
và các phần phụ thuộc tên bằng các mũi tên màu đen. Như trong các ví dụ trước
đó, hướng của mũi tên chỉ ra thứ tự phải được duy trì để thực thi đúng mã:

Vòng: LD F0,0 (R1)


ADD.D F4, F0, F2
SD F4,0 (R1) ; bỏ DADDUI & BNE
LD F0, -8 (R1)
ADD.D F4, F0, F2
SD F4, -8 (R1) ; bỏ DADDUI & BNE
LD F0, -16 (R1)
ADD.D F4, F0, F2
SD F4, -16 (R1)
LD F0, -24 (R1)
ADD.D F4, F0, F2
SD F4, -24 (R1)
DADDUI R1, R1, # - 32
BNE R1, R2, LOOP

Tên phụ thuộc buộc các lệnh trong vòng lặp phải được sắp xếp gần như
hoàn toàn, chỉ cho phép thứ tự củaLDtheo dõi mỗiSD được hoán đổi cho
nhau. Khi các thanh ghi được sử dụng cho mỗi bản sao của vòng lặp
4.1 Các kỹ thuật biên dịch cơ bản để hiển thị ILP 229

phần thân được đổi tên chỉ những phần phụ thuộc thực sự bên trong mỗi phần thân vẫn còn:

Vòng: LD F0,0 (R1)


ADD.D F4, F0, F2
SD F4,0 (R1) ; bỏ DADDUI & BNE
LD F6, -8 (R1)
ADD.D F8, F6, F2
SD F8, -8 (R1) ; bỏ DADDUI & BNE
LD F10, -16 (R1)
ADD.D F12, F10, F2
SD F12, -16 (R1)
LD F14, -24 (R1)
ADD.D F16, F14, F2
SD F16, -24 (R1)
DADDUI R1, R1, # - 32
BNE R1, R2, LOOP

Với việc đổi tên, các bản sao của mỗi phần thân vòng lặp trở nên độc lập và có thể được
chồng chéo hoặc thực thi song song. Quá trình đổi tên này có thể được thực hiện bởi
trình biên dịch hoặc trong phần cứng, như chúng ta đã thấy trong chương trước.
N

Có ba loại giới hạn khác nhau đối với lợi nhuận có thể đạt được bằng cách hủy
cuộn vòng lặp: giảm số lượng chi phí khấu hao với mỗi lần hủy cuộn, giới hạn kích
thước mã và giới hạn trình biên dịch. Trước tiên, hãy xem xét câu hỏi về chi phí
vòng lặp. Khi chúng tôi mở vòng lặp bốn lần, nó tạo ra đủ độ song song giữa các
lệnh để vòng lặp có thể được lập lịch mà không có chu kỳ ngừng trệ. Trên thực tế,
trong mười bốn chu kỳ đồng hồ, chỉ có hai chu kỳ là chi phí vòng lặp: DSUBI, duy
trì giá trị chỉ mục và BNE, kết thúc vòng lặp. Nếu vòng lặp được bỏ cuộn tám lần,
chi phí sẽ giảm từ 1/2 chu kỳ cho mỗi lần lặp ban đầu xuống còn 1/4. Một trong
những bài tập yêu cầu bạn tính số lần tối ưu về mặt lý thuyết để bỏ cuộn vòng lặp
này cho một số lần lặp ngẫu nhiên.
Giới hạn thứ hai đối với việc hủy cuộn là sự phát triển về kích thước mã. Đối với các vòng
lặp lớn hơn, sự gia tăng kích thước mã có thể là mối quan tâm trong không gian nhúng nơi
bộ nhớ có thể ở mức cao hơn hoặc nếu kích thước mã lớn hơn làm giảm tỷ lệ bỏ lỡ bộ nhớ
cache lệnh. Chúng ta quay trở lại vấn đề kích thước mã khi chúng ta xem xét các kỹ thuật
tích cực hơn để khám phá sự song song mức lệnh trong Phần 4.4.

Một yếu tố khác thường quan trọng hơn kích thước mã là sự thiếu hụt tiềm năng
trong các thanh ghi được tạo ra bằng cách lập lịch và hủy cuộn tích cực. Ảnh hưởng
thứ cấp này mà kết quả từ việc lập lịch hướng dẫn trong các đoạn mã lớn được gọi là
đăng ký áp lực. Nó phát sinh do mã lập lịch để tăng ILP khiến số lượng giá trị trực tiếp
tăng lên. Sau khi lập lịch hướng dẫn tích cực, nó không có khả năng-
230 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

ble để phân bổ tất cả các giá trị trực tiếp cho các thanh ghi. Mã được chuyển đổi, mặc
dù nhanh hơn về mặt lý thuyết, nhưng có thể mất một số hoặc tất cả lợi thế của nó,
bởi vì nó tạo ra sự thiếu hụt các thanh ghi. Không cần hủy cuộn, lập lịch tích cực được
giới hạn đủ bởi các nhánh để áp suất thanh ghi hiếm khi là một vấn đề. Tuy nhiên, sự
kết hợp của việc hủy cuộn và lập lịch tích cực có thể gây ra vấn đề này. Vấn đề trở nên
đặc biệt khó khăn trong nhiều máy phát hành yêu cầu hiển thị các chuỗi lệnh độc lập
hơn mà việc thực thi có thể bị chồng chéo. Nhìn chung, việc sử dụng các phép biến đổi
cấp cao phức tạp, mà những cải tiến tiềm năng khó có thể đo lường trước khi tạo mã
chi tiết, đã dẫn đến sự gia tăng đáng kể về độ phức tạp của các trình biên dịch hiện
đại.
Bỏ cuộn vòng lặp là một phương pháp đơn giản nhưng hữu ích để tăng kích thước của các
đoạn mã đường thẳng có thể được lên lịch một cách hiệu quả. Sự chuyển đổi này hữu ích trong
nhiều bộ vi xử lý, từ các đường ống đơn giản như trong MIPS đến các siêu thanh được lập lịch tĩnh
mà chúng ta đã mô tả trong chương trước, như chúng ta sẽ thấy bây giờ.

Sử dụng tính năng mở vòng lặp và lập lịch đường ống với nhiều vấn đề tĩnh

Chúng ta bắt đầu bằng cách xem xét một đường ống MIPS siêu hạng hai vấn đề, được
lập lịch tĩnh từ chương trước, sử dụng độ trễ của đường ống từ Hình 4.1 trên trang
222 và cùng một đoạn mã ví dụ mà chúng tôi đã sử dụng cho các ví dụ vấn đề đơn lẻ ở
trên. Bộ xử lý này có thể đưa ra hai lệnh cho mỗi chu kỳ đồng hồ, trong đó một trong
các lệnh có thể là hoạt động ALU tải, lưu trữ, nhánh hoặc số nguyên và lệnh kia có thể
là bất kỳ hoạt động dấu phẩy động nào.
Nhớ lại rằng đường ống này không tạo ra một sự nâng cao hiệu suất đáng kể cho
ví dụ trên, vì ILP bị giới hạn trong một lần lặp vòng lặp nhất định. Hãy xem cách lập
lịch đường ống và hủy cuộn vòng lặp có thể giúp ích như thế nào.

THÍ DỤ Bỏ cuộn và lên lịch cho vòng lặp được sử dụng trong các ví dụ trước đó và được hiển thị trên
trang 223.

CÂU TRẢ LỜI Để lên lịch cho vòng lặp này mà không có bất kỳ sự chậm trễ nào, chúng ta sẽ cần
phải mở vòng lặp để tạo năm bản sao của phần thân. Sau khi giải nén, vòng lặp
sẽ chứa nămLD, ADD.D,vàSD;mộtDADDUI;và mộtBNE.Mã chưa được cuộn và lập
lịch được hiển thị trong Hình 4.2.
Vòng lặp siêu địa phương không được cuộn này hiện chạy trong 12 chu kỳ đồng hồ mỗi
lần lặp, hoặc 2,4 chu kỳ đồng hồ cho mỗi phần tử, so với 3,5 cho vòng lặp được lập lịch
và không được cuộn trên đường ống MIPS thông thường. Trong ví dụ này, hiệu suất của
MIPS siêu phương bị giới hạn bởi sự cân bằng giữa tính toán số nguyên và dấu phẩy
động. Mọi lệnh dấu phẩy động được phát hành cùng với lệnh số nguyên, nhưng không
có đủ lệnh dấu phẩy động để giữ cho đường ống dấu phẩy động luôn đầy đủ. Khi được
lên lịch, vòng lặp ban đầu chạy trong 6 chu kỳ xung nhịp cho mỗi lần lặp. Chúng tôi đã
cải thiện điều đó bằng hệ số 2,5, hơn một nửa trong số đó đến từ việc bỏ cuộn vòng lặp.
Việc giải nén vòng lặp đã đưa chúng tôi từ 6 đến 3,5 (hệ số 1,7), trong khi thực thi siêu
thanh cho chúng tôi
4.2 Dự đoán nhánh tĩnh 231

Hướng dẫn số nguyên Hướng dẫn FP Chu kỳ đồng hồ

Vòng: LD F0,0 (R1) 1


LD F6, -8 (R1) 2
LD F10, -16 (R1) ADD.D F4, F0, F2 3
LD F14, -24 (R1) ADD.D F8, F6, F2 4
LD F18, -32 (R1) ADD.D F12, F10, F2 5
SD F4,0 (R1) ADD.D F16, F14, F2 6
SD F8, -8 (R1) ADD.D F20, F18, F2 7
SD F12, -16 (R1) số 8
DADDUI R1, R1, # - 40 9
SD F16,16 (R1) 10
BNE R1, R2, Vòng lặp 11
SD F20,8 (R1) 12
HÌNH 4.2 Mã chưa được cuộn và được lập lịch giống như mã sẽ trông trên MIPS siêu phương.

hệ số cải thiện 1,5. N

4.2Dự đoán nhánh tĩnh


Trong Chương 3, chúng tôi đã xem xét việc sử dụng các bộ dự báo nhánh động. Các bộ dự
đoán nhánh tĩnh đôi khi được sử dụng trong các bộ xử lý mà kỳ vọng là hành vi nhánh có
thể dự đoán cao tại thời điểm biên dịch; dự đoán tĩnh cũng có thể được sử dụng để hỗ trợ
các công cụ dự đoán động.
Trong Chương 1, chúng ta đã thảo luận về một tính năng kiến trúc hỗ trợ dự đoán
nhánh tĩnh, cụ thể là các nhánh bị trễ. Các nhánh bị trì hoãn gây ra mối nguy hiểm cho
đường ống để trình biên dịch có thể giảm hình phạt liên quan đến mối nguy đó. Như chúng
ta đã thấy, hiệu quả của kỹ thuật này một phần phụ thuộc vào việc chúng ta có đoán đúng
cách một nhánh sẽ đi hay không. Việc có thể dự đoán chính xác một nhánh tại thời điểm
biên dịch cũng rất hữu ích cho việc lập lịch các nguy cơ dữ liệu. Bỏ cuộn vòng lặp là một ví
dụ đơn giản về điều này; một ví dụ khác, phát sinh từ các nhánh lựa chọn có điều kiện. Hãy
xem xét đoạn mã sau:

LD R1,0 (R2)
DSUBU R1, R1, R3
BEQZ R1, L
HOẶC R4, R5, R6
DADDU R10, R4, R3
232 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

L: DADDU R7, R8, R9

Sự phụ thuộc củaDSUBUvàBEQZtrênLDhướng dẫn có nghĩa là một gian hàng sẽ cần


thiết sau khiLD.Giả sử chúng ta biết rằng nhánh này hầu như luôn được sử dụng và giá
trị củaR7không cần thiết trên con đường rơi. Sau đó, chúng tôi có thể tăng tốc độ của
chương trình bằng cách di chuyển lệnhDADD R7, R8, R9đến vị trí sauLD.Tương ứng, nếu
chúng ta biết rằng nhánh hiếm khi được sử dụng và giá trị củaR4không cần thiết trên
con đường đã định, sau đó chúng ta có thể xem xét việc di chuyểnHOẶChướng dẫn sau
LD.Ngoài ra, chúng ta cũng có thể sử dụng thông tin để lên lịch tốt hơn cho bất kỳ độ
trễ chi nhánh nào, vì việc chọn cách lập lịch trễ phụ thuộc vào việc biết hành vi của chi
nhánh. Chúng ta sẽ trở lại chủ đề này trong phần 4.4, khi chúng ta thảo luận về lập lịch
mã toàn cầu.
Để thực hiện các tối ưu hóa này, chúng ta cần dự đoán nhánh tĩnh khi chúng
ta biên dịch chương trình. Có một số phương pháp khác nhau để dự đoán tĩnh
hành vi của nhánh. Sơ đồ đơn giản nhất là dự đoán một nhánh như được thực
hiện. Sơ đồ này có tỷ lệ sai lầm trung bình bằng với tần suất nhánh chưa được
thực hiện, đối với các chương trình SPEC là 34%. Thật không may, tỷ lệ đoán sai
dao động từ không chính xác lắm (59%) đến chính xác cao (9%).
Một giải pháp thay thế tốt hơn là dự đoán trên cơ sở hướng đi của nhánh, chọn các
nhánh đi lùi sẽ được lấy và các nhánh đi về phía trước sẽ không được thực hiện. Đối với một
số chương trình và hệ thống biên dịch, tần suất các nhánh được thực hiện chuyển tiếp có
thể ít hơn đáng kể 50% và sơ đồ này sẽ hoạt động tốt hơn là chỉ dự đoán tất cả các nhánh
được thực hiện. Tuy nhiên, trong các chương trình SPEC, hơn một nửa số nhánh tương lai
được thực hiện. Do đó, dự đoán tất cả các nhánh như đã thực hiện là cách tiếp cận tốt hơn.
Ngay cả đối với các điểm chuẩn hoặc trình biên dịch khác, dự đoán dựa trên định hướng
không có khả năng tạo ra tỷ lệ sai lầm tổng thể dưới 30% đến 40%. Một cải tiến của kỹ thuật
này đã được khám phá bởi Ball và Larus; cách tiếp cận của họ sử dụng thông tin ngữ cảnh
chương trình và tạo ra các dự đoán chính xác hơn so với một lược đồ đơn giản chỉ dựa trên
hướng rẽ nhánh.
Một kỹ thuật vẫn chính xác hơn là dự đoán các nhánh trên cơ sở thông tin hồ sơ được
thu thập từ các lần chạy trước đó. Quan sát chính làm cho điều này đáng giá là hành vi của
các nhánh thường được phân phối theo phương thức sinh học; nghĩa là, một nhánh riêng lẻ
thường rất thiên vị về việc lấy hoặc không lấy. Hình 4.3 cho thấy sự thành công của dự đoán
chi nhánh bằng cách sử dụng chiến lược này. Dữ liệu đầu vào giống nhau được sử dụng để
chạy và thu thập hồ sơ; các nghiên cứu khác đã chỉ ra rằng
4.2 Dự đoán nhánh tĩnh 233

việc thay đổi đầu vào để cấu hình dành cho một lần chạy khác chỉ dẫn đến một thay đổi nhỏ
về độ chính xác của dự đoán dựa trên cấu hình.

25%
22%

20% 18%

15%
15%
12% 12%
Tỷ lệ sai lệch 11%
9% 10%
10%

5% 6%
5%

0%

do i
c
t

p
l
c

r
i
ot

gc
so

ta
du

co
jd
o2
es
nt

dl
pr

2
dr
es
eq

su
m
n

hy
ph


Điểm chuẩn

HÌNH 4.3 Tỷ lệ sai lệch trên SPEC92 đối với một công cụ dự đoán dựa trên hồ sơ rất
khác nhau nhưng nhìn chung là tốt hơn cho các chương trình FP, có tỷ lệ sai lệch trung
bình là 9% với độ lệch chuẩn là 4%, so với các chương trình số nguyên, có mức trung
bình tỷ lệ sai lệch 15% với độ lệch chuẩn là 5%.Hiệu suất thực tế phụ thuộc vào cả độ
chính xác của dự đoán và tần số nhánh, thay đổi từ 3% đến 24%; chúng ta sẽ xem xét hiệu
ứng kết hợp trong Hình 4.4.

Mặc dù chúng ta có thể lấy được độ chính xác dự đoán của một chiến lược dự đoán
và đo lường độ chính xác của lược đồ hồ sơ, như trong Hình 4.3, phạm vi tần suất rộng
của các nhánh có điều kiện trong các chương trình này, từ 3% đến 24%, có nghĩa là
tổng thể tần suất của một nhánh bị nhầm lẫn rất khác nhau. Hình 4.4 cho thấy số
lượng các lệnh được thực hiện giữa các nhánh được dự đoán sai cho cả chiến lược dựa
trên hồ sơ và chiến lược dự đoán. Con số rất khác nhau, cả vì sự thay đổi về độ chính
xác và sự thay đổi của tần số nhánh. Trung bình, chiến lược thực hiện dự đoán có 20
lệnh cho mỗi nhánh được dự đoán sai và chiến lược dựa trên hồ sơ có 110. Tuy nhiên,
các giá trị trung bình này rất khác nhau đối với các chương trình số nguyên và FP, như
dữ liệu trong Hình 4.4 cho thấy.
Hành vi nhánh tĩnh rất hữu ích cho việc lập lịch hướng dẫn khi độ trễ nhánh bị
lộ ra bởi kiến trúc (hoặc nhánh bị trì hoãn hoặc hủy), để hỗ trợ các bộ dự đoán
động (như chúng ta sẽ thấy trong kiến trúc IA-64 trong phần 4.7) và để xác định
mã nào đường dẫn thường xuyên hơn, đây là một bước quan trọng trong lập lịch
mã (xem phần 4.4, trang 251).
234 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

1000

250 113 253


159 92 96
100
56 60 58
Hướng dẫn giữa
37
sự sai lầm 19 19
10 11 11 14 11 11 14
10 6

li
c
tt

p
d
c

or
i
so

gc

ta

jd
du
to

o2
es

2c
dl
pr
n

do

dr
es
eq

su
m
n

hy
ph


Điểm chuẩn

Dự đoán được thực hiện Hồ sơ dựa trên

HÌNH 4.4 Độ chính xác của chiến lược dự đoán được thực hiện và công cụ dự đoán dựa trên hồ sơ cho các điểm chuẩn
SPEC92 được đo bằng số lượng các lệnh được thực hiện giữa các nhánh được đánh giá sai và được hiển thị trên thang điểm.
Số hướng dẫn trung bình giữa các lần bị nhầm lẫn là 20 đối với chiến lược được thực hiện dự đoán và 110 đối với dự đoán dựa trên
hồ sơ; tuy nhiên, độ lệch chuẩn rất lớn: 27 hướng dẫn cho chiến lược dự đoán và 85 hướng dẫn cho lược đồ dựa trên hồ sơ. Sự khác
biệt rộng rãi này phát sinh do các chương trình như su2cor có cả tần số nhánh có điều kiện thấp (3%) và các nhánh có thể dự đoán
được (độ chính xác 85% cho việc lập hồ sơ), mặc dù eqntott có tần suất nhánh gấp tám lần với các nhánh gần 1,5 lầnít hơncó thể
đoán trước được. Sự khác biệt giữa điểm chuẩn FP và số nguyên khi các nhóm là rất lớn. Đối với chiến lược được thực hiện dự đoán,
khoảng cách trung bình giữa các lần dự đoán sai đối với các điểm chuẩn số nguyên là 10 hướng dẫn và đó là 30 hướng dẫn cho các
chương trình FP. Với lược đồ hồ sơ, khoảng cách giữa các sai lệch đối với điểm chuẩn số nguyên là 46 hướng dẫn và đó là 173
hướng dẫn đối với điểm chuẩn FP.

4.3Nhiều vấn đề tĩnh: Phương pháp tiếp cận VLIW


Bộ xử lý siêu cấp quyết định nhanh chóng có bao nhiêu hướng dẫn để phát hành. Một
superscalar được lập lịch tĩnh phải kiểm tra bất kỳ sự phụ thuộc nào giữa các lệnh
trong gói vấn đề cũng như giữa bất kỳ ứng cử viên vấn đề nào và bất kỳ lệnh nào đã có
trong đường dẫn. Như chúng ta đã thấy trong Phần 4.1, một superscalar được lên lịch
tĩnh yêu cầu sự hỗ trợ đáng kể của trình biên dịch để đạt được hiệu suất tốt. Ngược lại,
một superscalar được lập lịch động yêu cầu ít sự hỗ trợ của trình biên dịch hơn, nhưng
có chi phí phần cứng đáng kể.
Một giải pháp thay thế cho cách tiếp cận siêu phương pháp là dựa vào công nghệ trình
biên dịch không chỉ để giảm thiểu các nguy cơ tiềm ẩn về dữ liệu mà còn thực sự định dạng
các hướng dẫn trong một gói sự cố tiềm ẩn để phần cứng không cần kiểm tra rõ ràng các
phụ thuộc. Trình biên dịch có thể được yêu cầu để đảm bảo rằng các phụ thuộc trong gói
vấn đề không thể có mặt hoặc ít nhất là chỉ ra khi nào có thể có sự phụ thuộc. Cách tiếp cận
như vậy mang lại lợi thế tiềm năng của phần cứng đơn giản hơn trong khi vẫn thể hiện hiệu
suất tốt thông qua tối ưu hóa trình biên dịch rộng rãi.
4.3 Nhiều vấn đề tĩnh: Phương pháp tiếp cận VLIW 235

Các bộ xử lý nhiều vấn đề đầu tiên yêu cầu dòng lệnh phải được tổ
chức rõ ràng để tránh sự phụ thuộc đã sử dụng các lệnh rộng với nhiều
thao tác trên mỗi lệnh. Vì lý do này, cách tiếp cận kiến trúc này được đặt
tên là VLIW, viết tắt của Very Long Instruction Word, và biểu thị rằng các
lệnh, vì chúng chứa một số lệnh, rất rộng (64 đến 128 bit hoặc hơn). Các
khái niệm kiến trúc cơ bản và công nghệ trình biên dịch đều giống nhau
cho dù nhiều hoạt động được tổ chức thành một lệnh duy nhất hay một
tập hợp các lệnh trong gói vấn đề được cấu hình sẵn bởi trình biên dịch
để loại trừ các hoạt động phụ thuộc (vì gói vấn đề có thể được coi là một
hướng dẫn rất lớn).

Để giảm bớt tính linh hoạt này và nâng cao hiệu suất của cách tiếp cận, một số đổi
mới đã được kết hợp vào các kiến trúc gần đây hơn thuộc loại này, trong khi vẫn yêu
cầu trình biên dịch thực hiện hầu hết công việc tìm kiếm và lập lịch hướng dẫn để thực
hiện song song. Thế hệ kiến trúc VLIW thứ hai này là cách tiếp cận đang được theo
đuổi cho thị trường máy tính để bàn và máy chủ.
Trong phần còn lại của phần này, chúng ta sẽ xem xét các khái niệm cơ bản trong kiến
trúc VLIW. Phần 4.4 giới thiệu các kỹ thuật trình biên dịch bổ sung cần thiết để đạt được hiệu
suất tốt cho các phương pháp tiếp cận chuyên sâu về trình biên dịch và Phần 4.5 mô tả các
cải tiến phần cứng nhằm cải thiện tính linh hoạt và hiệu suất của các phương pháp tiếp cận
song song rõ ràng. Cuối cùng, Phần 4.7 mô tả cách Intel IA-64 hỗ trợ song song rõ ràng.

Phương pháp tiếp cận VLIW cơ bản

VLIW sử dụng nhiều đơn vị chức năng độc lập. Thay vì cố gắng đưa ra nhiều lệnh
độc lập cho các đơn vị, một VLIW gói nhiều thao tác thành một lệnh rất dài hoặc
yêu cầu các lệnh trong gói vấn đề phải thỏa mãn các ràng buộc giống nhau. Vì
không có sự khác biệt cơ bản trong hai cách tiếp cận, chúng tôi sẽ chỉ giả sử rằng
nhiều hoạt động được đặt trong một lệnh, như trong cách tiếp cận VLIW ban đầu.
Vì gánh nặng cho việc lựa chọn các hướng dẫn được đưa ra đồng thời thuộc về
trình biên dịch, phần cứng trong một siêu phương trình để đưa ra các quyết định
về vấn đề này là không cần thiết.
Vì lợi thế này của VLIW tăng lên khi tỷ lệ vấn đề tối đa tăng lên, chúng tôi tập trung vào
bộ xử lý vấn đề rộng hơn. Thật vậy, đối với hai bộ xử lý vấn đề đơn giản, chi phí của một
superscalar có lẽ là tối thiểu. Nhiều nhà thiết kế có thể tranh luận rằng một bộ xử lý bốn vấn
đề có chi phí quản lý được, nhưng như chúng ta đã thấy trong chương trước, chi phí này
tăng lên theo chiều rộng vấn đề.
Bởi vì các phương pháp tiếp cận VLIW có ý nghĩa đối với các bộ xử lý rộng hơn,
chúng tôi chọn tập trung ví dụ của mình vào một kiến trúc như vậy. Ví dụ: một
bộ xử lý VLIW có thể có các lệnh chứa năm hoạt động, bao gồm: một hoạt động
số nguyên (cũng có thể là một nhánh), hai hoạt động dấu phẩy động và hai tham
chiếu bộ nhớ. Lệnh sẽ có một tập hợp các trường cho mỗi đơn vị chức năng có
thể từ 16 đến 24 bit trên mỗi đơn vị, tạo ra độ dài lệnh từ 112 đến 168 bit.
236 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Để giữ cho các đơn vị chức năng bận rộn, phải có đủ song song trong một chuỗi
mã để lấp đầy các vị trí hoạt động có sẵn. Sự song song này được phát hiện bằng cách
mở vòng lặp và lập lịch mã trong phần thân vòng lặp lớn hơn duy nhất. Nếu việc mở
cuộn tạo ra mã dòng thẳng, thìlập lịch cục bộcác kỹ thuật hoạt động trên một khối cơ
bản duy nhất có thể được sử dụng. Nếu việc tìm kiếm và khai thác tính song song yêu
cầu mã lập lịch qua các nhánh, thì về cơ bản phức tạp hơn nhiềulập lịch toàn cầuthuật
toán phải được sử dụng. Các thuật toán lập lịch toàn cầu không chỉ phức tạp hơn về
cấu trúc mà còn phải đối phó với sự cân bằng phức tạp hơn đáng kể trong việc tối ưu
hóa, vì việc di chuyển mã giữa các chi nhánh rất tốn kém. Trong phần tiếp theo, chúng
ta sẽ thảo luận vềlập lịch theo dõi, một trong những kỹ thuật lập lịch toàn cầu này
được phát triển đặc biệt cho VLIW. Trong Phần 4.5, chúng ta sẽ xem xét hỗ trợ phần
cứng cho phép loại bỏ một số nhánh có điều kiện, mở rộng tính hữu ích của lập lịch
cục bộ và nâng cao hiệu suất của lập lịch toàn cục.

Bây giờ, hãy giả sử chúng ta có một kỹ thuật để tạo ra các chuỗi mã dài, thẳng hàng, để chúng
ta có thể sử dụng lập lịch cục bộ để xây dựng các hướng dẫn VLIW và thay vào đó tập trung vào
cách các bộ xử lý này hoạt động tốt như thế nào.

THÍ DỤ Giả sử chúng ta có một VLIW có thể tạo ra hai tham chiếu bộ nhớ, hai hoạt động
FP và một hoạt động số nguyên hoặc nhánh trong mỗi chu kỳ đồng hồ. Hiển thị
phiên bản chưa được cuộn của vòng lặp x [i] = x [i] + s (xem trang 223 để biết câu
hỏi MIPS) cho một bộ xử lý như vậy. Mở nhiều lần nếu cần để loại bỏ bất kỳ gian
hàng nào. Bỏ qua khe trễ rẽ nhánh.

CÂU TRẢ LỜI Mã được hiển thị trong Hình 4.5. Vòng lặp đã được hủy cuộn để tạo ra bảy bản sao
của phần thân, giúp loại bỏ tất cả các lỗi (tức là các chu kỳ phát hành hoàn toàn
trống) và chạy trong 9 chu kỳ. Mã này mang lại tốc độ chạy 7 kết quả trong 9 chu
kỳ hoặc 1,29 chu kỳ cho mỗi kết quả, nhanh hơn gần gấp đôi so với siêu phương
trình hai vấn đề của Phần 4.1 đã sử dụng mã chưa được cuộn và lập lịch.
N

Đối với mô hình VLIW ban đầu, có cả vấn đề kỹ thuật và hậu cần. Các vấn đề kỹ
thuật là sự gia tăng kích thước mã và những hạn chế của hoạt động ở bước khóa. Hai
yếu tố khác nhau kết hợp để tăng đáng kể kích thước mã cho một VLIW. Đầu tiên, việc
tạo đủ các hoạt động trong một đoạn mã đường thẳng yêu cầu các vòng lặp mở cuộn
một cách có chủ ý (như các ví dụ trước đó), do đó làm tăng kích thước mã. Thứ hai, bất
cứ khi nào các lệnh không đầy đủ, các đơn vị chức năng không sử dụng sẽ dịch thành
các bit lãng phí trong mã hóa lệnh. Trong Hình 4.5, chúng ta thấy rằng chỉ có khoảng
60% các đơn vị chức năng được sử dụng, vì vậy gần một nửa số lệnh của mỗi lệnh là
trống. Trong hầu hết các VLIW, một lệnh có thể cần để trống hoàn toàn nếu không có
hoạt động nào có thể được lên lịch.
Để chống lại sự gia tăng kích thước mã này, đôi khi sử dụng các bảng mã thông
minh. Ví dụ, có thể chỉ có một trường lớn ngay lập tức để cho bất kỳ đơn vị chức năng
nào sử dụng. Một kỹ thuật khác là nén các lệnh trong bộ nhớ chính và
4.3 Nhiều vấn đề tĩnh: Phương pháp tiếp cận VLIW 237

Kỉ niệm Kỉ niệm FP FP Số nguyên


tài liệu tham khảo 1 tài liệu tham khảo 2 hoạt động 1 hoạt động 2 hoạt động / chi nhánh

LD F0,0 (R1) LD F6, -8 (R1)


LD F10, -16 (R1) LD F14, -24 (R1)
LD F18, -32 (R1) LD F22, -40 (R1) ADD.D F4, F0, F2 ADD.D F8, F6, F2
LD F26, -48 (R1) ADD.D F12, F10, F2 ADD.D F16, F14, F2
ADD.D F20, F18, F2 ADD.D F24, F22, F2
SD F4,0 (R1) SD -8 (R1), F8 ADD.D F28, F26, F2
SD F12, -16 (R1) SD -24 (R1), F16
SD F20, -32 (R1) SD -40 (R1), F24 DADDUI R1, R1, # - 56
SD F28,8 (R1) BNE R1, R2, Vòng lặp

HÌNH 4.5 Các lệnh VLIW chiếm vòng lặp bên trong và thay thế trình tự chưa được cuộn.Mã này mất chín chu kỳ giả sử
không có độ trễ nhánh; thông thường, sự chậm trễ chi nhánh cũng sẽ cần phải được lên lịch. Tỷ lệ vấn đề là 23 hoạt động
trong chín chu kỳ đồng hồ, hoặc 2,5 hoạt động mỗi chu kỳ. Hiệu suất, tỷ lệ phần trăm các vị trí khả dụng chứa một hoạt
động, là khoảng 60%. Để đạt được tỷ lệ vấn đề này, yêu cầu số lượng thanh ghi lớn hơn MIPS thường sử dụng trong vòng
lặp này. Chuỗi mã VLIW ở trên yêu cầu ít nhất tám thanh ghi FP, trong khi cùng một chuỗi mã cho bộ xử lý MIPS cơ sở có
thể sử dụng ít nhất hai thanh ghi FP hoặc nhiều nhất là năm thanh ghi khi được mở và lập lịch. Trong ví dụ superscalar ở
Hình 4.2, cần có sáu thanh ghi.

pand chúng khi chúng được đọc vào bộ nhớ cache hoặc được giải mã. Chúng ta sẽ thấy các
kỹ thuật để giảm sự gia tăng kích thước mã trong cả Phần 4.7 và 4.8.
Các VLIW ban đầu hoạt động ở bước khóa; không có phần cứng phát hiện nguy cơ nào
cả. Cấu trúc này quy định rằng một sự ngừng trệ trong bất kỳ đường ống đơn vị chức năng
nào phải khiến toàn bộ bộ xử lý ngừng hoạt động, vì tất cả các đơn vị chức năng phải được
duy trì đồng bộ. Mặc dù trình biên dịch có thể lên lịch cho các đơn vị chức năng xác định để
ngăn chặn sự cố, nhưng việc dự đoán những truy cập dữ liệu nào sẽ gặp phải sự cố ngừng
bộ nhớ cache và lập lịch cho chúng là rất khó. Do đó, bộ nhớ đệm cần thiết để chặn và gây ra
tất cả cáccác đơn vị chức năng đình trệ. Khi tốc độ phát hành và số lượng tham chiếu bộ nhớ
trở nên lớn, hạn chế đồng bộ hóa này trở nên không thể chấp nhận được. Trong các bộ xử lý
gần đây hơn, các đơn vị chức năng hoạt động độc lập hơn và trình biên dịch được sử dụng
để tránh các mối nguy hiểm tại thời điểm phát hành, trong khi kiểm tra phần cứng cho phép
thực thi không đồng bộ sau khi có lệnh.
Khả năng tương thích mã nhị phân cũng là một vấn đề hậu cần lớn đối với VLI-
Ws. Trong cách tiếp cận VLIW nghiêm ngặt, chuỗi mã sử dụng cả định nghĩa tập
lệnh và cấu trúc đường ống chi tiết, bao gồm cả các đơn vị chức năng và độ trễ
của chúng. Do đó, số lượng đơn vị chức năng và độ trễ đơn vị khác nhau yêu cầu
các phiên bản mã khác nhau. Yêu cầu này làm cho việc di chuyển giữa các triển
khai kế tiếp hoặc giữa các triển khai có độ rộng vấn đề khác nhau, khó khăn hơn
so với thiết kế superscalar. Tất nhiên, để có được hiệu suất được cải thiện từ một
thiết kế superscalar mới có thể yêu cầu biên dịch lại. Tuy nhiên, khả năng chạy
các tệp nhị phân cũ là một lợi thế thiết thực cho phương pháp siêu phương pháp.

Một giải pháp khả thi cho vấn đề di chuyển này và vấn đề tương thích mã nhị phân nói
chung là dịch hoặc mô phỏng mã đối tượng. Công nghệ này đang phát triển nhanh chóng
và có thể đóng một vai trò quan trọng trong việc di chuyển trong tương lai
238 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

các kế hoạch. Một cách tiếp cận khác là làm dịu tính nghiêm ngặt của cách tiếp cận để khả năng
tương thích nhị phân vẫn khả thi. Cách tiếp cận sau này được sử dụng trong kiến trúc IA-64, như
chúng ta sẽ thấy trong Phần 4.7.
Thách thức lớn đối với tất cả các bộ xử lý đa vấn đề là cố gắng khai
thác lượng lớn ILP. Khi tính song song xuất phát từ việc mở các vòng lặp
đơn giản trong các chương trình FP, thì vòng lặp ban đầu có thể đã được
chạy hiệu quả trên bộ xử lý vectơ (được mô tả trong Phụ lục B). Không rõ
rằng bộ xử lý đa vấn đề được ưu tiên hơn bộ xử lý vectơ cho các ứng
dụng như vậy; chi phí tương tự nhau và bộ xử lý vectơ thường có cùng
tốc độ hoặc nhanh hơn. Lợi thế tiềm năng của bộ xử lý đa vấn đề so với
bộ xử lý vectơ là gấp đôi. Thứ nhất, bộ xử lý đa vấn đề có khả năng trích
xuất một số lượng song song từ mã có cấu trúc ít thường xuyên hơn và
thứ hai, nó có khả năng sử dụng hệ thống bộ nhớ dựa trên bộ nhớ cache
thông thường hơn và thường ít tốn kém hơn.

4.4Hỗ trợ trình biên dịch nâng cao để hiển thị


và khai thác ILP
Trong phần này, chúng ta thảo luận về công nghệ trình biên dịch để tăng số lượng song
song mà chúng ta có thể khai thác trong một chương trình. Chúng ta bắt đầu bằng cách xác
định khi nào một vòng lặp là song song và cách một sự phụ thuộc có thể ngăn một vòng lặp
song song. Chúng tôi cũng thảo luận về các kỹ thuật để loại bỏ một số loại phụ thuộc. Như
chúng ta sẽ thấy trong các phần sau, hỗ trợ phần cứng cho các kỹ thuật trình biên dịch này
có thể làm tăng hiệu quả của chúng lên rất nhiều. Phần này đóng vai trò là phần giới thiệu
về các kỹ thuật này. Chúng tôi không cố gắng giải thích chi tiết về các kỹ thuật trình biên
dịch hướng ILP, vì điều này sẽ mất hàng trăm trang, thay vì 20 trang mà chúng tôi đã phân
bổ. Thay vào đó, chúng tôi xem tài liệu này là cung cấp nền tảng chung giúp người đọc có
thể hiểu cơ bản về các kỹ thuật trình biên dịch được sử dụng để khai thác ILP trong các máy
tính hiện đại.

Phát hiện và tăng cường song song cấp vòng lặp

Song song mức vòng lặp thường được phân tích ở mức nguồn hoặc gần với nó, trong khi hầu hết
các phân tích ILP được thực hiện sau khi trình biên dịch tạo ra các lệnh. Phân tích mức vòng lặp
bao gồm việc xác định những phụ thuộc nào tồn tại giữa các toán hạng trong một vòng lặp qua
các lần lặp của vòng lặp đó. Hiện tại, chúng ta sẽ chỉ xem xét các phần phụ thuộc dữ liệu, phát sinh
khi toán hạng được viết tại một thời điểm nào đó và được đọc vào một thời điểm nào đó. Tên phụ
thuộc cũng tồn tại và có thể bị loại bỏ bằng các kỹ thuật đổi tên giống như những kỹ thuật chúng
tôi đã sử dụng trước đó.
Việc phân tích tính song song mức vòng lặp tập trung vào việc xác định xem các truy cập dữ
liệu trong các lần lặp sau có phụ thuộc vào các giá trị dữ liệu được tạo ra trong các lần lặp trước đó
hay không, sự phụ thuộc như vậy được gọi làsự phụ thuộc theo vòng lặp. Hầu hết các kỳ thi-
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 239

ples chúng tôi đã xem xét trong Phần 4.1 không có phụ thuộc mang vòng lặp và do đó, là song
song mức vòng lặp. Để thấy rằng một vòng lặp là song song, trước tiên chúng ta hãy xem biểu
diễn nguồn:

vì(i = 1000; i> 0; i = i – 1)


x [i] = x [i] + s;

Trong vòng lặp này, có sự phụ thuộc giữa hai cách sử dụngx [i],nhưng sự phụ thuộc
này nằm trong một lần lặp duy nhất và không mang tính lặp lại. Có sự phụ thuộc giữa
việc sử dụng liên tiếptôitrong các lần lặp khác nhau, được thực hiện theo vòng lặp,
nhưng sự phụ thuộc này liên quan đến một biến cảm ứng và có thể dễ dàng nhận ra
và loại bỏ. Chúng ta đã thấy các ví dụ về cách loại bỏ sự phụ thuộc liên quan đến các
biến cảm ứng trong khi mở vòng lặp trong Phần 4.1 và chúng ta sẽ xem xét các ví dụ
bổ sung sau trong phần này.
Bởi vì việc tìm kiếm song song mức vòng lặp liên quan đến việc nhận dạng các cấu
trúc như vòng lặp, tham chiếu mảng và tính toán biến cảm ứng, trình biên dịch có thể
thực hiện phân tích này dễ dàng hơn ở hoặc gần mức nguồn, trái ngược với mức mã
máy. Hãy xem một ví dụ phức tạp hơn.

THÍ DỤ Hãy xem xét một vòng lặp như sau:

vì(i = 1; i <= 100; i = i + 1) {


A [i + 1] = A [i] + C [i]; B [i + 1] =/B*[i]
S1+*A/ [i
+ 1]; / * S2 * /
}
Giả sửA, B,vàClà các mảng riêng biệt, không trùng lặp. (Trong thực tế, các mảng
đôi khi có thể giống nhau hoặc có thể chồng lên nhau. Bởi vì các mảng có thể
được truyền dưới dạng tham số cho một thủ tục, bao gồm vòng lặp này, nên việc
xác định xem các mảng có chồng chéo hay giống nhau hay không thường đòi hỏi
sự phân tích phức tạp, liên thủ tục của chương trình.) Dữ liệu phụ thuộc vào các
câu lệnh S1 và S2 trong vòng lặp là gì?

CÂU TRẢ LỜI Có hai phụ thuộc khác nhau:

1. S1 sử dụng một giá trị được tính toán bởi S1 trong một lần lặp trước đó, kể từ
lần lặp tôitính toánA [i + 1],được đọc lặp đi lặp lạii + 1.Điều này cũng đúng
với S2 đối vớiB [i]vàB [i + 1].

2. S2 sử dụng giá trị,A [i + 1],được tính toán bởi S1 trong cùng một lần lặp.

Hai yếu tố phụ thuộc này khác nhau và có tác dụng khác nhau. Để xem chúng khác
nhau như thế nào, hãy giả sử rằng chỉ có một trong những phụ thuộc này tồn tại tại
một thời điểm. Bởi vì sự phụ thuộc của câu lệnh S1 vào một lần lặp trước đó của S1, sự
phụ thuộc này được thực hiện theo vòng lặp. Sự phụ thuộc này buộc các lần lặp liên tiếp
của vòng lặp này phải thực hiện hàng loạt.
Sự phụ thuộc thứ hai ở trên (S2 phụ thuộc vào S1) nằm trong nó-
240 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

eration và không được thực hiện theo vòng lặp. Do đó, nếu đây là sự phụ thuộc
duy nhất, thì nhiều lần lặp của vòng lặp có thể thực hiện song song, miễn là mỗi
cặp câu lệnh trong một lần lặp được giữ theo thứ tự. Chúng tôi đã thấy kiểu phụ
thuộc này trong một ví dụ trong Phần 4.1, nơi việc mở cuộn có thể hiển thị sự
song song.
N

Cũng có thể có một sự phụ thuộc mang theo vòng lặp không ngăn cản sự song
song, như ví dụ tiếp theo cho thấy.

THÍ DỤ Hãy xem xét một vòng lặp như sau:

vì(i = 1; i <= 100; i = i + 1) {


A [i] = A [i] + B [i]; B [i + 1] = C/ *[i]S1
+D*/
[i]; / * S2 * /
}

Sự phụ thuộc giữa S1 và S2 là gì? Vòng lặp này có song song không? Nếu không,
hãy chỉ cách làm cho nó song song.

CÂU TRẢ LỜI Câu lệnh S1 sử dụng giá trị được gán trong lần lặp trước bởi câu lệnh S2, do đó, có sự
phụ thuộc được thực hiện trong vòng lặp giữa S2 và S1. Bất chấp sự phụ thuộc vào
vòng lặp này, vòng lặp này có thể được thực hiện song song. Không giống như vòng lặp
trước đó, sự phụ thuộc này không phải là vòng tròn: Không câu lệnh nào phụ thuộc vào
chính nó, và mặc dù S1 phụ thuộc vào S2, nhưng S2 không phụ thuộc vào S1. Một vòng
lặp là song song nếu nó có thể được viết mà không có chu trình trong các phần phụ
thuộc, vì không có chu trình có nghĩa là các phần phụ thuộc đưa ra thứ tự từng phần
trên các câu lệnh.
Mặc dù không có phụ thuộc vòng nào trong vòng lặp trên, nhưng nó
phải được biến đổi để phù hợp với thứ tự từng phần và thể hiện tính song
song. Hai quan sát rất quan trọng đối với sự chuyển đổi này:

1. Không có sự phụ thuộc từ S1 đến S2. Nếu có, thì sẽ có một chu trình
trong các phụ thuộc và vòng lặp sẽ không song song. Vì không có
sự phụ thuộc khác này, nên việc hoán đổi hai câu lệnh sẽ không ảnh
hưởng đến việc thực thi S2.

2. Trong lần lặp đầu tiên của vòng lặp, câu lệnh S1 phụ thuộc vào giá trị củaB [1]
được tính toán trước khi bắt đầu vòng lặp.

Hai quan sát này cho phép chúng ta thay thế vòng lặp ở trên bằng
chuỗi mã sau:

A [1] = A [1] + B [1]; vì(i = 1; i <=


99; i = i + 1) {
B [i + 1] = C [i] + D [i]; A [i + 1] =
A [i + 1] + B [i + 1];
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 241

}
B [101] = C [100] + D [100];

Sự phụ thuộc giữa hai câu lệnh không còn được thực hiện theo vòng lặp nữa, do
đó các lần lặp của vòng lặp có thể bị chồng chéo, miễn là các câu lệnh trong mỗi
lần lặp được giữ theo thứ tự.
N

Phân tích của chúng tôi cần bắt đầu bằng cách tìm tất cả các phụ thuộc được thực hiện theo
vòng lặp. Thông tin phụ thuộc này làkhông chính xác, theo nghĩa nó cho chúng ta biết rằng sự phụ
thuộc như vậycó thểhiện hữu. Hãy xem xét ví dụ sau:

vì(i = 1; i <= 100; i = i + 1) {


A [i] = B [i] + C [i] D [i] =
A [i] * E [i]
}

Tham chiếu thứ hai đếnMộttrong ví dụ này không cần phải dịch sang lệnh nạp, vì
chúng ta biết rằng giá trị được tính toán và lưu trữ bởi câu lệnh trước đó; do đó, tham
chiếu thứ hai đếnMộtcó thể chỉ đơn giản là một tham chiếu đến sổ đăng ký trong đó
Mộtđã được tính toán. Thực hiện tối ưu hóa này yêu cầu biết rằng hai tham chiếu là
luôn luônđến cùng một địa chỉ bộ nhớ và không có quyền truy cập can thiệp vào cùng
một vị trí. Thông thường, phân tích sự phụ thuộc dữ liệu chỉ cho biết rằng một tham
chiếucó thểphụ thuộc vào cái khác; một phân tích phức tạp hơn được yêu cầu để xác
định rằng hai tài liệu tham khảocần phảiđến cùng một địa chỉ. Trong ví dụ trên, một
phiên bản đơn giản của phân tích này là đủ, vì hai tham chiếu nằm trong cùng một
khối cơ bản.
Thường thì các phụ thuộc được thực hiện theo vòng lặp có dạngsự tái xuất:

vì(i = 2; i <= 100; i = i + 1) {


Y [i] = Y [i-1] + Y [i];
}

Lặp lại là khi một biến được xác định dựa trên giá trị của biến đó trong một
lần lặp trước đó, thường là lần lặp ngay trước đó, như trong đoạn trên. Việc
phát hiện một lần lặp lại có thể quan trọng vì hai lý do: Một số kiến trúc (đặc
biệt là máy tính vectơ) có hỗ trợ đặc biệt để thực thi các lần lặp lại và một số
lần lặp lại có thể là nguồn gốc của một lượng song song hợp lý. Để xem cách
sau có thể đúng, hãy xem xét vòng lặp này:

vì(i = 6; i <= 100; i = i + 1) {


Y [i] = Y [i-5] + Y [i];
}
242 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Trên lặp lạitôi, phần tử tham chiếu vòng lặptôi-5. Vòng lặp được cho là có khoảng cách
phụ thuộccủa 5. Nhiều vòng lặp với các phụ thuộc mang theo có khoảng cách phụ
thuộc là 1. Khoảng cách càng lớn thì khả năng song song càng nhiều bằng cách mở
vòng lặp. Ví dụ, nếu chúng ta mở vòng lặp đầu tiên, với khoảng cách phụ thuộc là 1,
các câu lệnh liên tiếp phụ thuộc vào nhau; vẫn có một số song song giữa các hướng
dẫn riêng lẻ, nhưng không nhiều. Nếu chúng ta mở vòng lặp có khoảng cách phụ
thuộc là 5, sẽ có một chuỗi năm câu lệnh không có phụ thuộc và do đó nhiều ILP hơn.
Mặc dù nhiều vòng lặp với các phụ thuộc được thực hiện theo vòng lặp có khoảng
cách phụ thuộc là 1, các trường hợp có khoảng cách lớn hơn sẽ phát sinh và khoảng
cách dài hơn cũng có thể cung cấp đủ song song để giữ cho bộ xử lý bận rộn.

Tìm kiếm sự phụ thuộc


Tìm kiếm các phụ thuộc trong một chương trình là một phần quan trọng của ba nhiệm
vụ: (1) lập lịch trình mã tốt, (2) xác định các vòng lặp nào có thể chứa song song và (3)
loại bỏ các phụ thuộc tên. Sự phức tạp của phân tích sự phụ thuộc phát sinh do sự
hiện diện của mảng và con trỏ trong các ngôn ngữ như C hoặc C ++ hoặc truyền tham
số tham chiếu truyền trong Fortran. Vì các tham chiếu biến vô hướng tham chiếu rõ
ràng đến một tên, chúng thường có thể được phân tích khá dễ dàng, với bí danh vì các
con trỏ và tham số tham chiếu gây ra một số phức tạp và không chắc chắn trong phân
tích.
Làm thế nào để trình biên dịch phát hiện các phụ thuộc nói chung? Gần như tất cả
các thuật toán phân tích sự phụ thuộc hoạt động dựa trên giả định rằng các chỉ số
mảng làtình cảm.Nói một cách đơn giản nhất, chỉ số mảng một chiều là affine nếu nó
có thể được viết dưới dạng một×tôi+b,ở đâumộtvàblà hằng số, vàtôilà biến chỉ số vòng
lặp. Chỉ mục của mảng nhiều chiều là affine nếu chỉ mục trong mỗi chiều là affine. Các
truy cập mảng thưa thớt, thường có dạngx [y [i]],là một trong những ví dụ chính về truy
cập không theo quy định.
Do đó, việc xác định xem có sự phụ thuộc giữa hai tham chiếu đến cùng một mảng
trong một vòng lặp hay không tương đương với việc xác định xem hai hàm affine có
thể có cùng giá trị cho các chỉ số khác nhau giữa các giới hạn của vòng lặp hay không.
Ví dụ: giả sử chúng ta đã lưu trữ vào một phần tử mảng có giá trị chỉ mục một×tôi+bvà
được tải từ cùng một mảng với giá trị chỉ mụcc×tôi+d, ở đâutôilà biến chỉ mục vòng lặp
for chạy từmđếnN.Sự phụ thuộc tồn tại nếu có hai điều kiện:

1. Có hai chỉ số lặp lại,jvàk, cả trong giới hạn của vòng lặp for. Đó làm≤j≤
n, m≤k≤N.
2. Vòng lặp lưu trữ thành một phần tử mảng được lập chỉ mục bởimột×j+bvà sau đó
tìm nạp từ đótương tựphần tử mảng khi nó được lập chỉ mục bởic×k+d. Đó là,một×
j+ b=c×k+d.
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 243

Nói chung, chúng tôi không thể xác định liệu có tồn tại sự phụ thuộc vào thời điểm biên dịch
hay không. Ví dụ, các giá trị củaa, b, c, vàdcó thể không được biết (chúng có thể là các giá trị trong
các mảng khác), khiến không thể biết liệu có tồn tại sự phụ thuộc hay không. Trong các trường hợp
khác, việc kiểm tra sự phụ thuộc có thể rất tốn kém nhưng có thể quyết định được tại thời điểm
biên dịch. Ví dụ: các truy cập có thể phụ thuộc vào các chỉ số lặp của nhiều vòng lặp lồng nhau. Tuy
nhiên, nhiều chương trình chủ yếu chứa các chỉ mục đơn giản trong đó
a, b, c,vàdlà tất cả các hằng số. Đối với những trường hợp này, có thể đưa ra các bài kiểm tra thời
gian biên dịch hợp lý cho sự phụ thuộc.
Ví dụ, một thử nghiệm đơn giản và đủ để không có sự phụ thuộc làước chung lớn
nhất, hoặc GCD, thử nghiệm. Nó dựa trên quan sát rằng nếu tồn tại sự phụ thuộc theo
vòng lặp, thì GCD (c, a) phảichia(d - b). (Nhớ lại rằng một số nguyên,x,phân chiamột số
nguyên khác,y, nếu không có phần còn lại khi chúng ta thực hiện phép chiay / xvà
nhận một thương số nguyên.)

THÍ DỤ Sử dụng kiểm tra GCD để xác định xem các phụ thuộc có tồn tại trong vòng lặp sau hay
không:

vì(i = 1; i <= 100; i = i + 1) {


X [2 * i + 3] = X [2 * i] * 5.0;
}

CÂU TRẢ LỜI Đưa ra các giá trịmột=2,b=3,c=2 vàd=0, rồi đến GCD (AC) = 2 và d - b= -
3. Vì 2 không chia –3 nên không phụ thuộc. N

Bài kiểm tra GCD đủ để đảm bảo rằng không tồn tại sự phụ thuộc (bạn có thể chỉ ra
điều này trong Bài tập); tuy nhiên, có những trường hợp kiểm tra GCD thành công
nhưng không tồn tại sự phụ thuộc. Điều này có thể phát sinh, ví dụ, vì thử nghiệm
GCD không tính đến giới hạn của vòng lặp.
Nói chung, việc xác định xem liệu một sự phụ thuộc có thực sự tồn tại hay không là NP-đầy đủ. Tuy
nhiên, trong thực tế, nhiều trường hợp phổ biến có thể được phân tích chính xác với chi phí thấp. Gần đây,
các phương pháp tiếp cận sử dụng hệ thống phân cấp các thử nghiệm chính xác ngày càng tăng về tính
tổng quát và chi phí đã được chứng minh là vừa chính xác vừa hiệu quả. (Một bài kiểm tra làchính xácnếu
nó xác định chính xác liệu có tồn tại sự phụ thuộc hay không. Mặc dù trường hợp chung là hoàn chỉnh NP,
nhưng vẫn tồn tại các thử nghiệm chính xác cho các tình huống hạn chế và rẻ hơn nhiều.)
Ngoài việc phát hiện sự hiện diện của một sự phụ thuộc, một trình biên dịch còn
muốn phân loại kiểu phụ thuộc. Sự phân loại này cho phép trình biên dịch nhận ra các
phụ thuộc tên và loại bỏ chúng tại thời điểm biên dịch bằng cách đổi tên và sao chép.

THÍ DỤ Vòng lặp sau đây có nhiều loại phụ thuộc. Tìm tất cả các phụ thuộc thực
sự, phụ thuộc đầu ra và phụ thuộc, và loại bỏ
244 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

phụ thuộc đầu ra và phụ thuộc bằng cách đổi tên.

vì(i = 1; i <= 100; i = i + 1) {


Y [i] = X [i] / c; / * S1 * / X [i] = X
[i] + c; / * S2 * / Z [i] = Y [i] + c; /
* S3 * / Y [i] = c - Y [i]; / * S4 * /

CÂU TRẢ LỜI Các phụ thuộc sau tồn tại trong số bốn câu lệnh:

1. Có sự phụ thuộc thực sự từ S1 đến S3 và từ S1 đến S4 vìY [i].Đây


không phải là vòng lặp được thực hiện, vì vậy chúng không ngăn
vòng lặp được coi là song song. Những phụ thuộc này sẽ buộc S3
và S4 phải đợi S1 hoàn thành.

2. Có sự đối lập từ S1 đến S2, dựa trênX [i].

3. Có sự chống phụ thuộc từ S3 đến S4 choY [i].

4. Có sự phụ thuộc đầu ra từ S1 đến S4, dựa trênY [i].

Phiên bản sau của vòng lặp loại bỏ những phụ thuộc sai (hoặc giả)
này.

vì(i = 1; i <= 100; i = i + 1 {


/ * Y được đổi tên thành T để loại bỏ sự phụ thuộc đầu ra
* / T [i] = X [i] / c;
/ * X được đổi tên thành X1 để loại bỏ phụ thuộc * / X1 [i]
= X [i] + c;
/ * Y được đổi tên thành T để loại bỏ sự phụ thuộc * / Z
[i] = T [i] + c;
Y [i] = c - T [i];
}
Sau vòng lặp, biếnXđã được đổi tênX1.Trong mã sau vòng lặp, trình biên dịch có thể chỉ
cần thay thế tênXquaX1.Trong trường hợp này, việc đổi tên không yêu cầu thao tác sao
chép thực tế nhưng có thể được thực hiện bằng cách thay thế tên hoặc bằng cách cấp
phát thanh ghi. Tuy nhiên, trong các trường hợp khác, việc đổi tên sẽ yêu cầu sao chép.
N

Phân tích sự phụ thuộc là một công nghệ quan trọng để khai thác tính song song.
Ở cấp độ lệnh, nó cung cấp thông tin cần thiết để trao đổi các tham chiếu bộ nhớ khi
lập lịch, cũng như để xác định lợi ích của việc mở vòng lặp. Để phát hiện song song
mức vòng lặp, phân tích sự phụ thuộc là công cụ cơ bản. Việc biên dịch hiệu quả các
chương trình sang máy tính vectơ hoặc máy tính đa xử lý phụ thuộc vào sự phê bình-
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 245

cally về phân tích này. Hạn chế chính của phân tích sự phụ thuộc là nó chỉ áp dụng
trong một số trường hợp hạn chế, cụ thể là giữa các tham chiếu trong một tổ vòng lặp
đơn và sử dụng các hàm chỉ mục affine. Do đó, có rất nhiều tình huống trong đó phân
tích sự phụ thuộc theo hướng mảngkhông thểcho chúng tôi biết những gì chúng tôi
có thể muốn biết, bao gồm

N khi các đối tượng được tham chiếu qua con trỏ thay vì chỉ số mảng (nhưng hãy xem thảo
luận bên dưới);

N khi lập chỉ mục mảng là gián tiếp thông qua một mảng khác, điều này xảy ra với
nhiều biểu diễn của mảng thưa thớt;

N khi sự phụ thuộc có thể tồn tại đối với một số giá trị của các đầu vào, nhưng không tồn
tại trên thực tế khi mã được chạy vì các đầu vào không bao giờ nhận các giá trị đó;

N khi tối ưu hóa phụ thuộc vào việc biết nhiều hơn khả năng phụ thuộc,
nhưng cần biếtcái màviệc ghi một biến có phụ thuộc vào việc đọc biến đó
hay không.

Để giải quyết vấn đề phân tích chương trình với con trỏ, một loại phân tích khác, thường
được gọi làchỉ tớiphân tích, là bắt buộc (xem Wilson và Lam [1995]). Câu hỏi quan trọng mà
chúng tôi muốn trả lời từ phân tích sự phụ thuộc của con trỏ là liệu hai con trỏ có thể chỉ
định cùng một địa chỉ hay không. Trong trường hợp cấu trúc dữ liệu động phức tạp, vấn đề
này là vô cùng khó khăn. Ví dụ: chúng tôi có thể muốn biết liệu hai con trỏ có thể tham chiếu
đếntương tựnút trong danh sách tại một điểm nhất định trong chương trình, nói chung là
không thể xác định được và trong thực tế là cực kỳ khó trả lời. Tuy nhiên, chúng tôi có thể
trả lời một câu hỏi đơn giản hơn: hai con trỏ có thể chỉ định các nút trongtương tựdanh
sách, ngay cả khi chúng có thể là các nút riêng biệt. Phân tích hạn chế hơn này vẫn có thể
khá hữu ích trong việc lập lịch truy cập bộ nhớ được thực hiện thông qua con trỏ.

Phương pháp cơ bản được sử dụng trong phân tích điểm đến dựa trên thông tin từ ba
nguồn chính:

1. Nhập thông tin, thông tin này hạn chế những gì một con trỏ có thể trỏ đến.

2. Thông tin thu được khi một đối tượng được cấp phát hoặc khi địa chỉ của một đối tượng được
lấy, có thể được sử dụng để hạn chế những gì một con trỏ có thể trỏ đến. Ví dụ, nếu p luôn trỏ
đến một đối tượng được phân bổ trong một dòng nguồn nhất định và q không bao giờ trỏ
đến đối tượng đó, thì p và q không bao giờ có thể trỏ đến cùng một đối tượng.

3. Thông tin thu được từ phép gán con trỏ. Ví dụ, nếu p có thể được gán giá
trị của q, thì p có thể trỏ đến bất kỳ thứ gì mà q trỏ tới.

Có một số trường hợp phân tích con trỏ đã được áp dụng thành công
và cực kỳ hữu ích:
N Khi con trỏ được sử dụng để chuyển địa chỉ của một đối tượng làm tham số, nó là pos-
246 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

có khả năng sử dụng phân tích điểm để xác định tập hợp các đối tượng có thể được tham chiếu
bởi một con trỏ. Một công dụng quan trọng là xác định xem hai tham số con trỏ có thể chỉ định
cùng một đối tượng hay không.

N Khi một con trỏ có thể trỏ đến một trong một số kiểu, đôi khi có thể xác định rằng
kiểu của đối tượng dữ liệu mà một con trỏ chỉ định tại các phần khác nhau của
chương trình.

N Thường có thể tách ra các con trỏ chỉ có thể trỏ đến một đối tượng cục bộ so với một đối
tượng toàn cục.

Có hai loại hạn chế khác nhau ảnh hưởng đến khả năng phân tích sự phụ thuộc
chính xác của chúng ta đối với các chương trình lớn. Loại hạn chế đầu tiên phát sinh từ
các hạn chế trong các thuật toán phân tích. Thông thường, chúng tôi bị hạn chế bởi sự
thiếu khả năng ứng dụng của phân tích hơn là sự thiếu sót trong phân tích sự phụ
thuộc. Ví dụ, phân tích sự phụ thuộc cho con trỏ về cơ bản là không thể đối với các
chương trình sử dụng con trỏ theo kiểu tùy ý - ví dụ, bằng cách thực hiện số học trên
con trỏ.
Hạn chế thứ hai là cần phải phân tích hành vi qua các ranh giới thủ tục để có được
thông tin chính xác. Ví dụ: nếu một thủ tục chấp nhận hai tham số là con trỏ, việc xác
định xem các giá trị có thể giống nhau hay không đòi hỏi phải phân tích qua các ranh
giới của thủ tục. Loại phân tích này, được gọi làphân tích liên thủ tục, khó và phức tạp
hơn nhiều so với việc phân tích trong một quy trình đơn lẻ. Không giống như trường
hợp phân tích chỉ số mảng trong một tổ vòng lặp, phân tích điểm tới thường yêu cầu
phân tích liên thủ tục. Lý do cho điều này là đơn giản. Giả sử chúng ta đang phân tích
một đoạn chương trình có hai con trỏ; nếu phân tích không biết gì về hai con trỏ ở đầu
đoạn chương trình thì phải dè dặt và giả sử trường hợp xấu nhất. Trường hợp xấu
nhất là hai con trỏcó thểchỉ định cùng một đối tượng, nhưng chúng khôngđảm bảođể
chỉ định cùng một đối tượng. Trường hợp xấu nhất này có khả năng lan truyền thông
qua việc phân tích tạo ra thông tin vô ích. Trên thực tế, việc nhận được thông tin liên
thủ tục chính xác đầy đủ thường quá đắt đối với các chương trình thực. Thay vào đó,
các trình biên dịch thường sử dụng các phép gần đúng trong phân tích liên thủ tục.
Kết quả là thông tin có thể quá không chính xác để hữu ích.

Các ngôn ngữ lập trình hiện đại sử dụng kiểu gõ mạnh, chẳng hạn như Java, giúp việc
phân tích các phụ thuộc trở nên dễ dàng hơn. Đồng thời, việc sử dụng rộng rãi các thủ tục
để cấu trúc chương trình, cũng như các kiểu dữ liệu trừu tượng, làm cho việc phân tích trở
nên khó khăn hơn. Tuy nhiên, chúng tôi kỳ vọng rằng những tiến bộ tiếp tục trong các thuật
toán phân tích kết hợp với tầm quan trọng ngày càng tăng của phân tích sự phụ thuộc con
trỏ sẽ có nghĩa là vấn đề quan trọng này sẽ tiếp tục có tiến bộ.

Loại bỏ tính toán phụ thuộc


Trình biên dịch có thể giảm tác động của các phép tính phụ thuộc để đạt được nhiều
ILP hơn. Kỹ thuật quan trọng là loại bỏ hoặc giảm bớt một phép tính phụ thuộc
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 247

bằng cách thay thế ngược, làm tăng số lượng song song và đôi khi tăng số lượng tính
toán cần thiết. Các kỹ thuật này có thể được áp dụng cả trong một khối cơ bản và
trong các vòng lặp, và chúng tôi mô tả chúng theo cách khác nhau.
Trong một khối cơ bản, đơn giản hóa đại số của các biểu thức và tối ưu hóa
được gọi làsao chép nhân giống, giúp loại bỏ các thao tác sao chép giá trị, có thể
được sử dụng để đơn giản hóa các chuỗi như sau:

DADDUI R1, R2, # 4


DADDUI R1, R1, # 4
đến:
DADDUI R1, R2, # 8

giả sử đây là cách sử dụng duy nhất củaR1.Trên thực tế, các kỹ thuật chúng tôi đã sử
dụng để giảm nhiều gia số của chỉ số mảng trong quá trình mở vòng lặp và di chuyển
các gia số trên các địa chỉ bộ nhớ trong Phần 4.1 là các ví dụ về kiểu tối ưu hóa này.

Trong các ví dụ này, các phép tính thực sự bị loại bỏ, nhưng cũng có thể
chúng ta muốn tăng tính song song của mã, thậm chí có thể tăng số lượng
hoạt động. Những tối ưu hóa như vậy được gọi làgiảm chiều cao cây, vì
chúng làm giảm chiều cao của cấu trúc cây đại diện cho một phép tính, làm
cho nó rộng hơn nhưng ngắn hơn. Hãy xem xét chuỗi mã sau:

CỘNG R1, R2, R3


CỘNG R4, R1, R6
CỘNG R8, R4, R7

Lưu ý rằng trình tự này yêu cầu ít nhất ba chu kỳ thực thi, vì tất cả các lệnh đều
phụ thuộc vào lệnh trước đó. Bằng cách tận dụng khả năng kết hợp, chúng ta có
thể chuyển đổi mã và viết lại nó thành:

CỘNG R1, R2, R3


CỘNG R4, R6, R7
CỘNG R8, R1, R4

Trình tự này có thể được tính trong hai chu kỳ thực thi. Khi sử dụng tính năng hủy
cuộn vòng lặp, các cơ hội cho các loại tối ưu hóa này thường xuyên xảy ra.
Mặc dù số học với phạm vi không giới hạn và độ chính xác là liên kết, nhưng số học
máy tính không phải là liên kết, đối với số nguyên, vì phạm vi giới hạn hoặc số học dấu
phẩy động, vì cả phạm vi và độ chính xác. Do đó, việc sử dụng các kỹ thuật tái cấu trúc
này đôi khi có thể dẫn đến hành vi sai lầm, mặc dù những trường hợp như vậy là rất
hiếm. Vì lý do này, hầu hết các trình biên dịch yêu cầu rằng các tối ưu hóa dựa trên sự
kết hợp phải được bật một cách rõ ràng.
Khi các vòng lặp được bỏ cuộn, loại tối ưu hóa đại số này rất quan trọng để giảm
tác động của các yếu tố phụ thuộc phát sinh từ các lần lặp lại.Tái phátlà các biểu thức
có giá trị trên một lần lặp được cung cấp bởi một hàm phụ thuộc vào các lần lặp trước
đó. Khi một vòng lặp có lặp lại không được cuộn, chúng tôi có thể tối ưu hóa đại số cho
vòng lặp chưa được cuộn, để lặp lại chỉ cần được đánh giá-
248 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

uated một lần cho mỗi lần lặp lại không được cuộn. Một kiểu lặp lại phổ biến phát sinh từ một câu
lệnh chương trình rõ ràng, chẳng hạn như:

sum = sum + x;

Giả sử chúng ta bỏ cuộn một vòng lặp với lần lặp lại này năm lần, nếu chúng ta để giá
trị của x trên năm lần lặp này được cho bởix1, x2, x3, x4,vàx5,thì chúng ta có thể viết giá
trị củaTổngở cuối mỗi lần bỏ cuộn như:

sum = sum + x1 + x2 + x3 + x4 + x5;

Nếu chưa được tối ưu hóa, biểu thức này yêu cầu năm phép toán phụ thuộc, nhưng nó có thể được viết lại
thành:

sum = ((sum + x1) + (x2 + x3)) + (x4 + x5);

mà chỉ có thể được đánh giá trong ba phép toán phụ thuộc.
Các lần lặp lại cũng phát sinh từ các phép tính ngầm, chẳng hạn như các phép tính liên
quan đến lập chỉ mục mảng. Mỗi chỉ mục mảng chuyển thành một địa chỉ được tính toán
dựa trên biến chỉ số vòng lặp. Một lần nữa, với việc giải nén và tối ưu hóa đại số, các phép
tính phụ thuộc có thể được giảm thiểu.

Phần mềm Pipelining: Symbolic Loop Unrolling

Chúng ta đã thấy rằng một kỹ thuật biên dịch, giải nén vòng lặp, rất hữu ích để
phát hiện ra sự song song giữa các lệnh bằng cách tạo ra các chuỗi mã đường
thẳng dài hơn. Có hai kỹ thuật quan trọng khác đã được phát triển cho mục đích
này:phần mềm pipeliningvàlập lịch theo dõi.
Phần mềm pipelininglà một kỹ thuật để tổ chức lại các vòng lặp sao cho mỗi lần lặp
trong mã do phần mềm tổng hợp được thực hiện từ các hướng dẫn được chọn từ các
lần lặp khác nhau của vòng lặp ban đầu. Cách tiếp cận này dễ hiểu nhất bằng cách
xem mã đã lên lịch cho phiên bản siêu địa phương của MIPS, xuất hiện trong Hình 4.2
trên trang 231. Bộ lập lịch trong ví dụ này về cơ bản xen kẽ các lệnh từ các lần lặp vòng
lặp khác nhau, để tách các lệnh phụ thuộc xảy ra. trong một lần lặp vòng lặp duy nhất.
Bằng cách chọn các hướng dẫn từ các lần lặp khác nhau, các phép tính phụ thuộc
được tách biệt với nhau bởi toàn bộ phần thân của vòng lặp, làm tăng khả năng vòng
lặp chưa cuộn có thể được lập lịch trình mà không bị gián đoạn.

Một vòng lặp do phần mềm tổng hợp xen kẽ các lệnh từ các lần lặp khác nhau mà không
cần hủy vòng lặp, như được minh họa trong Hình 4.6. Kỹ thuật này là phần mềm đối chiếu
với những gì thuật toán của Tomasulo thực hiện trong phần cứng. Vòng lặp do phần mềm
tạo cho ví dụ trước đó sẽ chứa một lần tải, một lần bổ sung và một cửa hàng, mỗi lần lặp lại
từ một lần lặp khác nhau. Ngoài ra còn có một số mã khởi động cần thiết trước khi vòng lặp
bắt đầu cũng như mã để kết thúc sau khi hoàn thành vòng lặp. Chúng tôi sẽ bỏ qua những
điều này trong cuộc thảo luận này, vì đơn giản; chủ đề được đề cập trong Bài tập.
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 249

Sự lặp lại
0 Sự lặp lại
1 Sự lặp lại
2 Sự lặp lại
3 Sự lặp lại
4

Phần mềm-
pipelined
sự lặp lại

HÌNH 4.6 Một vòng lặp do phần mềm tổng hợp chọn các lệnh từ các lần lặp vòng lặp khác
nhau, do đó tách các lệnh phụ thuộc trong một lần lặp của vòng lặp ban đầu.Mã khởi động và
mã kết thúc sẽ tương ứng với các phần bên trên và bên dưới phần lặp lại theo đường dẫn của phần
mềm.

THÍ DỤ Hiển thị phiên bản do phần mềm tổng hợp của vòng lặp này, phiên bản này làm tăng
tất cả các phần tử của một mảng có địa chỉ bắt đầu bằng R1 bởi nội dung của F2:

Vòng: LD F0,0 (R1)


ADD.D F4, F0, F2
SD F4,0 (R1)
DADDUI R1, R1, # - 8
BNE R1, R2, Vòng lặp

Bạn có thể bỏ qua mã khởi động và làm sạch.

CÂU TRẢ LỜI Phần mềm pipelining hủy cuộn vòng lặp một cách tượng trưng và sau đó chọn các
hướng dẫn từ mỗi lần lặp lại. Vì thao tác hủy cuộn là tượng trưng, nên hướng dẫn chi
phí vòng lặp (DADDUIvàBNE)không cần phải được nhân rộng. Đây là phần nội dung của
vòng lặp chưa được cuộn không có hướng dẫn trên đầu, đánh dấu các hướng dẫn được
thực hiện từ mỗi lần lặp:
250 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Lặp lại i: LD F0,0 (R1)


ADD.D F4, F0, F2
SD F4,0 (R1)
Lặp lại i + 1: LD F0,0 (R1)
ADD.D F4, F0, F2
SD 0 (R1), F4
Lặp lại i + 2: LD F0,0 (R1)
ADD.D F4, F0, F2
SD F4,0 (R1)

Các hướng dẫn đã chọn từ các lần lặp khác nhau sau đó được đặt cùng nhau trong
vòng lặp với các hướng dẫn điều khiển vòng lặp:

Vòng: SD F4,16 (R1) ; lưu trữ vào M [i]


ADD.D F4, F0, F2 ; thêm vào M [i-1]
LD F0,0 (R1) ; tải M [i-2]
DADDUI R1, R1, # - 8
BNE R1, R2, Vòng lặp

Vòng lặp này có thể được chạy với tốc độ 5 chu kỳ cho mỗi kết quả, bỏ qua
các phần khởi động và dọn dẹp, và giả sử rằngDADDUIđược lên lịch sau
ADD.DvàLDlệnh, với độ lệch đã điều chỉnh, được đặt trong khe trễ nhánh.
Bởi vì tải và lưu trữ được phân tách bằng hiệu số 16 (hai lần lặp), nên vòng
lặp sẽ chạy với hai lần lặp ít hơn. (Chúng tôi giải quyết vấn đề này và các
phần khởi động và dọn dẹp trong Bài tập 4.18.) Lưu ý rằng việc sử dụng lại
các thanh ghi (ví dụ: F4, F0 và R1) yêu cầu phần cứng tránh các nguy cơ WAR
sẽ xảy ra trong vòng lặp. Nguy cơ này không phải là vấn đề trong trường
hợp này, vì không xảy ra các gian hàng phụ thuộc vào dữ liệu.

Bằng cách nhìn vào phiên bản chưa được cuộn, chúng ta có thể thấy mã
khởi động và mã kết thúc sẽ cần là gì. Để khởi động, chúng ta sẽ cần thực
hiện bất kỳ lệnh nào tương ứng với lần lặp 1 và 2 sẽ không được thực hiện.
Những hướng dẫn này làLDcho các lần lặp 1 và 2 vàADD.Dcho lần lặp 1. Đối
với mã kết thúc, chúng ta cần thực hiện bất kỳ lệnh nào sẽ không được thực
hiện trong hai lần lặp cuối cùng. Chúng bao gồmADD.Dcho lần lặp lại cuối
cùng vàSDcho hai lần lặp lại cuối cùng. N

Quản lý đăng ký trong các vòng lặp do phần mềm có thể phức tạp. Ví dụ trên
không quá khó vì các thanh ghi được viết trên một lần lặp vòng lặp sẽ được đọc ở lần
tiếp theo. Trong các trường hợp khác, chúng ta có thể cần tăng số lần lặp lại giữa khi
chúng ta đưa ra một lệnh và khi kết quả được sử dụng. Sự gia tăng này là bắt buộc khi
có một số lượng nhỏ các lệnh trong thân vòng lặp và độ trễ lớn. Trong những trường
hợp như vậy, cần có sự kết hợp của phần mềm pipelining và giải nén vòng lặp. Một ví
dụ về điều này được hiển thị trong Bài tập.
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 251

Phần mềm pipelining có thể được coi làtượng trưngmở vòng lặp. Thật vậy, một số thuật toán cho phần mềm xoay vòng sử dụng các thuật toán giải phóng vòng lặp để

tìm ra cách phần mềm chuyển mạch vòng lặp. Ưu điểm chính của phần mềm pipelining so với việc giải nén vòng lặp thẳng là phần mềm pipelining tiêu tốn ít không gian mã

hơn. Phần mềm pipelining và giải nén vòng lặp, ngoài việc mang lại vòng lặp bên trong theo lịch trình tốt hơn, mỗi loại còn giảm một loại chi phí khác nhau. Việc hủy cuộn

vòng lặp làm giảm chi phí của vòng lặp — mã nhánh và mã cập nhật đối chiếu. Phần mềm pipelining giảm thời gian khi vòng lặp không chạy ở tốc độ cao nhất xuống còn

một lần cho mỗi vòng lặp khi bắt đầu và kết thúc. Nếu chúng ta bỏ cuộn một vòng lặp thực hiện 100 lần lặp với một số lần không đổi, chẳng hạn 4, chúng ta phải trả chi phí

100/4 = 25 lần mỗi khi bắt đầu vòng lặp không cuộn bên trong. Hình 4.7 cho thấy hành vi này bằng đồ thị. Bởi vì các kỹ thuật này tấn công hai loại chi phí khác nhau, hiệu

suất tốt nhất có thể đến từ việc thực hiện cả hai. chi phí cao so với hiệu quả của vòng lặp Pipelined phần mềm rất phức tạp và vấn đề quản lý sổ đăng ký sẽ tạo thêm sự phức

tạp. Để giúp giải quyết hai vấn đề cuối cùng trong số này, IA-64 đã bổ sung hỗ trợ phần cứng mở rộng cho đường dẫn phần mềm. Mặc dù phần cứng này có thể làm cho việc

áp dụng pipelining phần mềm hiệu quả hơn, nhưng nó không loại bỏ nhu cầu hỗ trợ trình biên dịch phức tạp hoặc nhu cầu đưa ra các quyết định khó khăn về cách tốt nhất

để biên dịch một vòng lặp. Hiệu suất tốt nhất có thể đến từ việc thực hiện cả hai. Trong thực tế, việc biên dịch bằng cách sử dụng phần mềm pipelining là khá khó khăn vì

một số lý do: nhiều vòng lặp yêu cầu chuyển đổi đáng kể trước khi chúng có thể được kết nối phần mềm, sự cân bằng giữa chi phí và hiệu quả của vòng lặp Pipelined phần

mềm là phức tạp, và vấn đề quản lý sổ đăng ký tạo thêm phức tạp. Để giúp giải quyết hai vấn đề cuối cùng trong số này, IA-64 đã bổ sung hỗ trợ phần cứng mở rộng cho

đường dẫn phần mềm. Mặc dù phần cứng này có thể làm cho việc áp dụng pipelining phần mềm hiệu quả hơn, nhưng nó không loại bỏ nhu cầu hỗ trợ trình biên dịch phức

tạp hoặc nhu cầu đưa ra các quyết định khó khăn về cách tốt nhất để biên dịch một vòng lặp. Hiệu suất tốt nhất có thể đến từ việc thực hiện cả hai. Trong thực tế, việc biên

dịch bằng cách sử dụng phần mềm pipelining là khá khó khăn vì một số lý do: nhiều vòng lặp yêu cầu chuyển đổi đáng kể trước khi chúng có thể được kết nối phần mềm, sự

cân bằng giữa chi phí và hiệu quả của vòng lặp Pipelined phần mềm là phức tạp, và vấn đề quản lý sổ đăng ký tạo thêm phức tạp. Để giúp giải quyết hai vấn đề cuối cùng

trong số này, IA-64 đã bổ sung hỗ trợ phần cứng mở rộng cho đường dẫn phần mềm. Mặc dù phần cứng này có thể làm cho việc áp dụng pipelining phần mềm hiệu quả

hơn, nhưng nó không loại bỏ nhu cầu hỗ trợ trình biên dịch phức tạp hoặc nhu cầu đưa ra các quyết định khó khăn về cách tốt nhất để biên dịch một vòng lặp. nhiều vòng

lặp yêu cầu chuyển đổi đáng kể trước khi chúng có thể được tạo thành phần mềm, sự cân bằng giữa chi phí và hiệu quả của vòng lặp Pipelined phần mềm rất phức tạp và

vấn đề quản lý sổ đăng ký tạo thêm sự phức tạp. Để giúp giải quyết hai vấn đề cuối cùng trong số này, IA-64 đã bổ sung hỗ trợ phần cứng mở rộng cho đường dẫn phần

mềm. Mặc dù phần cứng này có thể làm cho việc áp dụng pipelining phần mềm hiệu quả hơn, nhưng nó không loại bỏ nhu cầu hỗ trợ trình biên dịch phức tạp hoặc nhu cầu đưa ra các quyết định khó khăn về cách tốt nhất để biên

Lập lịch mã toàn cầu


Trong phần 4.1, chúng tôi đã xem xét việc sử dụng lập lịch trình mã và giải nén
vòng lặp để cải thiện ILP. Các kỹ thuật trong phần 4.1 hoạt động tốt khi phần
thân của vòng lặp là mã đường thẳng, vì vòng lặp không được cuộn kết quả trông
giống như một khối cơ bản duy nhất. Tương tự như vậy, phần mềm pipelining
hoạt động tốt khi phần thân là một khối cơ bản duy nhất, vì nó dễ dàng hơn để
tìm lịch trình lặp lại. Tuy nhiên, khi phần thân của một vòng lặp chưa được cuộn
có chứa luồng kiểm soát nội bộ, việc lập lịch trình mã phức tạp hơn nhiều. Nói
chung, lập lịch hiệu quả cho một thân vòng lặp với luồng điều khiển nội bộ sẽ yêu
cầu các lệnh di chuyển qua các nhánh, đó là lập lịch mã toàn cục. Trong phần này,
trước tiên chúng ta xem xét thách thức và hạn chế của việc lập lịch mã toàn cầu.
Trong phần 4.5, chúng tôi xem xét hỗ trợ phần cứng để loại bỏ luồng điều khiển
trong một vòng lặp bên trong; sau đó,
Lập lịch mã toàn cầu nhằm mục đích thu gọn một đoạn mã có cấu trúc kiểm soát nội bộ
thành một chuỗi ngắn nhất có thể để bảo toàn dữ liệu và các phụ thuộc điều khiển. Các phụ
thuộc dữ liệu buộc một thứ tự một phần đối với các hoạt động, trong khi các phụ thuộc điều
khiển ra lệnh cho các lệnh mà mã không thể được di chuyển dễ dàng. Sự phụ thuộc dữ liệu
được khắc phục bằng cách mở cuộn và, trong trường hợp hoạt động bộ nhớ, sử dụng phân
tích sự phụ thuộc để xác định xem hai tham chiếu có tham chiếu đến cùng một địa chỉ hay
không. Tìm chuỗi ngắn nhất có thể cho một đoạn mã có nghĩa là
252 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Khởi động Thư giãn


mã số mã số

Con số
của
chồng lên nhau
hoạt động
(a) Đường ống phần mềm Thời gian

Theo tỷ lệ
đến số Chồng chéo giữa
các lần lặp lại không được cuộn
mở cuộn

Con số
của
chồng lên nhau
hoạt động
(b) Mở vòng lặp Thời gian

HÌNH 4.7 Mẫu thực thi cho (a) một vòng lặp do phần mềm tổng hợp và (b) một vòng lặp
không được cuộn.Các vùng bóng mờ là thời điểm mà vòng lặp không chạy với sự chồng
chéo hoặc song song tối đa giữa các lệnh. Điều này xảy ra một lần ở đầu và một lần ở cuối
đối với vòng lặp do phần mềm tổng hợp. Đối với vòng lặp chưa được cuộn, nó xảy ram / n
lần nếu vòng lặp có tổng sốmlặp lại và không được cuộnNlần. Mỗi khối đại diện cho một lần
hủy đăng kýNcác lần lặp lại. Tăng số lần giải phóng sẽ giảm chi phí khởi động và dọn dẹp.
Chi phí của một lần lặp sẽ chồng lên tổng chi phí của lần lặp tiếp theo, do đó làm giảm tác
động. Tổng diện tích dưới vùng đa giác trong mỗi trường hợp sẽ giống nhau, vì tổng số hoạt
động chỉ là tốc độ thực hiện nhân với thời gian.

tìm chuỗi ngắn nhất chocon đường quan trọng, là chuỗi các lệnh phụ
thuộc dài nhất.
Sự phụ thuộc điều khiển phát sinh từ các nhánh vòng lặp được giảm bớt bằng cách bỏ cuộn.
Lập lịch mã toàn cục có thể làm giảm ảnh hưởng của sự phụ thuộc điều khiển phát sinh từ các
nhánh nonloop có điều kiện bằng cách di chuyển mã. Vì việc di chuyển mã qua các nhánh thường
sẽ ảnh hưởng đến tần suất thực thi của đoạn mã đó, nên việc sử dụng hiệu quả chuyển động mã
toàn cục yêu cầu ước tính tần suất tương đối của các đường dẫn khác nhau. Mặc dù chuyển động
mã toàn cục không thể đảm bảo mã nhanh hơn, nhưng nếu thông tin tần số là chính xác, trình
biên dịch có thể xác định xem chuyển động mã như vậy có khả năng dẫn đến mã nhanh hơn hay
không.
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 253

Chuyển động mã toàn cục rất quan trọng vì nhiều vòng lặp bên trong chứa các câu
lệnh điều kiện. Hình 4.8 cho thấy một đoạn mã điển hình, có thể được coi là sự lặp lại
của một vòng lặp chưa được cuộn và làm nổi bật luồng điều khiển phổ biến hơn.

A [i] = A [i] + B [i]

T F
A [i] = 0?

B [i] = X

C [i] =

HÌNH 4.8 Một đoạn mã và đường dẫn chung được tô màu xám.Chuyển các bài tập sang B hoặc C đòi
hỏi một phân tích phức tạp hơn so với mã đường thẳng. Trong phần này, chúng tôi tập trung vào việc lập
lịch phân đoạn mã này một cách hiệu quả mà không cần hỗ trợ phần cứng. Dự đoán hoặc hướng dẫn có
điều kiện, mà chúng ta sẽ thảo luận trong phần tiếp theo, cung cấp một cách khác để lập lịch cho mã này.

Việc lập lịch hiệu quả cho mã này có thể yêu cầu chúng ta chuyển các nhiệm vụ cho
B và C sang sớm hơn trong trình tự thực thi, trước khi kiểm tra A. Chuyển động mã
toàn cục như vậy phải thỏa mãn một tập hợp các ràng buộc là hợp pháp. Ngoài ra,
chuyển động của mã liên kết với B, không giống như chuyển động liên kết với C, là suy
đoán: nó sẽ chỉ tăng tốc độ tính toán khi đường dẫn chứa mã được thực hiện.

Để thực hiện chuyển động của B, chúng ta phải đảm bảo rằng cả luồng dữ liệu và hành
vi ngoại lệ đều không bị thay đổi. Các trình biên dịch tránh thay đổi hành vi ngoại lệ bằng
cách không di chuyển các lớp hướng dẫn nhất định, chẳng hạn như tham chiếu bộ nhớ, có
thể gây ra ngoại lệ. Trong phần 4.5, chúng ta sẽ xem cách hỗ trợ phần cứng cho phép nhiều
cơ hội hơn cho chuyển động mã đầu cơ cũng như loại bỏ các phụ thuộc điều khiển. Mặc dù
việc hỗ trợ đầu cơ được nâng cao như vậy có thể giúp bạn khám phá nhiều cơ hội hơn,
nhưng khó khăn trong việc lựa chọn cách biên dịch mã tốt nhất vẫn còn phức tạp.

Làm thế nào trình biên dịch có thể đảm bảo rằng các bài tập cho B và C có thể được
di chuyển mà không ảnh hưởng đến luồng dữ liệu? Để xem những gì liên quan, chúng
ta hãy xem xét trình tự tạo mã điển hình cho lưu đồ trong Hình 4.8. Giả sử rằng địa chỉ
của A, B, C lần lượt nằm trong R1, R2 và R3, đây là một chuỗi như vậy:
254 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

LD R4,0 (R1) ; tải A


LD R5,0 (R2) ; tải B
DADDU R4, R4, R5 ; Thêm vào A
SD 0 (R1), R4 ; Cửa hàng A
...
BNEZ R4, phần khác ; Kiểm tra A
... ; sau đó một phần
SD 0 (R2), ... ; Cửa hàng đến B
J tham gia ; nhảy qua người
phần khác: ... khác; phần khác
X ; mã cho X
...
tham gia: ... ; sau nếu
SD 0 (R3), ... ; cửa hàng C [i]

Đầu tiên chúng ta hãy xem xét vấn đề chuyển nhiệm vụ cho B đến trước BNEZ
hướng dẫn. Gọi lệnh cuối cùng để gán cho B trước câu lệnh if,tôi. Nếu B được
tham chiếu trước khi nó được gán trong đoạn mã X hoặc sau câu lệnh if, hãy gọi
lệnh tham chiếuj. Nếu có một chỉ dẫn như vậyj, sau đó chuyển nhiệm vụ đến B sẽ
thay đổi luồng dữ liệu của chương trình. Đặc biệt, việc chuyển nhiệm vụ sang B sẽ
khiếnjtrở nên phụ thuộc vào dữ liệu vào phiên bản đã chuyển của nhiệm vụ đến B
thay vìtôitrên đójban đầu phụ thuộc. Người ta có thể tưởng tượng ra các lược đồ
thông minh hơn để cho phép B được di chuyển ngay cả khi giá trị được sử dụng:
ví dụ: trong trường hợp đầu tiên, chúng ta có thể tạo một bản sao bóng của B
trước câu lệnh if và sử dụng bản sao bóng đó trong X. Các lược đồ như vậy là
thường được tránh, cả hai vì chúng phức tạp để thực hiện và vì chúng sẽ làm
chậm chương trình nếu dấu vết được chọn không tối ưu và các hoạt động kết
thúc yêu cầu các hướng dẫn bổ sung để thực thi.
Chuyển nhiệm vụ đến C lên trước nhánh đầu tiên cần hai bước. Đầu
tiên, nhiệm vụ được chuyển qua điểm nối của phần khác thành phần
tương ứng với phần sau đó. Sự di chuyển này làm cho các lệnh cho điều
khiển C phụ thuộc vào nhánh và có nghĩa là chúng sẽ không thực thi nếu
đường dẫn khác, là đường dẫn không thường xuyên, được chọn. Do đó,
các lệnh phụ thuộc dữ liệu vào việc gán cho C và thực thi sau đoạn mã
này, sẽ bị ảnh hưởng. Để đảm bảo giá trị chính xác được tính cho các
lệnh như vậy, một bản sao được tạo từ các lệnh tính toán và gán cho C
trên đường dẫn khác. Thứ hai, chúng ta có thể di chuyển C từ phần sau
của nhánh qua điều kiện rẽ nhánh, nếu nó không ảnh hưởng đến bất kỳ
luồng dữ liệu nào vào điều kiện nhánh. Nếu C được chuyển đến trước if-
test,
Từ ví dụ này, chúng ta có thể thấy rằng lập lịch mã toàn cục phải chịu nhiều ràng buộc.
Quan sát này là điều khiến các nhà thiết kế cung cấp hỗ trợ phần cứng để làm cho chuyển
động mã như vậy dễ dàng hơn và phần 4.5 khám phá chi tiết hỗ trợ đó.
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 255

Lập lịch mã toàn cầu cũng đòi hỏi sự cân bằng phức tạp để đưa ra quyết định
chuyển động mã. Ví dụ, giả sử rằng phép gán cho B có thể được di chuyển trước
nhánh có điều kiện (có thể với một số mã bù trên nhánh thay thế) liệu chuyển
động này có làm cho mã chạy nhanh hơn không? Câu trả lời là: có thể! Tương tự,
di chuyển các bản sao của C vào các nhánh if và else, làm cho mã ban đầu lớn
hơn! Chỉ khi trình biên dịch có thể di chuyển thành công việc tính toán qua if-test
thì mới có lợi ích.
Xem xét các yếu tố mà trình biên dịch sẽ phải xem xét khi di chuyển
tính toán và gán B:
N Tần số thực thi tương đối của trường hợp then và trường hợp khác trong nhánh là gì?
Nếu trường hợp đó xảy ra thường xuyên hơn nhiều, chuyển động mã có thể có lợi. Nếu
không, nó ít có khả năng xảy ra hơn, mặc dù không phải là không thể xem xét việc di
chuyển mã.

N Chi phí thực hiện phép tính và gán cho B ở trên nhánh là bao nhiêu?
Có thể có một số khe phát hành lệnh trống trong mã phía trên nhánh
và các lệnh cho B có thể được đặt vào các khe này mà nếu không sẽ
trống. Cơ hội này làm cho việc tính toán B "miễn phí" ít nhất cho đơn
hàng đầu tiên.
N Chuyển động của B sẽ thay đổi thời gian thực hiện như thế nào đối với trường hợp sau đó? Nếu
B ở đầu con đường quan trọng cho trường hợp sau đó, việc di chuyển nó có thể rất có lợi.

N B có phải là đoạn mã tốt nhất có thể được di chuyển phía trên nhánh không? Nó so sánh như
thế nào với chuyển động C hoặc các câu lệnh khác trong trường hợp đó?

N Giá của mã bồi thường có thể cần thiết cho elsecase là bao nhiêu? Mã này có
thể được lên lịch hiệu quả như thế nào và tác động của nó đến thời gian thực
thi là gì?

Như chúng ta có thể thấy từ điều nàymột phầndanh sách, lập lịch mã toàn cục là một vấn đề
cực kỳ phức tạp. Sự cân bằng phụ thuộc vào nhiều yếu tố và các quyết định cá nhân đối với các
hướng dẫn lịch trình toàn cầu phụ thuộc lẫn nhau rất nhiều. Ngay cả việc chọn hướng dẫn nào để
bắt đầu được coi là ứng cử viên cho chuyển động mã toàn cầu cũng phức tạp!
Để cố gắng đơn giản hóa quá trình này, một số phương pháp khác nhau để lập lịch mã toàn
cầu đã được phát triển. Hai phương pháp chúng ta khám phá ngắn gọn ở đây dựa trên một
nguyên tắc đơn giản: tập trung sự chú ý của trình biên dịch vào một đoạn mã đường thẳng đại
diện cho những gì được ước tính là đường dẫn mã được thực thi thường xuyên nhất. Việc hủy cuộn
được sử dụng để tạo mã đường thẳng, nhưng tất nhiên, sự phức tạp nảy sinh trong cách xử lý các
nhánh có điều kiện. Trong cả hai trường hợp, chúng được làm thẳng một cách hiệu quả bằng cách
chọn và lên lịch cho con đường thường xuyên nhất.
256 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Lập lịch theo dõi: Tập trung vào Đường dẫn quan trọng
Lập lịch theo dõi hữu ích cho các bộ xử lý có số lượng sự cố lớn trên mỗi xung nhịp, trong đó
việc thực thi có điều kiện hoặc dự đoán (xem Phần 4.5) là không phù hợp hoặc không được
hỗ trợ và khi việc mở vòng lặp đơn giản có thể không đủ để khám phá đủ ILP để giữ cho bộ
xử lý bận . Lập lịch theo dõi là một cách để tổ chức quá trình chuyển động mã toàn cầu, để
đơn giản hóa việc lập lịch mã bằng cách chịu chi phí của chuyển động mã có thể xảy ra trên
các đường dẫn ít thường xuyên hơn. Bởi vì nó có thể tạo racó ý nghĩachi phí chung trên
đường dẫn không thường xuyên được chỉ định, nó được sử dụng tốt nhất khi thông tin hồ
sơ chỉ ra sự khác biệt đáng kể về tần suất giữa các đường dẫn khác nhau và nơi thông tin hồ
sơ có nhiều dấu hiệu về hành vi chương trình độc lập với đầu vào. Tất nhiên, điều này hạn
chế khả năng áp dụng hiệu quả của nó đối với một số lớp chương trình nhất định.

Có hai bước để lập lịch trình theo dõi. Bước đầu tiên, được gọi làlựa chọn dấu vết,
cố gắng tìm một chuỗi các khối cơ bản có khả năng có các hoạt động sẽ được ghép lại
với nhau thành một số lượng lệnh nhỏ hơn; trình tự này được gọi làdấu vết. Bỏ cuộn
vòng lặp được sử dụng để tạo ra các dấu vết dài, vì các nhánh của vòng lặp được thực
hiện với xác suất cao. Ngoài ra, bằng cách sử dụng dự đoán nhánh tĩnh, các nhánh có
điều kiện khác cũng được chọn là lấy hoặc không lấy, do đó dấu vết kết quả là một
chuỗi đường thẳng do ghép nhiều khối cơ bản. Ví dụ, nếu đoạn chương trình được
hiển thị trong Hình 4.8 trên trang 253 tương ứng với một vòng lặp bên trong với
đường dẫn được đánh dấu thường xuyên hơn nhiều và vòng lặp không được gắn bốn
lần, dấu vết chính sẽ bao gồm bốn bản sao của phần tô bóng của chương trình, như
trong Hình 4.9. .
Sau khi một dấu vết được chọn, quá trình thứ hai, được gọi làtheo dõi nén, cố gắng
đưa dấu vết vào một số lượng nhỏ các hướng dẫn rộng. Trace compaction là lập lịch
mã; do đó, nó cố gắng di chuyển các hoạt động càng sớm càng tốt theo một trình tự
(theo dõi), đóng gói các hoạt động thành càng ít lệnh rộng (hoặc gói phát hành) càng
tốt.
Ưu điểm của phương pháp lập lịch theo dõi là nó đơn giản hóa các quyết định liên quan
đến chuyển động mã toàn cầu. Đặc biệt, các nhánh được xem như là bước nhảy vào hoặc ra
khỏi dấu vết đã chọn, được giả định là con đường có thể xảy ra nhất. Khi mã được di chuyển
qua các điểm vào và ra theo dõi như vậy, mã kế toán bổ sung thường sẽ cần thiết trên điểm
vào hoặc ra. Giả định quan trọng là dấu vết có khả năng xảy ra cao hơn nhiều so với các lựa
chọn thay thế nên chi phí của mã sổ sách kế toán không cần phải là yếu tố quyết định: nếu
một lệnh có thể được di chuyển và làm cho dấu vết chính thực thi nhanh hơn, thì nó sẽ được
di chuyển.
Mặc dù lập lịch theo dõi đã được áp dụng thành công cho mã khoa học với các
vòng lặp chuyên sâu và dữ liệu hồ sơ chính xác của nó, vẫn chưa rõ liệu cách tiếp cận
này có phù hợp với các chương trình ít đặc trưng và ít vòng lặp hơn hay không. Trong
các chương trình như vậy, chi phí đáng kể của mã bù có thể làm cho việc lập lịch theo
dõi trở thành một cách tiếp cận kém hấp dẫn, hoặc tốt nhất, việc sử dụng hiệu quả nó
sẽ cực kỳ phức tạp đối với trình biên dịch.
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 257

A [i] = A [i] + B [i]

T F
A [i] = 0?
Theo dõi lối ra

B [i] =

C [i] =

Lối vào theo dõi


A [i] = A [i] + B [i]

T F
A [i] = 0?
Theo dõi lối ra

B [i] =

C [i] =

Lối vào theo dõi


A [i] = A [i] + B [i]

T F
A [i] = 0?
Theo dõi lối ra

B [i] =

C [i] =

Lối vào theo dõi


A [i] = A [i] + B [i]

T F
A [i] = 0?
Theo dõi lối ra

B [i] =

C [i] =

HÌNH 4.9 Dấu vết này thu được bằng cách giả định rằng đoạn chương trình trong Hình 4.8 là
vòng lặp bên trong và cuộn nó bốn lần để xử lý phần được tô bóng trong Hình.
4.8 là đường dẫn khả dĩ.Các lối ra dấu vết tương ứng với việc nhảy ra khỏi đường đi thường xuyên, và các lối vào
theo dấu vết tương ứng với việc quay trở lại dấu vết.
258 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Superblocks
Một trong những nhược điểm lớn của lập lịch theo dõi là các mục nhập và thoát vào
giữa theo dõi gây ra các phức tạp đáng kể yêu cầu trình biên dịch tạo và theo dõi mã
bù và thường gây khó khăn cho việc đánh giá chi phí của mã đó.Superblocksđược hình
thành bởi một quá trình tương tự như được sử dụng cho dấu vết, nhưng, là một dạng
của các khối cơ bản mở rộng, được giới hạn để có một điểm vào duy nhất nhưng cho
phép nhiều lối ra.
Bởi vì siêu khối chỉ có một điểm vào duy nhất, việc thu gọn một siêu khối sẽ dễ
dàng hơn so với việc thu gọn một dấu vết vì chỉ cần xem xét chuyển động mã qua một
lối ra. Trong ví dụ trước đó của chúng tôi, chúng tôi sẽ tạo ra siêu khối không chứa bất
kỳ lối vào nào và do đó, việc di chuyển C sẽ dễ dàng hơn. Hơn nữa, trong các vòng lặp
có một lối ra vòng lặp duy nhất dựa trên số đếm (ví dụ: vòng lặp for không có lối ra
vòng lặp nào khác ngoài điều kiện kết thúc vòng lặp), các siêu khóa kết quả chỉ có một
lối ra cũng như một lối vào. Các khối như vậy sau đó có thể được lên lịch dễ dàng hơn.

Làm thế nào có thể xây dựng một siêu khối chỉ có một lối vào? Câu trả lời
là sử dụngtrùng đuôiđể tạo một khối riêng biệt tương ứng với phần của dấu
vết sau khi nhập. Trong ví dụ của chúng tôi ở trên, mỗi lần mở vòng lặp sẽ
tạo ra một lối ra từ siêu khối đến một vòng lặp dư để xử lý các lần lặp còn lại.
Hình 4.10 cho thấy cấu trúc siêu khối nếu đoạn mã từ Hình 4.8 được coi như
phần thân của một vòng lặp bên trong và được mở bốn lần. Vòng lặp dư xử
lý bất kỳ lần lặp nào xảy ra nếu thoát khỏi superblock, đến lượt nó, xảy ra khi
đường dẫn không được bảo vệ được chọn. Nếu tần số dự kiến của vòng lặp
dư vẫn cao, thì một siêu khối cũng có thể được tạo cho vòng lặp đó.

Phương pháp superblock làm giảm sự phức tạp của việc ghi sổ và lập lịch so với phương
pháp tạo dấu vết tổng quát hơn, nhưng có thể mở rộng kích thước mã hơn phương pháp
dựa trên dấu vết. Giống như lập lịch theo dõi, lập lịch superblock của tôi là thích hợp nhất
khi các kỹ thuật khác (ví dụ: chuyển đổi nếu) không thành công. Ngay cả trong những
trường hợp như vậy, việc đánh giá chi phí sao chép mã có thể hạn chế tính hữu ích của cách
tiếp cận và chắc chắn sẽ làm phức tạp quá trình biên dịch.
Giải nén vòng lặp, liên kết phần mềm, lập lịch theo dõi và lập lịch siêu khối đều
nhằm mục đích cố gắng tăng lượng ILP có thể được khai thác bởi bộ xử lý đưa ra
nhiều lệnh trên mỗi chu kỳ đồng hồ. Hiệu quả của từng kỹ thuật này và tính phù
hợp của chúng đối với các cách tiếp cận kiến trúc khác nhau là một trong những
chủ đề nóng nhất đang được các nhà nghiên cứu và thiết kế bộ xử lý tốc độ cao
tích cực theo đuổi.
4.4 Hỗ trợ trình biên dịch nâng cao để hiển thị và khai thác ILP 259

A [i] = A [i] + B [i]

T F
A [i] = 0?

Lối ra tuyệt vời


với n = 4
B [i] =

C [i] =

A [i] = A [i] + B [i]


F
A [i] = A [i] + B [i]

T
A [i] = 0?
T F
A [i] = 0?
Lối ra tuyệt vời
với n = 3
B [i] =
B [i] = X

C [i] =

C [i] =

A [i] = A [i] + B [i]


Hành hình
n lần

T F
A [i] = 0?

Lối ra tuyệt vời


với n = 2
B [i] =

C [i] =

A [i] = A [i] + B [i]

T F
A [i] = 0?
Lối ra tuyệt vời
với n = 1
B [i] =

C [i] =

HÌNH 4.10 Siêu khối này là kết quả của việc giải mã trong Hình 4.8 bốn lần và tạo ra
một siêu khối.
260 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

4,5Hỗ trợ phần cứng để hiển thị nhiều song


song hơn tại thời gian biên dịch

Có thể sử dụng các kỹ thuật như giải nén vòng lặp, kết nối phần mềm và lập lịch theo
dõi để tăng lượng song song khả dụng khi hành vi của các nhánh khá dễ đoán tại thời
điểm biên dịch. Khi hành vi của các nhánh không được biết rõ, chỉ riêng các kỹ thuật
trình biên dịch có thể không phát hiện ra nhiều ILP. Trong những trường hợp như vậy,
các phụ thuộc điều khiển có thể hạn chế nghiêm trọng số lượng song song có thể
được khai thác. Tương tự, sự phụ thuộc tiềm ẩn giữa các lệnh tham chiếu bộ nhớ có
thể ngăn chặn chuyển động mã làm tăng ILP khả dụng. Phần này giới thiệu một số kỹ
thuật có thể giúp khắc phục những hạn chế như vậy.

Đầu tiên là phần mở rộng của tập lệnh bao gồmcó điều kiệnhoặchướng dẫn dự đoán.
Những hướng dẫn như vậy có thể được sử dụng để loại bỏ các nhánh chuyển đổi sự phụ
thuộc điều khiển thành sự phụ thuộc vào dữ liệu và có khả năng cải thiện hiệu suất. Các
cách tiếp cận như vậy rất hữu ích với các lược đồ chuyên sâu về phần cứng của chương
trước hoặc các cách tiếp cận chuyên sâu về phần mềm được thảo luận trong chương này, vì
trong cả hai trường hợp, dự đoán có thể được sử dụng để loại bỏ các nhánh.
Suy đoán phần cứng với hành vi ngoại lệ cam kết theo thứ tự được bảo toàn bằng
cách phát hiện và nâng cao ngoại lệ chỉ tại thời điểm cam kết khi lệnh không còn mang
tính đầu cơ. Để nâng cao khả năng củatrình biên dịchđể di chuyển mã qua các nhánh
một cách suy đoán, trong khi vẫn bảo toàn hành vi ngoại lệ, chúng tôi xem xét một số
phương pháp khác nhau, bao gồm kiểm tra rõ ràng các ngoại lệ hoặc kỹ thuật để đảm
bảo rằng chỉ những ngoại lệ phát sinh mới được tạo ra.
Cuối cùng, các sơ đồ đầu cơ phần cứng của chương trước đã cung cấp hỗ trợ cho
việc sắp xếp lại các tải và các cửa hàng, bằng cách kiểm tra các xung đột địa chỉ tiềm
ẩn trong thời gian chạy. Để cho phép trình biên dịch sắp xếp lại các tải và lưu trữ khi
nghi ngờ chúng không xung đột, nhưng không thể chắc chắn tuyệt đối, có thể thêm
một cơ chế để kiểm tra các xung đột đó vào phần cứng. Cơ chế này cho phép các cơ
hội bổ sung để suy đoán tham chiếu bộ nhớ.

Hướng dẫn có điều kiện hoặc định trước

Khái niệm đằng sau các lệnh có điều kiện khá đơn giản: Một lệnh đề cập đến một
điều kiện, được đánh giá là một phần của việc thực thi lệnh. Nếu điều kiện là
đúng, lệnh được thực hiện bình thường; nếu điều kiện sai, việc thực thi tiếp tục
như thể lệnh cấm. Nhiều kiến trúc mới hơn bao gồm một số dạng hướng dẫn có
điều kiện. Ví dụ phổ biến nhất của một lệnh như vậy là di chuyển có điều kiện, di
chuyển một giá trị từ thanh ghi này sang thanh ghi khác nếu điều kiện là đúng.
Một lệnh như vậy có thể được sử dụng để loại bỏ hoàn toàn một nhánh trong các
chuỗi mã đơn giản.
4.5 Hỗ trợ phần cứng để hiển thị nhiều song song hơn tại thời gian biên dịch 261

THÍ DỤ Hãy xem xét đoạn mã sau:

nếu (A == 0) {S = T;}

Giả sử rằng đăng kýR1, R2,vàR3giữ các giá trị củaBẰNG,vàT, tương
ứng, hiển thị mã cho câu lệnh này với nhánh và với động thái có điều
kiện.

CÂU TRẢ LỜI Mã đơn giản sử dụng một nhánh cho câu lệnh này là (hãy nhớ rằng chúng tôi
đang giả định các nhánh bình thường chứ không phải bị trễ)

BNEZ R1, L
THÊM BẠN R2, R3, R0
L:
Sử dụng một bước di chuyển có điều kiện chỉ thực hiện di chuyển nếu toán hạng
thứ ba bằng 0, chúng ta có thể thực hiện câu lệnh này trong một lệnh:

CMOVZ R2, R3, R1

Lệnh có điều kiện cho phép chúng ta chuyển đổi sự phụ thuộc điều khiển có
trong chuỗi mã dựa trên nhánh thành sự phụ thuộc vào dữ liệu. (Phép biến
đổi này cũng được sử dụng cho máy tính vectơ, nơi nó được gọi là
ifconversion.) Đối với bộ xử lý pipelined, điều này sẽ di chuyển nơi mà sự
phụ thuộc phải được giải quyết từ gần phía trước của đường ống, nơi nó
được giải quyết cho các nhánh, đến cuối đường ống nơi xảy ra việc ghi
thanh ghi. N

Một cách sử dụng rõ ràng cho việc di chuyển có điều kiện là thực hiện hàm giá
trị tuyệt đối:A = abs (B),được thực hiện nhưif (B <0) {A = -B;) else {A = B;}.Câu lệnh if này
có thể được thực hiện như một cặp động thái có điều kiện hoặc như một động
thái không điều kiện (A = B)và một động thái có điều kiện (A = -B).
Trong ví dụ trên hoặc trong việc biên dịch giá trị tuyệt đối, các bước di chuyển
có điều kiện được sử dụng để thay đổi sự phụ thuộc điều khiển thành sự phụ
thuộc vào dữ liệu. Điều này cho phép chúng tôi loại bỏ nhánh và có thể cải thiện
hành vi của đường ống. Khi tỷ lệ phát hành tăng lên, các nhà thiết kế phải đối mặt
với một trong hai lựa chọn: thực hiện nhiều nhánh trên mỗi chu kỳ đồng hồ hoặc
tìm một phương pháp loại bỏ các nhánh để tránh yêu cầu này. Việc xử lý nhiều
nhánh trên mỗi đồng hồ là phức tạp, vì một nhánh phải được điều khiển phụ
thuộc vào nhánh kia. Khó khăn trong việc dự đoán chính xác hai kết quả nhánh,
cập nhật bảng dự đoán và thực hiện trình tự chính xác, cho đến nay đã khiến hầu
hết các nhà thiết kế tránh các bộ xử lý thực thi nhiều nhánh trên mỗi đồng hồ.
Các bước di chuyển có điều kiện và các hướng dẫn dự đoán cung cấp một cách để
giảm áp suất nhánh. Thêm vao Đoa,
Các bước di chuyển có điều kiện là hình thức đơn giản nhất của các hướng dẫn có điều
kiện hoặc dự đoán, và mặc dù hữu ích cho các chuỗi ngắn, nhưng có những hạn chế. Đặc
biệt, việc sử dụng động thái có điều kiện để loại bỏ các nhánh bảo vệ việc thực thi các khối
mã lớn có thể không hiệu quả, vì nhiều động thái có điều kiện có thể cần được thực hiện.
262 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Để khắc phục sự kém hiệu quả của việc sử dụng các di chuyển có điều kiện,
một số kiến trúc hỗ trợ dự đoán đầy đủ, theo đó việc thực hiện tất cả các lệnh
được điều khiển bởi một vị từ. Khi vị từ là false, lệnh sẽ trở thành no-op. Dự đoán
đầy đủ cho phép chúng ta chuyển đổi các khối mã lớn phụ thuộc vào nhánh một
cách đơn giản. Ví dụ: một câu lệnh if-then-else trong một vòng lặp có thể được
chuyển đổi hoàn toàn thành thực thi dự đoán, để mã trong trường hợp thì thực
thi chỉ khi giá trị của điều kiện là đúng và mã trong trường hợp khác thực thi chỉ
khi giá trị của điều kiện là sai. Dự đoán đặc biệt có giá trị với lập lịch mã toàn cầu,
vì nó có thể loại bỏ các nhánh nonloop, điều này làm phức tạp đáng kể việc lập
lịch lệnh.
Các lệnh định trước cũng có thể được sử dụng để di chuyển một cách phỏng đoán một lệnh quan
trọng về thời gian, nhưng có thể gây ra một ngoại lệ nếu được di chuyển trước một nhánh canh gác. Mặc
dù có thể thực hiện điều này với cách di chuyển có điều kiện, nhưng nó sẽ tốn kém hơn, như chúng ta đã
tìm hiểu trong các bài thực hành.

THÍ DỤ Đây là một chuỗi mã cho một siêu địa chỉ hai vấn đề có thể tạo ra sự kết
hợp của một tham chiếu bộ nhớ và một hoạt động ALU hoặc một nhánh
của chính nó, mỗi chu kỳ:

Vị trí hướng dẫn đầu tiên Khe hướng dẫn thứ hai

LW R1,40 (R2) THÊM R3, R4, R5


THÊM R6, R3, R7
BEQZ R10, L
LW R8,0 (R10)
LW R9,0 (R8)

Trình tự này lãng phí một khe hoạt động bộ nhớ trong chu kỳ thứ hai và sẽ gây ra
sự cố phụ thuộc dữ liệu nếu nhánh không được sử dụng, kể từ chu kỳ thứ haiLW
sau nhánh phụ thuộc vào tải trước. Chỉ ra cách mã có thể được cải thiện bằng
cách sử dụng dạng dự đoán củaLW.

CÂU TRẢ LỜI Gọi từ tải phiên bản dự đoánLWCvà giả sử tải xảy ra trừ khi toán hạng
thứ ba là 0.LWngay sau nhánh có thể được chuyển đổi thànhLWCvà
chuyển lên vùng phát hành thứ hai:

Vị trí hướng dẫn đầu tiên Khe hướng dẫn thứ hai

LW R1,40 (R2) THÊM R3, R4, R5


LWC R8,20 (R10), R10 THÊM R6, R3, R7
BEQZ R10, L
LW R9,0 (R8)
4.5 Hỗ trợ phần cứng để hiển thị nhiều song song hơn tại thời gian biên dịch 263

Điều này giúp cải thiện thời gian thực thi lên một số chu kỳ vì nó loại bỏ một
khe vấn đề về lệnh và giảm tình trạng ngưng trệ đường ống cho lệnh cuối
cùng trong chuỗi. Tất nhiên, nếu trình biên dịch xác định sai nhánh, lệnh dự
đoán sẽ không có hiệu lực và sẽ không cải thiện thời gian chạy. Đây là lý do
tại sao sự chuyển đổi là suy đoán.
Nếu trình tự theo sau nhánh ngắn, toàn bộ khối mã có thể được
chuyển đổi thành thực thi dự đoán và nhánh bị loại bỏ.
N

Khi chúng ta chuyển đổi toàn bộ đoạn mã sang thực thi dự đoán hoặc di
chuyển một cách suy đoán một chỉ dẫn và làm cho nó được dự đoán, chúng ta sẽ
loại bỏ sự phụ thuộc vào điều khiển. Việc tạo mã chính xác và thực thi có điều
kiện các lệnh dự đoán đảm bảo rằng chúng tôi duy trì luồng dữ liệu được thực thi
bởi nhánh. Để đảm bảo rằng hành vi ngoại lệ cũng được duy trì, một lệnh dự
đoán không được tạo ra một ngoại lệ nếu vị từ là sai. Thuộc tính của việc không
gây ra ngoại lệ là khá quan trọng, như Ví dụ trên cho thấy: Nếu đăng kýR10chứa
số không, hướng dẫnLW R8,0 (R10)được thực thi vô điều kiện có khả năng gây ra
ngoại lệ bảo vệ và ngoại lệ này sẽ không xảy ra. Tất nhiên, nếu điều kiện được
thỏa mãn (tức làR10không phải là 0),LWvẫn có thể gây ra ngoại lệ hợp pháp và có
thể tiếp tục lại (ví dụ: lỗi trang) và phần cứng phải thực hiện ngoại lệ khi nó biết
rằng điều kiện kiểm soát là đúng.
Sự phức tạp lớn trong việc thực hiện các hướng dẫn dự đoán là quyết định khi nào nên
hủy bỏ một chỉ dẫn. Các hướng dẫn dành riêng có thể bị hủy bỏ trong quá trình phát hành
lệnh hoặc sau đó trong đường dẫn trước khi chúng cam kết bất kỳ kết quả nào hoặc đưa ra
một ngoại lệ. Mỗi sự lựa chọn đều có một nhược điểm. Nếu các hướng dẫn dự đoán bị hủy
bỏ sớm trong đường dẫn, giá trị của điều kiện kiểm soát phải được biết sớm để ngăn chặn
sự cố do rủi ro dữ liệu. Vì các điều kiện nhánh phụ thuộc vào dữ liệu, có xu hướng ít dự đoán
hơn, là những ứng cử viên để chuyển đổi sang thực thi dự đoán, lựa chọn này có thể dẫn
đến nhiều gian hàng đường ống hơn. Do điều này có thể xảy ra đối với các ngăn chặn nguy
cơ dữ liệu, không có thiết kế nào với việc thực hiện dự đoán (hoặc di chuyển có điều kiện) sẽ
hủy bỏ các hướng dẫn sớm. Thay vào đó, tất cả các bộ xử lý hiện có sẽ hủy bỏ các hướng
dẫn sau này trong đường dẫn, có nghĩa là các hướng dẫn bị hủy bỏ sẽ tiêu tốn tài nguyên
của đơn vị chức năng và có khả năng có tác động tiêu cực đến hiệu suất. Một loạt các kỹ
thuật triển khai đường ống khác, chẳng hạn như chuyển tiếp, tương tác với các hướng dẫn
dự đoán làm phức tạp thêm việc triển khai.

Các hướng dẫn dành riêng hoặc có điều kiện cực kỳ hữu ích để thực hiện các
luồng điều khiển thay thế ngắn, để loại bỏ một số nhánh không thể đoán trước
và để giảm chi phí lập lịch mã toàn cầu. Tuy nhiên, tính hữu dụng của các lệnh có
điều kiện bị giới hạn bởi một số yếu tố:

N Các lệnh dành riêng bị hủy bỏ (tức là có điều kiện sai) vẫn lấy một số tài
nguyên của bộ xử lý. Một lệnh dự đoán bị hủy yêu cầu tối thiểu tìm nạp tài
nguyên và trong hầu hết các bộ xử lý thực thi đơn vị chức năng
264 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

thời gian. Do đó, việc di chuyển một lệnh qua một nhánh và làm cho nó có điều
kiện sẽ làm chậm chương trình bất cứ khi nào lệnh được di chuyển không được
thực thi bình thường. Tương tự như vậy, việc dự đoán một phần mã phụ thuộc điều
khiển và loại bỏ một nhánh có thể làm chậm bộ xử lý nếu mã đó không được thực
thi. Một ngoại lệ quan trọng cho những trường hợp này xảy ra khi các chu kỳ được
sử dụng bởi lệnh đã di chuyển khi nó không được thực hiện dù sao cũng sẽ không
hoạt động (như trong ví dụ siêu phương trên). Di chuyển một lệnh qua một nhánh
hoặc chuyển đổi một đoạn mã sang thực thi dự đoán về cơ bản là suy đoán về kết
quả của nhánh. Các hướng dẫn có điều kiện làm cho việc này dễ dàng hơn nhưng
không loại bỏ thời gian thực hiện do đoán sai. Trong những trường hợp đơn giản,
khi chúng ta giao dịch một nước đi có điều kiện cho một nhánh và một nước đi, sử
dụng di chuyển có điều kiện hoặc dự đoán hầu như luôn tốt hơn. Khi các chuỗi mã
dài hơn được thực hiện có điều kiện, lợi ích sẽ bị hạn chế hơn.

N Các hướng dẫn dành sẵn hữu ích nhất khi vị từ có thể được đánh giá sớm. Nếu
không thể tách biệt được việc đánh giá điều kiện và các hướng dẫn dự đoán (do
phụ thuộc vào dữ liệu trong việc xác định điều kiện), thì một lệnh có điều kiện có
thể dẫn đến việc dừng lại vì một nguy cơ dữ liệu. Với dự đoán và suy đoán nhánh,
có thể tránh được những gian hàng như vậy, ít nhất là khi các nhánh được dự đoán
chính xác.

N Việc sử dụng các lệnh có điều kiện có thể bị hạn chế khi luồng điều khiển
liên quan đến nhiều hơn một trình tự thay thế đơn giản. Ví dụ, việc di
chuyển một lệnh qua nhiều nhánh đòi hỏi phải làm cho nó có điều kiện
đối với cả hai nhánh, điều này yêu cầu hai điều kiện được chỉ định hoặc
yêu cầu các lệnh bổ sung để tính toán vị từ điều khiển. Nếu không có các
khả năng này, chi phí chuyển đổi if sẽ lớn hơn, làm giảm lợi thế của nó.

N Hướng dẫn có điều kiện có thể có một số hình phạt về tốc độ so với hướng dẫn không
điều kiện. Điều này có thể hiển thị dưới dạng số chu kỳ cao hơn cho các hướng dẫn như
vậy hoặc tốc độ xung nhịp nói chung chậm hơn. Nếu các hướng dẫn có điều kiện đắt
hơn, chúng sẽ cần được sử dụng một cách thận trọng.

Vì những lý do này, nhiều kiến trúc đã bao gồm một vài lệnh có điều kiện đơn
giản (với việc di chuyển có điều kiện là thường xuyên nhất), nhưng chỉ một số
kiến trúc bao gồm các phiên bản có điều kiện cho phần lớn các lệnh. MIPS,
Alpha, Power-PC, SPARC và Intel x86 (như được định nghĩa trong bộ xử lý
Pentium) đều hỗ trợ di chuyển có điều kiện. Kiến trúc IA-64 hỗ trợ dự đoán đầy đủ
cho tất cả các hướng dẫn, như chúng ta sẽ thấy phần 4.7.

Đầu cơ trình biên dịch với hỗ trợ phần cứng


Như chúng ta đã thấy trước đó trong chương này, nhiều chương trình có các nhánh có thể được dự
đoán chính xác tại thời điểm biên dịch từ cấu trúc chương trình hoặc bằng cách sử dụng một cấu
hình. Trong những trường hợp như vậy, trình biên dịch có thể muốn suy đoán để cải thiện
4.5 Hỗ trợ phần cứng để hiển thị nhiều song song hơn tại thời gian biên dịch 265

lập lịch hoặc để tăng tỷ lệ phát hành. Các hướng dẫn dành riêng cung cấp một phương pháp
để suy đoán, nhưng chúng thực sự hữu ích hơn khi các phụ thuộc điều khiển có thể được
loại bỏ hoàn toàn bằng chuyển đổi if. Trong nhiều trường hợp, chúng tôi muốn di chuyển
các hướng dẫn đã suy đoán không chỉ trước nhánh, mà trước khi đánh giá điều kiện và dự
đoán không thể đạt được điều này.
Như đã chỉ ra trước đó, để suy đoán một cách tham vọng cần có ba khả năng:

1. khả năng của trình biên dịch để tìm các hướng dẫn, với khả năng sử dụng đổi tên thanh ghi, có
thể được di chuyển một cách phỏng đoán và không ảnh hưởng đến luồng dữ liệu chương
trình,

2. khả năng bỏ qua các ngoại lệ trong các hướng dẫn đã suy đoán, cho đến khi chúng ta biết
rằng các ngoại lệ đó thực sự nên xảy ra, và

3. khả năng hoán đổi các tải và cửa hàng một cách suy đoán, hoặc các cửa hàng và cửa
hàng, có thể có xung đột về địa chỉ.

Cái đầu tiên trong số này là khả năng biên dịch, trong khi hai cái cuối cùng yêu cầu hỗ trợ phần
cứng, chúng ta sẽ khám phá tiếp theo.

Hỗ trợ phần cứng để bảo tồn hành vi ngoại lệ


Để suy đoán một cách tham vọng, chúng ta phải có thể di chuyển bất kỳ loại lệnh nào và vẫn
bảo toàn hành vi ngoại lệ của nó. Chìa khóa để có thể làm được điều này là quan sát rằng
các kết quả của một trình tự suy đoán bị dự đoán sai sẽ không được sử dụng trong tính toán
cuối cùng và một chỉ dẫn được suy đoán như vậy sẽ không gây ra ngoại lệ.

Có bốn phương pháp đã được nghiên cứu để hỗ trợ suy đoán tham
vọng hơn mà không đưa ra hành vi ngoại lệ sai lầm:

1. Phần cứng và hệ điều hành hợp tác bỏ qua các ngoại lệ đối với các hướng dẫn suy đoán. Như chúng ta
sẽ thấy bên dưới, cách tiếp cận này duy trì hành vi ngoại lệ cho các chương trình chính xác, nhưng
không bảo vệ các chương trình không chính xác. Cách tiếp cận này có thể được xem là không thể
chấp nhận được đối với một số chương trình, nhưng nó đã được sử dụng, dưới sự kiểm soát của
chương trình, như một “chế độ nhanh” trong một số bộ xử lý.

2. Các hướng dẫn suy đoán không bao giờ nêu ra ngoại lệ được sử dụng và kiểm tra
được đưa ra để xác định khi nào một ngoại lệ sẽ xảy ra.

3. Tập hợp các bit trạng thái, được gọi làbit độc, được đính kèm với các thanh ghi
kết quả được viết bởi các lệnh được suy đoán khi các lệnh gây ra ngoại lệ. Các
bit độc gây ra lỗi khi một lệnh bình thường cố gắng sử dụng thanh ghi.

4. Một cơ chế được cung cấp để chỉ ra rằng một lệnh là suy đoán và phần
cứng đệm kết quả của lệnh cho đến khi chắc chắn rằng lệnh đó không
còn là suy đoán nữa.
266 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Để giải thích các lược đồ này, chúng ta cần phân biệt giữa các ngoại lệ chỉ ra lỗi chương
trình và thông thường sẽ gây ra kết thúc, chẳng hạn như vi phạm bảo vệ bộ nhớ và những
ngoại lệ được xử lý và tiếp tục bình thường, chẳng hạn như lỗi trang. Các trường hợp ngoại
lệ có thể được tiếp tục lại có thể được chấp nhận và xử lý đối với các hướng dẫn suy đoán
giống như khi chúng là các hướng dẫn bình thường. Nếu lệnh suy đoán lẽ ra không được
thực thi, việc xử lý ngoại lệ không cần thiết có thể có một số tác động tiêu cực đến hiệu suất,
nhưng nó không thể gây ra việc thực thi không chính xác. Tuy nhiên, chi phí của những
ngoại lệ này có thể cao và một số bộ xử lý sử dụng hỗ trợ phần cứng để tránh áp dụng
những ngoại lệ đó, cũng như những bộ xử lý có đầu cơ phần cứng có thể áp dụng một số
ngoại lệ trong chế độ suy đoán, trong khi tránh những ngoại lệ khác cho đến khi một lệnh
được biết là không phải là suy đoán.
Các ngoại lệ chỉ ra lỗi chương trình sẽ không xảy ra trong các chương trình chính xác và kết quả
của một chương trình nhận được ngoại lệ như vậy không được xác định rõ, có lẽ ngoại trừ khi
chương trình đang chạy ở chế độ gỡ lỗi. Nếu các trường hợp ngoại lệ như vậy phát sinh trong các
hướng dẫn được suy đoán, chúng ta không thể coi đó là ngoại lệ cho đến khi chúng ta biết rằng
lệnh đó không còn là suy đoán nữa.
Trong phương pháp đơn giản nhất để bảo toàn các ngoại lệ, phần cứng và hệ điều
hành chỉ cần xử lý tất cả các ngoại lệ có thể tiếp tục khi ngoại lệ xảy ra và chỉ cần trả về
một giá trị không xác định cho bất kỳ ngoại lệ nào sẽ gây ra sự kết thúc. Nếu lệnh tạo
ngoại lệ kết thúc không phải là suy đoán, thì chương trình đang bị lỗi. Lưu ý rằng thay
vì kết thúc chương trình, chương trình được phép tiếp tục, mặc dù nó gần như chắc
chắn sẽ tạo ra kết quả không chính xác. Nếu lệnh tạo ngoại lệ kết thúc là suy đoán, thì
chương trình có thể đúng và kết quả suy đoán sẽ đơn giản là không được sử dụng; do
đó, việc trả về một giá trị không xác định cho lệnh không thể có hại. Lược đồ này
không bao giờ có thể khiến một chương trình chính xác bị lỗi, cho dù có bao nhiêu suy
đoán được thực hiện. Một chương trình không chính xác, mà trước đây có thể đã nhận
được một ngoại lệ kết thúc, sẽ nhận được một kết quả không chính xác. Điều này có
thể chấp nhận được đối với một số chương trình, giả sử trình biên dịch cũng có thể tạo
ra một phiên bản bình thường của chương trình, phiên bản này không suy đoán và có
thể nhận được một ngoại lệ kết thúc.

THÍ DỤ Hãy xem xét đoạn mã sau từ một câu lệnh if-then-else của biểu mẫu

nếu(A == 0) A = B;khácA = A + 4;

ở đâuMộtđang ở0 (R3)vàBđang ở0 (R2):

LD R1,0 (R3) ; tải A


BNEZ R1, L1 ; kiểm tra A
LD R1,0 (R2) ; mệnh đề then
J L2 ; bỏ qua cái khác
L1: DADDI R1, R1, # 4 ; mệnh đề khác
L2: SD 0 (R3), R1 ; cửa hàng A

Giả sử mệnh đề then làgần như luôn luônThực thi. Biên dịch mã bằng cách sử dụng
đầu cơ dựa trên trình biên dịch. Giả địnhR14không được sử dụng và có sẵn.
4.5 Hỗ trợ phần cứng để hiển thị nhiều song song hơn tại thời gian biên dịch 267

CÂU TRẢ LỜI Đây là mã mới:

LD R1,0 (R3) ; tải A


LD R14,0 (R2) ; tải trọng đầu cơ B
BEQZ R1, L3 ; nhánh khác của mệnh đề if;
DADDI R14, R1, # 4 else
L3: SD 0 (R3), R14 ; cửa hàng không tích lũy

Mệnh đề then hoàn toàn được suy đoán. Chúng tôi giới thiệu một sổ đăng
ký tạm thời để tránh phá hủyR1khi nàoBNó đã nạp đầy; nếu tải là suy đoán
R14 sẽ vô dụng. Sau khi toàn bộ đoạn mã được thực thi,Mộtsẽ ởR14.Mệnh
đề else cũng có thể được biên dịch theo kiểu suy đoán với một động thái có
điều kiện, nhưng nếu nhánh có khả năng dự đoán cao và chi phí thấp, thì
điều này có thể làm chậm mã, vì hai lệnh bổ sung sẽ luôn được thực hiện
trái ngược với một nhánh. N

Trong một sơ đồ như vậy, không cần thiết phải biết rằng một chỉ dẫn là suy đoán.
Thật vậy, nó chỉ hữu ích khi một chương trình bị lỗi và nhận được một ngoại lệ kết thúc
trên một lệnh bình thường; trong những trường hợp như vậy, nếu lệnh không được
đánh dấu là suy đoán, chương trình có thể bị chấm dứt.
Trong phương pháp này để xử lý suy đoán, như trong phương pháp tiếp theo,
việc đổi tên thường sẽ cần thiết để ngăn chặn các hướng dẫn suy đoán phá hủy
các giá trị sống. Đổi tên thường bị hạn chế đối với các giá trị đăng ký. Do hạn chế
này, mục tiêu của các cửa hàng không thể bị phá hủy và các cửa hàng không thể
được đầu cơ. Số lượng thanh ghi nhỏ và chi phí tràn sẽ đóng vai trò như một hạn
chế đối với số lượng đầu cơ. Tất nhiên, hạn chế chính vẫn là chi phí thực hiện các
lệnh suy đoán khi dự đoán rẽ nhánh của trình biên dịch không chính xác.

Cách tiếp cận thứ hai để bảo toàn hành vi ngoại lệ khi suy đoán giới thiệu
các phiên bản đầu cơ của hướng dẫn không tạo ra các ngoại lệ kết thúc và
hướng dẫn để kiểm tra các ngoại lệ đó. Sự kết hợp này bảo toàn chính xác
hành vi ngoại lệ.

THÍ DỤ Cho biết cách mã hóa ví dụ trước bằng cách sử dụng tải suy đoán (sLD)
và hướng dẫn kiểm tra đầu cơ (SPECCK)để bảo toàn hoàn toàn hành vi
ngoại lệ. Giả địnhR14không được sử dụng và có sẵn.

CÂU TRẢ LỜI Đây là mã đạt được điều này:

LD R1,0 (R3) ; tải A


sLD R14,0 (R2) ; đầu cơ, không kết thúc; thử
BNEZ R1, L1 nghiệm A
SPECCK 0 (R2) ; thực hiện kiểm tra đầu cơ
268 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

J L2 ; bỏ qua cái khác


L1: DADDI R14, R1, # 4 ; mệnh đề khác
L2: SD 0 (R3), R14 ; cửa hàng A

Lưu ý rằng việc kiểm tra đầu cơ yêu cầu chúng ta duy trì một khối cơ bản cho trường
hợp sau đó. Nếu chúng ta chỉ suy đoán một phần của trường hợp thì, thì một khối cơ
bản đại diện cho trường hợp sau đó sẽ tồn tại trong bất kỳ trường hợp nào. Quan trọng
hơn, hãy lưu ý rằng việc kiểm tra một ngoại lệ có thể xảy ra yêu cầu thêm mã.
N

Cách tiếp cận thứ ba để bảo toàn hành vi ngoại lệ theo dõi các ngoại lệ khi chúng xảy ra
nhưng hoãn lại bất kỳ ngoại lệ kết thúc nào cho đến khi một giá trị thực sự được sử dụng,
bảo toàn sự xuất hiện của ngoại lệ, mặc dù không phải theo cách hoàn toàn chính xác. Lược
đồ rất đơn giản: Một bit độc được thêm vào mọi thanh ghi và một bit khác được thêm vào
mọi lệnh để cho biết liệu lệnh đó có phải là suy đoán hay không. Bit độc của thanh ghi đích
được đặt bất cứ khi nào một lệnh suy đoán dẫn đến một ngoại lệ kết thúc; tất cả các trường
hợp ngoại lệ khác được xử lý ngay lập tức. Nếu một lệnh suy đoán sử dụng một thanh ghi có
bit độc được bật, thì thanh ghi đích của lệnh chỉ đơn giản là bật bit độc của nó. Nếu một lệnh
bình thường cố gắng sử dụng một nguồn đăng ký với bit độc của nó được bật, thì lệnh đó sẽ
gây ra lỗi. Bằng cách này, bất kỳ chương trình nào đã tạo ra một ngoại lệ vẫn tạo ra một
ngoại lệ, mặc dù ở trường hợp đầu tiên, nơi một kết quả được sử dụng bởi một lệnh không
phải là suy đoán. Vì bit độc chỉ tồn tại trên các giá trị thanh ghi chứ không phải giá trị bộ
nhớ, các kho lưu trữ không bao giờ mang tính suy đoán và do đó bẫy nếu một trong hai
toán hạng là “độc”.

THÍ DỤ Hãy xem xét đoạn mã từ trang 267 và cho biết nó sẽ được biên dịch như
thế nào với các hướng dẫn suy đoán và các bit độc. Chỉ ra nơi mà một
ngoại lệ cho tham chiếu bộ nhớ suy đoán sẽ được nhận dạng. Giả sử R14,
không được sử dụng và có sẵn.

CÂU TRẢ LỜI Đây là mã (một ”s” tiếp tục opcode chỉ ra một hướng dẫn suy đoán):

LD R1,0 (R3) ; tải A


sLD R14,0 (R2) ; tải trọng đầu cơ B
BEQZ R1, L3 ;
DADDI R14, R1, # 4 ;
L3: SD 0 (R3), R14 ; ngoại lệ cho LW đầu cơ

Nếu đầu cơsLDtạo ra một ngoại lệ kết thúc, bit độc của R14sẽ được bật.
Khi không tích lũySWlệnh xảy ra, nó sẽ đưa ra một ngoại lệ nếu bit độc
choR14đang bật. N

Một vấn đề phức tạp phải được khắc phục là cách hệ điều hành lưu đăng ký của người
dùng trên một công tắc ngữ cảnh nếu bit độc được đặt. Một hướng dẫn đặc biệt là cần thiết
để lưu và thiết lập lại trạng thái của các bit độc để tránh vấn đề này.
4.5 Hỗ trợ phần cứng để hiển thị nhiều song song hơn tại thời gian biên dịch 269

Cách tiếp cận thứ tư và cuối cùng được liệt kê ở trên dựa trên một cơ chế phần
cứng hoạt động giống như một bộ đệm sắp xếp lại. Trong cách tiếp cận như vậy, các
hướng dẫn được trình biên dịch đánh dấu là suy đoán và bao gồm một chỉ báo về số
nhánh mà hướng dẫn đã được di chuyển qua một cách phỏng đoán và hành động
nhánh nào (được thực hiện / không được thực hiện) mà trình biên dịch giả định. Phần
thông tin cuối cùng này về cơ bản cho phần cứng biết vị trí của khối mã nơi lệnh được
suy đoán ban đầu. Trong thực tế, hầu hết lợi ích của việc đầu cơ có được bằng cách
cho phép di chuyển qua một nhánh duy nhất, và do đó, chỉ cần một bit cho biết liệu
lệnh suy đoán đến từ con đường đã thực hiện hay không được thực hiện là bắt buộc.
Ngoài ra, vị trí ban đầu của lệnh suy đoán được đánh dấu bằnglính gác, điều này cho
phần cứng biết rằng lệnh suy đoán trước đó không còn mang tính suy đoán nữa và
các giá trị có thể được cam kết.
Tất cả các hướng dẫn được đặt trong một bộ đệm sắp xếp lại khi được
ban hành và buộc phải cam kết theo thứ tự, như trong cách tiếp cận đầu
cơ phần cứng. (Lưu ý, mặc dù không có dự đoán nhánh suy đoán thực tế
hoặc lập lịch động nào xảy ra.) Bộ đệm sắp xếp lại theo dõi khi các lệnh
sẵn sàng để cam kết và trì hoãn phần “ghi lại” của bất kỳ lệnh suy đoán
nào. Các hướng dẫn suy đoán không được phép cam kết cho đến khi các
nhánh mà chúng đã được suy đoán chuyển qua cũng đã sẵn sàng để
cam kết, hoặc, cách khác, cho đến khi đạt được điểm giám sát tương
ứng. Tại thời điểm đó, chúng ta biết liệu lệnh được suy đoán có nên được
thực thi hay không. Nếu lẽ ra nó phải được thực thi và nó tạo ra một
ngoại lệ kết thúc, thì chúng ta biết rằng chương trình nên được kết thúc.
Nếu lệnh không được thực thi, thì ngoại lệ có thể được bỏ qua.

Hỗ trợ phần cứng cho đầu cơ tham chiếu bộ nhớ


Di chuyển tải qua các cửa hàng thường được thực hiện khi trình biên dịch chắc chắn rằng
các địa chỉ không xung đột. Như chúng ta đã thấy với các ví dụ trong phần 4.1, các phép
biến đổi như vậy rất quan trọng để giảm độ dài đường dẫn quan trọng của một đoạn mã.
Để cho phép trình biên dịch thực hiện chuyển động mã như vậy, khi không thể chắc chắn
tuyệt đối rằng chuyển động đó là chính xác, một lệnh đặc biệt để kiểm tra xung đột địa chỉ
có thể được đưa vào kiến trúc. Chỉ dẫn đặc biệt được để ở vị trí ban đầu của hướng dẫn tải
(và hoạt động như một người giám hộ) và tải được chuyển lên trên một hoặc nhiều cửa
hàng.
Khi một tải suy đoán được thực thi, phần cứng sẽ lưu địa chỉ của vị trí bộ
nhớ được truy cập. Nếu một cửa hàng tiếp theo thay đổi địa điểm trước khi
hướng dẫn kiểm tra, thì việc suy đoán đã thất bại. Nếu vị trí chưa được chạm
vào thì việc suy đoán đã thành công. Sự thất bại trong đầu cơ có thể được xử
lý theo hai cách. Nếu chỉ có lệnh tải được suy đoán, thì nó đủ để thực hiện lại
tải tại điểm của lệnh kiểm tra (có thể cung cấp thanh ghi đích ngoài địa chỉ
bộ nhớ). Nếu các hướng dẫn bổ sung phụ thuộc vào tải cũng được suy đoán,
thì một trình tự sửa lỗi sẽ thực hiện lại tất cả
270 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

hướng dẫn suy đoán bắt đầu với tải là cần thiết. Trong trường hợp này,
lệnh kiểm tra chỉ định địa chỉ nơi chứa mã sửa lỗi.
Trong phần này, chúng ta đã thấy một loạt các cơ chế hỗ trợ phần cứng. Các cơ chế như vậy là
chìa khóa để đạt được sự hỗ trợ tốt với các phương pháp tiếp cận chuyên sâu của trình biên dịch
của chương này. Ngoài ra, một số trong số chúng có thể được tích hợp dễ dàng trong các phương
pháp tiếp cận chuyên sâu về phần cứng của chương trước và cung cấp các lợi ích bổ sung.

4,6Vấn đề xuyên suốt


Cơ chế đầu cơ phần cứng so với phần mềm
Các phương pháp tiếp cận đầu cơ chuyên sâu về phần cứng trong chương trước và các
phương pháp tiếp cận phần mềm của chương này cung cấp các cách tiếp cận thay thế để
khai thác ILP. Một số sự cân bằng và hạn chế đối với những cách tiếp cận này được liệt kê
dưới đây:

N Để suy đoán rộng rãi, chúng ta phải có khả năng phân định các tham chiếu bộ nhớ. Khả năng
này rất khó thực hiện tại thời điểm biên dịch đối với các chương trình số nguyên có chứa con
trỏ. Trong một lược đồ dựa trên phần cứng, việc phân định địa chỉ bộ nhớ trong thời gian chạy
động được thực hiện bằng cách sử dụng các kỹ thuật mà chúng ta đã thấy trước đó đối với
thuật toán của Tomasulo. Định dạng này cho phép chúng tôi di chuyển tải các cửa hàng trước
đây trong thời gian chạy. Hỗ trợ cho các tham chiếu bộ nhớ suy đoán có thể giúp khắc phục
tính bảo thủ của trình biên dịch, nhưng trừ khi các cách tiếp cận như vậy được sử dụng cẩn
thận, chi phí của các cơ chế khôi phục có thể làm mất đi lợi thế.

N Suy đoán dựa trên phần cứng hoạt động tốt hơn khi luồng điều khiển không thể đoán
trước và khi dự đoán nhánh dựa trên phần cứng vượt trội hơn so với dự đoán nhánh dựa
trên phần mềm được thực hiện tại thời điểm biên dịch. Các thuộc tính này giữ cho nhiều
chương trình số nguyên. Ví dụ: một công cụ dự đoán tĩnh tốt có tỷ lệ dự đoán sai khoảng
16% đối với bốn chương trình SPEC92 số nguyên chính và một công cụ dự đoán phần
cứng có tỷ lệ dự đoán sai dưới 10%. Bởi vì các hướng dẫn được suy đoán có thể làm
chậm quá trình tính toán khi dự đoán không chính xác, sự khác biệt này là đáng kể. Một
kết quả của sự khác biệt này là ngay cả các bộ xử lý được lập lịch tĩnh thường bao gồm
các bộ dự báo nhánh động.

N Suy đoán dựa trên phần cứng duy trì một mô hình ngoại lệ hoàn toàn chính xác ngay cả đối với
các hướng dẫn được suy đoán. Các phương pháp tiếp cận dựa trên phần mềm gần đây đã
thêm hỗ trợ đặc biệt để cho phép điều này.

N Đầu cơ dựa trên phần cứng không yêu cầu bồi thường hoặc mã sổ sách kế toán,
điều này cần thiết bởi các cơ chế đầu cơ phần mềm đầy tham vọng.

N Các phương pháp tiếp cận dựa trên trình biên dịch có thể được hưởng lợi từ khả năng nhìn xa hơn
trong chuỗi mã, dẫn đến việc lập lịch mã tốt hơn so với một phương pháp phần cứng thuần túy
4.7 Kết hợp tất cả lại với nhau: Kiến trúc Intel IA-64 và Bộ xử lý Itanium 271

cách tiếp cận vi.

N Suy đoán dựa trên phần cứng với lập lịch động không yêu cầu các chuỗi mã
khác nhau để đạt được hiệu suất tốt cho các triển khai khác nhau của một kiến
trúc. Mặc dù lợi thế này là khó định lượng nhất, nhưng nó có thể là quan trọng
nhất về lâu dài. Thật thú vị, đây là một trong những động lực cho IBM 360/91.
Mặt khác, các kiến trúc song song rõ ràng gần đây hơn, chẳng hạn như IA-64,
đã bổ sung tính linh hoạt làm giảm sự phụ thuộc vào phần cứng vốn có trong
một chuỗi mã.

Chống lại những lợi thế này là một bất lợi lớn: hỗ trợ đầu cơ trong phần cứng rất phức
tạp và đòi hỏi tài nguyên phần cứng bổ sung. Chi phí phần cứng này phải được đánh
giá dựa trên cả độ phức tạp của một trình biên dịch đối với cách tiếp cận dựa trên
phần mềm và số lượng và tính hữu ích của các đơn giản hóa trong một bộ xử lý dựa
vào một trình biên dịch đó. Chúng tôi trở lại chủ đề này trong phần nhận xét kết luận.

Một số nhà thiết kế đã cố gắng kết hợp các phương pháp tiếp cận dựa trên trình biên
dịch và động để đạt được hiệu quả tốt nhất của mỗi phương pháp. Sự kết hợp như vậy có
thể tạo ra những tương tác thú vị và khó hiểu. Ví dụ, nếu các bước di chuyển có điều kiện
được kết hợp với việc đổi tên thanh ghi, một hiệu ứng phụ tinh tế sẽ xuất hiện. Một động
thái có điều kiện bị hủy bỏ vẫn phải sao chép một giá trị vào thanh ghi đích, vì nó đã được
đổi tên trước đó trong đường dẫn lệnh. Những tương tác tinh vi này làm phức tạp quá trình
thiết kế và xác minh và cũng có thể làm giảm hiệu suất. Ví dụ, trong Alpha 21264, vấn đề này
được khắc phục bằng cách ánh xạ có điều kiện tới hai lệnh trong đường ống.

4,7Kết hợp tất cả lại với nhau: Kiến trúc Intel IA-64 và
Bộ xử lý Itanium

Phần này là tổng quan về kiến trúc Intel IA-64 và cách triển khai ban
đầu, bộ xử lý Itanium

Kiến trúc Bộ lệnh Intel IA-64


IA-64 là tập lệnh thanh ghi kiểu RISC, nhưng có nhiều tính năng mới được thiết kế
để hỗ trợ khai thác ILP dựa trên trình biên dịch. Trọng tâm của chúng tôi ở đây là
về các khía cạnh độc đáo của IA-64 ISA. Hầu hết các khía cạnh này đã được thảo
luận trong chương này, bao gồm dự đoán, phát hiện song song dựa trên trình
biên dịch và hỗ trợ suy đoán tham chiếu bộ nhớ.

Mô hình đăng ký IA-64


Các thành phần của trạng thái thanh ghi IA-64 là:
272 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

N 128 thanh ghi mục đích chung 64 bit, như chúng ta sẽ thấy ngay sau đây thực sự
rộng 65 bit;

N 128 thanh ghi dấu chấm động 82 bit, cung cấp thêm hai bit lũy thừa trên định
dạng IEEE 80 bit tiêu chuẩn,

N 64 thanh ghi vị từ 1 bit,


N 8 thanh ghi nhánh 64 bit, được sử dụng cho các nhánh gián tiếp, và

N nhiều loại thanh ghi được sử dụng để điều khiển hệ thống, ánh xạ bộ nhớ, bộ đếm
hiệu suất và giao tiếp với hệ điều hành.

Các thanh ghi số nguyên được cấu hình để giúp tăng tốc các lệnh gọi thủ tục bằng cách sử
dụng cơ chế ngăn xếp thanh ghi tương tự như cơ chế được phát triển trong bộ xử lý Berkeley RISC-
I và được sử dụng trong kiến trúc SPARC. Các đăng ký 0-31 luôn có thể truy cập được và được đặt
là 0-31. Các thanh ghi 32-128 được sử dụng như một ngăn xếp thanh ghi và mỗi thủ tục được cấp
phát một tập các thanh ghi (từ 0 đến 96) để sử dụng. Khung ngăn xếp thanh ghi mới được tạo cho
một thủ tục được gọi bằng cách đổi tên các thanh ghi trong phần cứng; một thanh ghi đặc biệt
được gọi là con trỏ khung hiện tại (CFM) trỏ đến tập hợp các thanh ghi sẽ được sử dụng bởi một
thủ tục nhất định. Khung bao gồm hai phần: vùng cục bộ và vùng đầu ra. Vùng cục bộ được sử
dụng để lưu trữ cục bộ, trong khi vùng đầu ra được sử dụng để chuyển các giá trị cho bất kỳ thủ
tục nào được gọi. Cáccấp phátchỉ dẫn xác định kích thước của các khu vực này. Chỉ các thanh ghi số
nguyên có hỗ trợ ngăn xếp thanh ghi.

Trong một lệnh gọi thủ tục, con trỏ CFM được cập nhật để R32 của thủ tục
được gọi trỏ đến thanh ghi đầu tiên của vùng đầu ra của thủ tục được gọi. Bản
cập nhật này cho phép các tham số của người gọi được truyền vào các thanh ghi
có thể định địa chỉ của callee. Callee thực hiện mộtcấp phátlệnh cấp phát cả số
lượng thanh ghi cục bộ được yêu cầu, bao gồm các thanh ghi đầu ra của trình gọi
và số lượng thanh ghi đầu ra cần thiết để truyền tham số tới một thủ tục được
gọi. Các hướng dẫn lưu trữ và tải đặc biệt có sẵn để lưu và khôi phục ngăn xếp
thanh ghi cũng như phần cứng đặc biệt (được gọi làđăng ký công cụ ngăn xếp)
xử lý tràn ngăn xếp thanh ghi.
Ngoài các thanh ghi số nguyên, có ba bộ thanh ghi khác: thanh ghi dấu
phẩy động, thanh ghi vị từ và thanh ghi nhánh. Các thanh ghi dấu chấm
động được sử dụng cho dữ liệu dấu chấm động và các thanh ghi nhánh được
sử dụng để giữ các địa chỉ đích nhánh cho các nhánh gián tiếp. Các thanh ghi
dự đoán giữ các vị từ, điều khiển việc thực hiện các lệnh được dự đoán;
chúng tôi sẽ mô tả cơ chế dự đoán sau trong phần này.
Cả thanh ghi số nguyên và dấu phẩy động đều hỗ trợ quay vòng thanh
ghi cho các thanh ghi 32-128. Xoay thanh ghi được thiết kế để dễ dàng thực
hiện nhiệm vụ cấp phát thanh ghi trong các vòng xoay của phần mềm, một
vấn đề mà chúng ta đã thảo luận trong Phần 4.4. Ngoài ra, khi kết hợp với
việc sử dụng dự đoán, có thể tránh được nhu cầu mở cuộn và cho mã phần
mở đầu và phần kết riêng biệt cho một vòng lặp có phần mềm
4.7 Kết hợp tất cả lại với nhau: Kiến trúc Intel IA-64 và Bộ xử lý Itanium 273

kho lưu trữ và làm cho kỹ thuật này có thể sử dụng được cho các vòng lặp với số lần
lặp nhỏ hơn, trong đó chi phí chung theo truyền thống sẽ phủ nhận nhiều lợi thế.

Định dạng hướng dẫn và hỗ trợ song song rõ ràng


Kiến trúc IA-64 được thiết kế để đạt được những lợi ích chính của phương pháp tiếp cận
VLIW – tính song song ngầm định giữa các hoạt động trong một lệnh và định dạng cố định
của các trường hoạt động – trong khi vẫn duy trì tính linh hoạt cao hơn so với VLIW thông
thường cho phép. Sự kết hợp này đạt được bằng cách dựa vào trình biên dịch để phát hiện
ILP và lập lịch các lệnh vào các khe lệnh song song, nhưng tăng thêm tính linh hoạt trong
định dạng lệnh và cho phép trình biên dịch chỉ ra khi nào một lệnh không thể được thực
hiện song song với các lệnh kế nhiệm của nó.
Kiến trúc IA-64 sử dụng hai khái niệm khác nhau để đạt được lợi ích của tính
song song ngầm định và dễ dàng giải mã lệnh. Song song ngầm định đạt được
bằng cách đặt các hướng dẫn vàonhóm hướng dẫn, trong khi định dạng cố định
của nhiều hướng dẫn đạt được thông qua việc giới thiệu một khái niệm được gọi
làbó, trong đó có ba hướng dẫn. Hãy bắt đầu bằng cách xác định một nhóm
hướng dẫn.
Mộtnhóm hướng dẫnlà một chuỗi các lệnh liên tiếp không có phụ thuộc dữ
liệu thanh ghi giữa chúng (có một vài ngoại lệ nhỏ). Tất cả các lệnh trong một
nhóm có thể được thực hiện song song, nếu có đủ tài nguyên phần cứng và nếu
có bất kỳ sự phụ thuộc nào thông qua bộ nhớ được bảo toàn. Một nhóm lệnh có
thể dài tùy ý, nhưng trình biên dịch phảirõ ràngchỉ ra ranh giới giữa nhóm lệnh
này và nhóm lệnh khác. Ranh giới này được chỉ ra bằng cách đặt mộtdừng lạigiữa
hai hướng dẫn thuộc các nhóm khác nhau. Để hiểu cách các điểm dừng được chỉ
ra, trước tiên chúng ta phải giải thích cách các hướng dẫn được đặt thành các gói.

Hướng dẫn IA-64 được mã hóa trongbó,rộng 128 bit. Mỗi gói bao gồm
một trường mẫu năm bit và ba lệnh, mỗi lệnh có độ dài 41 bit. Để đơn
giản là quá trình giải mã và vấn đề lệnh, trường mẫu của một gói chỉ
định loại đơn vị thực thi mà mỗi lệnh trong gói yêu cầu. Hình 4.11 cho
thấy năm loại đơn vị thực thi khác nhau và mô tả chúng có thể chứa
những lớp lệnh nào, cùng với một số ví dụ.
Trường mẫu năm bit trong mỗi gói mô tảcả haisự hiện diện của bất kỳ điểm
dừng nào được liên kết với gói và loại đơn vị thực thi theo yêu cầu của mỗi lệnh
trong gói. Hình 4.12 cho thấy các định dạng có thể có mà trường mẫu mã hóa và
vị trí của bất kỳ điểm dừng nào mà nó chỉ định. Các định dạng gói chỉ có thể chỉ
định một tập hợp con của tất cả các kết hợp có thể có của các loại lệnh và điểm
dừng. Để xem cách gói hoạt động, hãy xem xét một ví dụ.

THÍ DỤ Bỏ cuộn ví dụ về số gia tăng của mảng, x [i] = x [i] + s (được giới thiệu trên trang
223), bảy lần (xem trang 236 để biết mã chưa được cuộn) và đặt các hướng dẫn
thành các gói, trước tiên bỏ qua độ trễ của đường ống (để giảm thiểu con số
274 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Chấp hành Hướng dẫn Hướng dẫn Hướng dẫn ví dụ


Vị trí đơn vị loại hình Sự mô tả

Một Số nguyên ALU cộng, trừ và, hoặc so sánh


I-đơn vị
Tôi Số nguyên không phải ALU thay đổi số nguyên và đa phương tiện, kiểm tra bit, di chuyển

Một Số nguyên ALU cộng, trừ và, hoặc so sánh


Đơn vị M
M Truy cập bộ nhớ Tải và lưu trữ cho thanh ghi số nguyên / FP

Đơn vị F F Dấu chấm động Hướng dẫn dấu chấm động.

Đơn vị B B Chi nhánh Các nhánh có điều kiện, các cuộc gọi, các nhánh lặp

L+X L+X Mở rộng Mở rộng tức thì, dừng và không hoạt động.

HÌNH 4.11 Năm khe đơn vị thực thi trong kiến trúc IA-64 và loại lệnh nào chúng có thể giữ được hiển thị. Các
hướng dẫn loại A, tương ứng với các lệnh ALU số nguyên, có thể được đặt trong vị trí I-unit hoặc M-unit. Các khe cắm L + X
là đặc biệt, vì chúng chiếm hai khe lệnh; Các lệnh L + X được sử dụng để mã hóa các lệnh tức thời 64-bit và một số lệnh đặc
biệt. Các lệnh L + X được thực hiện bởi I-unit hoặc B-unit.

gói) và sau đó lập lịch mã để giảm thiểu gian hàng. Trong lập lịch mã, giả sử
1 gói thực thi trên mỗi đồng hồ và bất kỳ sự cố nào cũng khiến toàn bộ gói
bị đình trệ. Sử dụng độ trễ đường ống từ Hình 4.1 trên trang 222. Sử dụng
thuật ngữ hướng dẫn MIPS để đơn giản hóa.

CÂU TRẢ LỜI Hai phiên bản khác nhau được thể hiện trong Hình 4.13. Mặc dù độ trễ khác với
các độ trễ trong Itanium, nhưng gói phổ biến nhất, MMF, phải được phát hành
bởi chính Itanium, giống như ví dụ của chúng tôi giả định. N

Kiến thức cơ bản về bộ hướng dẫn

Trước khi chuyển sang hỗ trợ đặc biệt cho suy đoán, chúng ta thảo luận
ngắn gọn về các mã hóa lệnh chính và khảo sát các lệnh trong mỗi lớp
trong số năm lớp lệnh chính (A, I, M, F và B). Mỗi lệnh IA-64 có độ dài 41
bit. Bốn bit bậc cao, cùng với các bit gói chỉ định khe đơn vị thực thi, được
sử dụng làm opcode chính. (Có nghĩa là, trường opcode bốn bit được sử
dụng lại trên các khe trường thực thi và thích hợp để coi opcode là 4 bit +
ký hiệu M, F, I, B, L + X.) sáu bit của mọi lệnh được sử dụng để chỉ định
thanh ghi vị từ bảo vệ lệnh (xem phần tiếp theo).

Hình 4.14 tóm tắt hầu hết các định dạng lệnh chính, ngoài các lệnh đa
phương tiện, và đưa ra các ví dụ về các lệnh được mã hóa cho mỗi định dạng.

Dự đoán và Hỗ trợ đầu cơ


Kiến trúc IA-64 cung cấp hỗ trợ toàn diện cho việc dự đoán: gần như mọi
lệnh trong kiến trúc IA-64 đều có thể được dự đoán. Một chỉ dẫn là
4.7 Kết hợp tất cả lại với nhau: Kiến trúc Intel IA-64 và Bộ xử lý Itanium 275

Mẫu Khe 0 Vị trí 1 Vị trí 2

0 M Tôi Tôi
1 M Tôi Tôi
2 M Tôi Tôi
3 M Tôi Tôi
4 M L X
5 M L X
số 8 M M Tôi
9 M M Tôi
10 M M Tôi
11 M M Tôi
12 M F Tôi
13 M F Tôi
14 M M F
15 M M F
16 M Tôi B
17 M Tôi B
18 M B B
19 M B B
22 B B B
23 B B B
24 M M B
25 M M B
28 M F B
29 M F B
HÌNH 4.12 24 giá trị mẫu có thể có (8 giá trị có thể được bảo lưu) và các vị trí và điểm
dừng hướng dẫn được hiển thị cho mỗi định dạng. Các điểm dừng được biểu thị bằng
các dòng đậm và có thể xuất hiệntrong và / hoặcở cuối bó. Ví dụ: mẫu 9 chỉ định rằng các vị
trí lệnh là M, M và I (theo thứ tự đó) và điểm dừng duy nhất là giữa gói này và gói tiếp theo.
Mẫu 11 có cùng loại khe hướng dẫn nhưng cũng bao gồm một điểm dừng sau khe đầu tiên.
Định dạng L + X được sử dụng khi vùng 1 là L và vùng 2 là X.

được xác định bởi một thanh ghi vị từ chỉ định, mà danh tính của nó được đặt
trong sáu bit thấp hơn của mỗi trường lệnh. Bởi vì gần như tất cả các hướng dẫn
đều có thể dự đoán được, cả chuyển đổi if và chuyển động mã đều có chi phí thấp
hơn so với chỉ hỗ trợ hạn chế cho các lệnh có điều kiện. Một hệ quả của vị từ đầy
đủ là một nhánh có điều kiện chỉ đơn giản là một nhánh có một vị từ bảo vệ!
276 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Bó Khe 0 Vị trí 1 Vị trí 2 Thực hiện chu kỳ


mẫu (1 gói / chu kỳ)

9: MMI LD F0,0 (R1) LD F6, -8 (R1) 1

14: MMF LD F10, -16 (R1) LD F14, -24 (R1) ADD.D F4, F0, F2 3

15: MMF LD F18, -32 (R1) LD F22, -40 (R1) ADD.D F8, F6, F2 4

15: MMF LD F26, -48 (R1) SD F4,0 (R1) ADD.D F12, F10, F2 6

15: MMF SD F8, -8 (R1) SD F12, -16 (R1) ADD.D F16, F14, F2 9

15: MMF SD F16, -24 (R1) ADD.D F20, F18, F2 12

15: MMF SD F20, -32 (R1) ADD.D F24, F22, F2 15


15: MMF SD F24, -40 (R1) ADD.D F28, F26, F2 18
12: MMF SD F28, -48 (R1) DADDUI R1, R1, # - 56 BNE R1, R2, Vòng lặp 21

một. Mã được lập lịch để giảm thiểu số lượng gói.

Bó Khe 0 Vị trí 1 Vị trí 2 Thực hiện chu kỳ


mẫu (1 gói / chu kỳ)

8: MMI LD F0,0 (R1) LD F6, -8 (R1) 1

9: MMI LD F10, -16 (R1) LD F14, -24 (R1) 2

14: MMF LD F18, -32 (R1) LD F22, -40 (R1) ADD.D F4, F0, F2 3

14: MMF LD F26, -48 (R1) ADD.D F8, F6, F2 4

15: MMF ADD.D F12, F10, F2 5

14: MMF SD F4,0 (R1) ADD.D F16, F14, F2 6

14: MMF SD F8, -8 (R1) ADD.D F20, F18, F2 7


15: MMF SD F12, -16 (R1) ADD.D F24, F22, F2 số 8
14: MMF SD F16, -24 (R1) ADD.D F28, F26, F2 9

9: MMI SD F20, -32 (R1) SD F24, -40 (R1) 10

8: MMI SD F28, -48 (R1) DADDUI R1, R1, # - 56 BNE R1, R2, Vòng lặp 11

b. Mã được lập lịch để giảm thiểu số chu kỳ giả sử một gói được thực thi trên mỗi chu kỳ.

HÌNH 4.13 Các lệnh IA-64, bao gồm các bit gói và các điểm dừng, cho phiên bản chưa được cuộn của x [i] = x [i] + s,
khi được mở bảy lần và được lập lịch (a) để giảm thiểu số lượng gói lệnh và (b ) để giảm thiểu số chu kỳ (giả sử rằng
một mối nguy hiểm ngăn chặn toàn bộ gói).Các mục nhập trống cho biết các vị trí không sử dụng, được mã hóa dưới
dạng không hoạt động. Việc không có điểm dừng chỉ ra rằng một số gói có thể được thực hiện song song. Giảm thiểu số
lượng bó sẽ tạo ra 9 bó so với 11 cần thiết để giảm thiểu số chu kỳ. Phiên bản đã lên lịch thực thi chỉ trong hơn một nửa số
chu kỳ. Phiên bản (a) lấp đầy 85% vị trí hướng dẫn, trong khi (b) lấp đầy 70%. Số lượng vị trí trống trong mã đã lên lịch và
việc sử dụng các gói có thể dẫn đến kích thước mã lớn hơn nhiều so với các kiến trúc RISC khác.
4.7 Kết hợp tất cả lại với nhau: Kiến trúc Intel IA-64 và Bộ xử lý Itanium 277

Hướng dẫn # Tiêu biểu Thêm GPR / Miễn dịch Nhận xét khác
loại hình định dạng hướng dẫn opcode FPR chút ít

chút ít

cộng, trừ và, hoặc 9 3 0


sang trái và thêm 7 3 0 Đếm dịch chuyển 2 bit

ALU lập tức 9 2 số 8


Thêm ngay lập tức 3 2 14
Một số 8
Thêm ngay lập tức 0 2 22
So sánh 4 2 0 2 thanh ghi vị ngữ
các điểm đến

So sánh ngay lập tức 3 1 số 8 2 thanh ghi vị ngữ


các điểm đến

Shift R / L biến 9 3 0 Nhiều đa phương tiện


hướng dẫn sử dụng cái này
định dạng

Kiểm tra bit 6 3 Trường 6 bit 2 thanh ghi vị ngữ


Tôi 29 người chỉ định các điểm đến

Di chuyển đến BR 6 1 9-bit đăng ký chi nhánh


chi nhánh người chỉ định

dự đoán

Tải và lưu trữ số nguyên / FP, Tìm 10 2 0 Đầu cơ / không


nạp trước dòng đầu cơ
Số nguyên / FP tải / lưu trữ, 9 2 số 8 Đầu cơ / không
và tìm nạp trước dòng & đầu cơ
xác định vị trí ngay lập tức

M 46 Tìm nạp trước số nguyên / 10 3 Đầu cơ / không


FP tải và vị trí đăng ký đầu cơ
Suy đoán số nguyên / FP 3 1 21 trong hai
kiểm tra lĩnh vực

Nhánh PC-họ hàng, 7 0 21


B 9 chi nhánh đếm
Cuộc gọi liên quan đến máy tính 4 0 21 1 chi nhánh đăng ký

Số học FP 2 4
F 15 So sánh FP 2 2 2 vị từ 6 bit regs
L+X 4 Di chuyển ngay lập tức lâu dài 2 1 64
HÌNH 4.14 Trình bày tóm tắt một số định dạng lệnh của IA-64 ISA.Các bit opcode chính và trình xác định thanh ghi dự
đoán bảo vệ thêm 10 bit vào mỗi lệnh. Số lượng định dạng được chỉ ra cho mỗi lớp lệnh trong cột thứ hai (tổng số 111) là
một cách diễn giải chặt chẽ: khi một trường sử dụng khác nhau, thậm chí có cùng kích thước, được coi là một định dạng
khác. Số lượng định dạng thực sự cócác kích thước trường khác nhaulớn bằng một phần ba đến một nửa. Các bit tức
thời bao gồm bit dấu. Các lệnh rẽ nhánh bao gồm các bit dự đoán, được sử dụng khi bộ dự đoán không có một dự đoán
hợp lệ. Không có định dạng nào trong số nhiều định dạng cho các hướng dẫn đa phương tiện được hiển thị trong bảng
này.
278 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Thanh ghi vị ngữ được thiết lập bằng cách sử dụng hướng dẫn so sánh hoặc
kiểm tra. Lệnh so sánh chỉ định một trong mười phép thử so sánh khác nhau và
hai thanh ghi vị từ làm đích. Hai thanh ghi vị từ được viết bằng kết quả của phép
so sánh (0 hoặc 1) và phần bù hoặc bằng một số hàm logic kết hợp hai phép thử
(chẳng hạn nhưvà)và phần bổ sung. Khả năng này cho phép thực hiện nhiều
phép so sánh trong một lệnh.
Hỗ trợ suy đoán trong kiến trúc IA-64 bao gồm hỗ trợ riêng cho suy
đoán điều khiển, hỗ trợ ngoại lệ trì hoãn cho các lệnh được suy đoán và
suy đoán tham chiếu bộ nhớ, hỗ trợ suy đoán các lệnh tải.

Xử lý ngoại lệ hoãn lại cho các lệnh suy đoán được hỗ trợ bằng cách cung cấp các
bit độc tương đương. Đối với GPR, các bit này được gọi là NaT cho Not a Thing và bit
bổ sung này làm cho GPR có độ rộng 65 bit một cách hiệu quả. Đối với các thanh ghi
FP, khả năng này có được bằng cách sử dụng một giá trị đặc biệt, NaTVal, cho Giá trị
Không phải Điều; giá trị này được mã hóa bằng số 0 và số mũ nằm ngoài phạm vi IEEE.
Chỉ các lệnh tải suy đoán mới tạo ra các giá trị như vậy, nhưng tất cả các lệnh không
ảnh hưởng đến bộ nhớ sẽ khiến NaT hoặc NatVal được truyền vào thanh ghi kết quả.
(Có cả tải suy đoán và tải không tích lũy; tải sau chỉ có thể nâng cao các ngoại lệ ngay
lập tức và không thể trì hoãn chúng.) Các ngoại lệ dấu chấm động không được xử lý
thông qua cơ chế này, nhưng sử dụng thanh ghi trạng thái dấu chấm động để ghi lại
các ngoại lệ.
Một ngoại lệ hoãn lại có thể được giải quyết theo hai cách khác nhau. Đầu tiên, nếu một
lệnh không tích lũy, chẳng hạn như một cửa hàng, nhận NaT hoặc NaTVal làm toán hạng
nguồn, thì nó sẽ tạo ra một ngoại lệ ngay lập tức và không thể khôi phục. Ngoài ra, một
chk.shướng dẫn có thể được sử dụng để phát hiện sự hiện diện của NaT hoặc NatVal và rẽ
nhánh tới một quy trình do trình biên dịch thiết kế để khôi phục từ hoạt động suy đoán.
Cách tiếp cận phục hồi như vậy có ý nghĩa hơn đối với việc suy đoán tham chiếu bộ nhớ.
Không có khả năng lưu trữ nội dung của các hướng dẫn với NaT hoặc NatVal
set sẽ khiến HĐH không thể lưu trạng thái của bộ xử lý. Do đó, IA-64 bao gồm các
lệnh đặc biệt để lưu và khôi phục các thanh ghi không gây ra ngoại lệ cho NaT
hoặc NaTVal và cũng lưu và khôi phục các bit NaT.
Hỗ trợ tham chiếu bộ nhớ trong IA-64 sử dụng khái niệm được gọi là tải nâng cao.
Mộttải nâng caolà một tải đã được di chuyển một cách phỏng đoán phía trên hướng
dẫn cửa hàng mà nó có khả năng phụ thuộc vào. Để thực hiện một cách suy đoán tải,
ld.a (cho tải nâng cao) hướng dẫn được sử dụng. Việc thực thi lệnh này sẽ tạo ra một
mục nhập trong một bảng đặc biệt, được gọi làALAT. ALAT lưu trữ cả đích đăng ký của
tải và địa chỉ của vị trí bộ nhớ được truy cập. Khi một cửa hàng được thực thi, một tra
cứu liên quan đối với các mục nhập ALAT đang hoạt động được thực hiện. Nếu có một
mục nhập ALAT có cùng địa chỉ bộ nhớ với cửa hàng, mục nhập ALAT được đánh dấu là
không hợp lệ.
Trước khi bất kỳ lệnh không tích lũy nào (tức là một cửa hàng) sử dụng giá trị
được tạo bởi tải nâng cao hoặc giá trị có được từ kết quả của tải nâng cao, cần
phải kiểm tra rõ ràng. Việc kiểm tra chỉ định đăng ký đích của tải nâng cao. Nếu
ALAT cho sổ đăng ký đó vẫn còn hiệu lực, suy đoán là hợp pháp
4.7 Kết hợp tất cả lại với nhau: Kiến trúc Intel IA-64 và Bộ xử lý Itanium 279

và tác dụng duy nhất của việc kiểm tra là xóa mục nhập ALAT. Nếu séc không thành
công, hành động được thực hiện phụ thuộc vào việc sử dụng loại séc nào trong hai
loại séc khác nhau. Loại kiểm tra đầu tiên là một hướng dẫnld.c,mà chỉ đơn giản là
khiến dữ liệu được tải lại từ bộ nhớ tại thời điểm đó. Mộtld.chướng dẫn được sử dụng
khichỉ cótải được nâng cao. Hình thức thay thế của séc,chk.a,chỉ định địa chỉ của một
quy trình sửa chữa được sử dụng để thực hiện lại tảivà bất kỳ khácmã suy đoán phụ
thuộc vào giá trị của tải.

Bộ xử lý Itanium
Bộ xử lý Itanium là sự triển khai đầu tiên của kiến trúc IA-64. Nó được cung cấp vào
giữa năm 2001 với xung nhịp 800 MHz. Lõi bộ xử lý có khả năng xử lý tối đa sáu vấn đề
trên mỗi xung nhịp, với tối đa ba nhánh và hai tham chiếu bộ nhớ. Hệ thống phân cấp
bộ nhớ bao gồm một bộ đệm ba cấp. Cấp độ đầu tiên sử dụng lệnh phân tách và bộ
nhớ đệm dữ liệu; dữ liệu dấu chấm động không được đặt trong bộ nhớ cache cấp đầu
tiên. Mức thứ hai và thứ ba là bộ nhớ đệm thống nhất, với mức thứ ba là bộ nhớ đệm
4MB ngoài chip được đặt trong cùng một vùng chứa với khuôn Itanium.

Các đơn vị chức năng và vấn đề hướng dẫn


Có chín đơn vị chức năng trong bộ xử lý Itanium: 2 đơn vị I, 2 đơn vị M, 3 đơn vị B và 2
đơn vị F. Tất cả các đơn vị chức năng là pipelined. Hình 4.15 đưa ra độ trễ của đường
ống đối với một số hướng dẫn điển hình. Ngoài ra, khi một kết quả bị bỏ qua từ đơn vị
này sang đơn vị khác, thường có thêm ít nhất một chu kỳ trễ bổ sung.

Hướng dẫn Độ trễ

Tải số nguyên 1
Tải trọng dấu chấm động 9
Đã dự đoán chính xác nhánh đã lấy 0-3
Chi nhánh bị sai lệch 9
Phép toán ALU số nguyên 0
Số học FP 4
HÌNH 4.15 Độ trễ của một số lệnh điển hình trên Itanium.Độ trễ được định nghĩa là số lượng
lệnh can thiệp nhỏ nhất giữa hai lệnh phụ thuộc. Độ trễ tải số nguyên giả định một lần truy cập
trong bộ nhớ cache cấp đầu tiên. FP tải luôn bỏ qua bộ đệm chính, vì vậy độ trễ là cho đến khi có
lần truy cập trong bộ đệm cấp hai. Có một số hạn chế nhỏ đối với một số đơn vị chức năng, nhưng
những hạn chế này chủ yếu liên quan đến việc thực hiện các hướng dẫn không thường xuyên.
280 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Itanium có một cửa sổ vấn đề hướng dẫn chứa tối đa hai gói tại bất kỳ thời điểm
nào. Với kích thước cửa sổ này, Itanium có thể đưa ra tối đa sáu lệnh trong một đồng
hồ. Trong trường hợp xấu nhất, nếu một gói bị tách ra khi nó được phát hành, phần
cứng có thể thấy ít nhất bốn hướng dẫn: một từ gói đầu tiên sẽ được thực thi và ba từ
gói thứ hai. Các hướng dẫn được phân bổ cho các đơn vị chức năng dựa trên các bit
gói, bỏ qua sự hiện diện của các lệnh no-ops hoặc các lệnh được dự đoán với các vị từ
không đúng sự thật. Ngoài ra, khi phát hành cho một đơn vị chức năng bị chặn, vì lệnh
tiếp theo được phát hành cần một đơn vị đã được cam kết, gói kết quả sẽ được tách ra.
Một gói đã tách vẫn chiếm một trong hai vị trí gói, ngay cả khi nó chỉ còn lại một lệnh.
Thêm vao Đoa, có một số hạn chế phụ thuộc vào Itanium khiến một gói bị tách ra và
gây ra sự cố dừng. Ví dụ: một gói MMF, chứa hai lệnh kiểu bộ nhớ và một lệnh kiểu
dấu phẩy động, luôn tạo ra một phần tách trước gói này và sau gói này. Hạn chế vấn
đề này có nghĩa là một chuỗi các gói MMF (giống như trong ví dụ trước đó của chúng
tôi được hiển thị trong 4.13 trên trang 276) có thể thực thi tối đa ba lệnh trên mỗi
đồng hồ, ngay cả khi không có phụ thuộc dữ liệu nào và không xảy ra bỏ lỡ bộ nhớ
cache.

Bộ xử lý Itanium sử dụng một đường ống 10 giai đoạn được chia thành bốn phần chính:

N Front-end (các giai đoạn IPG, Tìm nạp và Xoay): tìm nạp trước lên đến 32 byte mỗi đồng hồ (2
gói) vào bộ đệm tìm nạp trước, có thể chứa tối đa tám gói (24 lệnh). Dự đoán nhánh được thực
hiện bằng cách sử dụng một công cụ dự đoán thích ứng đa cấp giống như trong vi kiến trúc
P6 mà chúng ta đã thấy trong Chương 3.

N Phân phối lệnh (các giai đoạn EXP và REN): phân phối tối đa sáu lệnh cho chín
đơn vị chức năng. Thực hiện các thanh ghi đổi tên cho cả quay và xếp chồng
thanh ghi.

N Phân phối toán hạng (WLD và REG): truy cập tệp đăng ký, thực hiện bỏ qua đăng ký, truy
cập và cập nhật bảng điểm đăng ký, và kiểm tra các phụ thuộc vị từ. Bảng điểm được sử
dụng để phát hiện khi nào các hướng dẫn riêng lẻ có thể tiếp tục, do đó, một lệnh dừng
của một hướng dẫn trong một gói không cần thiết khiến toàn bộ gói bị đình trệ. (Như
chúng ta đã thấy trong Hình 4.13 trên trang 276, việc dừng toàn bộ gói sẽ dẫn đến hiệu
suất kém trừ khi các hướng dẫn được lên lịch cẩn thận.)

N Thực thi (EXE, DET và WRB): thực hiện các hướng dẫn thông qua ALU và tải / lưu trữ
các đơn vị, phát hiện các ngoại lệ và đăng các NaT, gỡ bỏ các hướng dẫn và thực
hiện ghi lại.

Đáng chú ý, Itanium có nhiều tính năng thường được liên kết với các đường
ống được lập lịch động được mô tả trong chương cuối: nhấn mạnh mạnh mẽ vào
dự đoán nhánh, đổi tên thanh ghi, bảng điểm, một đường ống dẫn sâu với nhiều
giai đoạn trước khi thực hiện (để xử lý căn chỉnh lệnh, đổi tên , v.v.), và một số giai
đoạn sau khi thực hiện để xử lý phát hiện ngoại lệ. Có phần ngạc nhiên khi một
cách tiếp cận có mục tiêu là dựa vào công nghệ trình biên dịch-
4.7 Kết hợp tất cả lại với nhau: Kiến trúc Intel IA-64 và Bộ xử lý Itanium 281

ogy và phần cứng đơn giản hơn dường như ít nhất là phức tạp như các bộ xử lý được lập lịch
động mà chúng ta đã thấy trong chương trước!

Hiệu suất Itanium


Hình 4.16 cho thấy hiệu suất của Itanium 800 MHz so với 1 GHz Alpha 21264
và Pentium 4 2 GHz cho SPECint. Itanium chỉ bằng khoảng 60% hiệu suất của
Pentium 4 và 68% hiệu suất của Alpha 21264. Điều có lẽ còn đáng ngạc nhiên
hơn là ngay cả khi chúng ta chuẩn hóa tốc độ xung nhịp, Itanium vẫn chỉ
bằng khoảng 85% của hiệu suất của Alpha 21264, một thiết kế cũ hơn trong
công nghệ cũ hơn với mức tiêu thụ điện năng ít hơn khoảng 20%, mặc dù tốc
độ xung nhịp cao hơn!

SPECint_base2000

t wo lf

bzip2

vo rt ex

khoảng cách

perlbmk

Alpha 21264
eon Pentium 4
Itanium

phân tích cú pháp

xảo trá

mc f

gcc

vpr

gzip

0 100 200 300 400 500 600 700 800 900

SPECint_base2000 màn biểu diễn

HÌNH 4.16 Bộ điểm chuẩn SPECint cho thấy Itanium chậm hơn đáng kể so với Alp-ha 21264 hoặc Pentium 4.Hệ thống
Itanium là máy chủ Hewlett Packard rx4610 với Itanium 800MHz và bộ đệm ẩn 4 MB, bộ nhớ đệm cấp 3. Hệ thống Alpha là
Compaq Alphaserver GS320 1 GHz chỉ có bộ nhớ đệm L2 trên chip. Hệ thống Pentium 4 là máy trạm Compaq Precision 330
với phần 2 GHz với bộ nhớ đệm L2 256KB trên chip. Số tổng thể SPECint_base 2000 được tính là giá trị trung bình hình học
của các tỷ lệ riêng lẻ.
282 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Các điểm chuẩn của SPECfp cho thấy một câu chuyện khác, như chúng ta có thể thấy
trong Hình 4.17. Nhìn chung, bộ vi xử lý Itanium nhanh hơn 1,08 lần so với Pentium 4 và
nhanh hơn khoảng 1,20 lần so với Alpha 21264, với tốc độ xung nhịp cao chỉ từ 40% đến
80%. Đối với các ứng dụng dấu phẩy động, Itanium trông giống như một bộ xử lý rất cạnh
tranh. Như chúng ta đã thấy trong Chương 3, điểm chuẩn dấu chấm động khai thác tốt mức
độ ILP cao hơn và cũng có thể sử dụng hiệu quả hệ thống bộ nhớ tích cực, bao gồm bộ nhớ
đệm L3 lớn. Cả hai yếu tố này có thể đóng một vai trò nào đó.

SPECfp_base2000

apsi

giá đỡ si xt

fma3d

lucas

ammp

facerec

đánh đồng

Mỹ thuật

galgel

mesa

applu

mgrid Alpha 21264


Pentium 4
bơi Itanium

ngược chiều

0 500 1000 1500 2000 2500

HÌNH 4.17 Bộ điểm chuẩn SPECfp cho thấy Itanium nhanh hơn một chút so với Alpha 21264 hoặc Pentium 4.Hệ
thống Itanium là máy chủ Hewlett Packard rx4610 với một bộ xử lý Itanium 800 MHz được kích hoạt và bộ nhớ đệm cấp 3
ngoài chip 4MB. Hệ thống Alpha là Compaq Alphaserver GS320 với 1 GHz Alpha 212164. Hệ thống Pentium 4 là máy trạm
Compaq Precision 330 với phần 2 GHz và giống như hệ thống Alpha chỉ có bộ nhớ đệm L2 cấp trên chip. Số tổng thể
SPECfp_base 2000 được tính là giá trị trung bình hình học của các tỷ lệ riêng lẻ.

Có hai khía cạnh bất thường của các phép đo hiệu suất SPECfp. Đầu tiên,
Itanium có được lợi thế về hiệu suất so với Pentium 4 chủ yếu nhờ vào sức
mạnh hiệu suất của nó trên một tiêu chuẩn: “nghệ thuật”, nhanh hơn gấp 4
lần so với Pentium 4. Nếu loại bỏ tiêu chuẩn “nghệ thuật”, thì Pentium 4 sẽ
tốt hơn Itanium cho SPECfp. Các khía cạnh bất thường khác của
4.8 Góc nhìn khác: ILP trong Thị trường Nhúng và Di động 283

dữ liệu hiệu suất này là bộ xử lý Alpha cho thấy khoảng cách lớn gần 30% giữa
hiệu suất được điều chỉnh và hiệu suất cơ bản đối với SPECfp. Điều này so sánh
với khoảng cách giữa cơ sở và đỉnh đối với hệ thống Itanium là 0% và đối với hệ
thống Pentium 4 là 3%. Nhìn vào các cờ điểm chuẩn cụ thể cho hệ thống Alpha,
chủ yếu mô tả tối ưu hóa giải nén vòng lặp, có vẻ như sự khác biệt này là do trình
biên dịch chưa trưởng thành cho hệ thống Alpha. Nếu hiệu suất cơ bản có thể đạt
đến 95% hiệu suất cao nhất, hệ thống Alpha sẽ có xếp hạng SPECfp cao nhất
trong số ba bộ vi xử lý này.
Như chúng tôi đã đề cập trong chương trước, nguồn điện có thể là trở
ngại khó khăn nhất đối với các bộ xử lý tương lai và trong việc đạt được
các mục tiêu hiệu suất của chúng. . Dữ liệu SPECFP xác nhận quan điểm
này. Mặc dù Itanium đạt được hiệu suất dấu phẩy động tốt hơn Alpha
21264 hoặc Pentium 4, nhưng hiệu suất dấu phẩy động trên mỗi watt
của nó không tốt hơn Alpha 21264 và chỉ bằng 56% của Pentium 4!

4.8Một góc nhìn khác: ILP trong Thị trường Nhúng và Thị trường Di
động

Các chip Trimedia và Crusoe đại diện cho các cách tiếp cận thú vị để áp dụng các
khái niệm VLIW trong không gian nhúng. CPU Trimedia có lẽ là bộ xử lý hiện tại
gần nhất với bộ xử lý VLIW “cổ điển”; nó cũng hỗ trợ một cơ chế nén các lệnh khi
chúng nằm trong bộ nhớ chính và bộ đệm ẩn lệnh và giải nén chúng trong quá
trình tìm nạp lệnh. Cách tiếp cận này giải quyết các nhược điểm về kích thước mã
của bộ xử lý VLIW, điều này sẽ đặc biệt rắc rối trong không gian nhúng. Ngược
lại, bộ xử lý Crusoe sử dụng bản dịch phần mềm từ kiến trúc x86 sang bộ xử lý
VLIW, đạt được mức tiêu thụ điện năng thấp hơn bộ vi xử lý x86 điển hình, đây là
chìa khóa cho thị trường mục tiêu của Crusoe - các ứng dụng di động.

Kiến trúc Trimedia TM32


CPU Trimedia TM32 là một kiến trúc VLIW cổ điển: mỗi lệnh chứa năm hoạt
động và bộ xử lý hoàn toàn được lập lịch tĩnh. Đặc biệt, trình biên dịch có
trách nhiệm bao gồm rõ ràng các lệnh cấm cả trong một lệnh - khi trường
thao tác không thể được sử dụng - và giữa các lệnh phụ thuộc. Bộ xử lý
không phát hiện ra các mối nguy, nếu có sẽ dẫn đến việc thực thi không
chính xác. Để giảm chi phí của các lệnh cấm rõ ràng về kích thước mã, bộ xử
lý Trimedia nén dòng mã cho đến khi các lệnh được tìm nạp từ bộ đệm lệnh
khi chúng được mở rộng.
284 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Một lệnh Trimedia bao gồm năm khe thao tác, mỗi khe có thể chỉ định một
hoạt động cho một đơn vị chức năng hoặc một trường tức thì. Mỗi hoạt động
riêng lẻ trong một lệnh được dự đoán với một giá trị thanh ghi duy nhất, nếu 0
gây racái đó thao tác trong hướng dẫn bị hủy bỏ. Trình biên dịch phải đảm bảo
rằng khi nhiều nhánh được bao gồm trong một lệnh,nhấtvị ngữ là true. Tải có thể
được suy đoán tự do trong kiến trúc Trimedia, vì chúng không tạo ra ngoại lệ.
(Không có hỗ trợ cho bộ nhớ ảo được phân trang.)
Ánh xạ giữa các khe lệnh và đơn vị bị hạn chế, vì lý do mã hóa lệnh và
chỉ đơn giản là gửi lệnh. Như Hình 4.18 cho thấy, có 23 đơn vị chức năng
thuộc 11 loại khác nhau. Một hướng dẫn có thể chỉ định bất kỳ kết hợp
nào sẽ phù hợp với các giới hạn trên năm trường.

Chức năng Đơn vị Khe hoạt động Các hoạt động điển hình đã thực hiện
Đơn vị Độ trễ bởi đơn vị chức năng
1 2 3 4 5
ALU 0 Vâng Vâng Vâng Vâng Vâng Số nguyên cộng / trừ / so sánh, logic
DMem 2 Vâng Vâng Tải trọng và cửa hàng

DMemSpec 2 Vâng Bộ nhớ cache làm mất hiệu lực, tìm nạp trước, phân bổ

Shifter 0 Vâng Vâng Dịch chuyển và xoay vòng

DSPALU 1 Vâng Vâng Các phép toán số học DSP đơn giản

DSPMul 2 Vâng Vâng Hoạt động DSP với phép nhân


Chi nhánh 3 Vâng Vâng Vâng Nhánh và nhảy
FALU 2 Vâng Vâng FP cộng, trừ
IFMul 2 Vâng Vâng Số nguyên và FP nhân lên

FComp 0 Vâng So sánh FP


FTough 16 Vâng Phép chia FP, căn bậc hai

HÌNH 4.18 Có 23 đơn vị chức năng thuộc 11 loại khác nhau trong CPU Trimedia.Bảng này hiển thị loại hoạt động được
thực hiện bởi mỗi đơn vị chức năng và các khe lệnh có sẵn để chỉ định một đơn vị chức năng cụ thể. Số lượng rãnh hướng
dẫn có sẵn để chỉ định một đơn vị bằng số bản sao của đơn vị đó. Do đó, có năm đơn vị ALU và hai đơn vị FALU.

Để xem bộ xử lý VLIW này hoạt động như thế nào, chúng ta hãy xem một ví dụ.

THÍ DỤ Đầu tiên, biên dịch vòng lặp cho mã C sau đây thành các lệnh MIPS, sau
đó hiển thị nó có thể trông như thế nào nếu các trường hoạt động của
bộ xử lý Trimedia giống với lệnh MIPS. (Trên thực tế, các kiểu hoạt động
Trimedia rất gần với các lệnh MIPS về khả năng.)
4.8 Góc nhìn khác: ILP trong Thị trường Nhúng và Di động 285

Vòng lặp: LDR11, R0 (R4) # R11 = a [i]


LD R12, R0 (R5)) # R12 = b [i]
DADDU R17, R11, R12 # R17 = a [i] + b [i]
SD 0 (R6), R17, # c [i] = a [i] + b [i]
DADDIU R4, R4,8 # R4 = địa chỉ [] tiếp theo
DADDIU R5, R5,8 # R5 = b [] địa chỉ tiếp theo
DADDIU R6, R6,8 # R6 = địa chỉ c [] tiếp theo
BNE R4, R7, Vòng lặp # nếu không, hãy chuyển đến Vòng lặp

một. Mã MIPS trước khi mở cuộn.

Vòng lặp: LDR11,0 (R4)) tải một [i]


LD R12, R0 (R5)) # tải b [i]
DADDU R17, R11, R12 # tải b [i]
SD 0 (R6), R17, # c [i] = a [i] + b [i]
LD R14,8 (R4) # tải một [i]
LD R15,8 (R5) # tải b [i]
DADDU R18, R14, R15 # a [i] + b [i]
SD 8 (R6), R18 # c [i] = a [i] + b [i]
LD R19,16 (R4) # tải một [i]
LD R20,16 (R5) # tải b [i]
DADDU R21, R19, R20 # a [i] + b [i]
SD 16 (R6), R21 # c [i] = a [i] + b [i]
LD R22,24 (R4) # tải một [i]
LD R23,24 (R5) # tải b [i]
DADDU R24, R22, R23 # a [i] + b [i]
SD 24 (R6), R24 # c [i] = a [i] + b [i]
DADDIU R4, R4,32 # R4 = địa chỉ [] tiếp theo
DADDIU R5, R5,32 # R5 = b [] địa chỉ tiếp theo
DADDIU R6, R6,32 # R6 = địa chỉ c [] tiếp theo
BNE R4, R7, Vòng lặp # nếu không, hãy chuyển đến Vòng lặp

b. Mã MIPS sau khi mở bốn lần và tối ưu hóa mã. Để đơn giản, chúng ta đã giả định rằng n
là bội số của bốn.

HÌNH 4.19Mã MIPS cho tổng vectơ số nguyên được hiển thị trong phần a trước khi
mở cuộn và trong phần b sau khi bỏ cuộn bốn lần. Các chuỗi mã này giả định
rằng các địa chỉ bắt đầu củaa, b,vàcđang ở trong sổ đăng kýR4, R5,vàR6,và điều
đóR7 chứa địa chỉ củamột].
286 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

dung lượng và độ trễ đơn vị tional được thể hiện trong Hình 4.18.

void sum (int a [], int b [], int c [], int n) {


int i;
cho (i = 0; i <n; i ++)
c [i] = a [i] + b [i];
}
Mở vòng lặp để có tối đa bốn bản sao của phần thân, nếu cần.

CÂU TRẢ LỜI Hình 4.19 cho thấy mã MIPS trước và sau khi giải nén. Hình 4.20 cho
thấy mã của bộ xử lý Trimedia được hiển thị trong. (Chúng tôi giả định
rằng R30 chứa địa chỉ của lệnh đầu tiên trong chuỗi.) Một bộ xử lý MIPS
chuẩn cần 20 lệnh 32-bit cho vòng lặp không được cuộn và bộ xử lý
Trimedia có 8 hướng dẫn, nghĩa là 1/2 số khe hoạt động VLIW đã đầy.
Tầm quan trọng của việc nén dòng mã trong CPU Trimedia là rõ ràng từ
ví dụ này. Như Hình 2.37 cho thấy, ngay cả sau khi nén, mã Trimedia vẫn
lớn hơn mã MIPS từ hai đến ba lần.
N

Vị trí 1 Vị trí 2 Vị trí 3 Vị trí 4 Vị trí 5

LD R11,0 (R4) LD R12, R0 (R5)

DADDUI R25, R6,32 LD R14,8 (R4) LD R15,8 (R5)

SETEQ R25, R25, R7 LD R19,16 (R4) LD R20,16 (R5)

DADDU R17, R11, R12 DADDIU R4, R4,32 LD R22,24 (R4) LD R23,24 (R5)

DADDU R18, R14, R15 JMPF R25, R30 SD 0 (R6), R17,

DADDU R21, R19, R20 DADDIU R5, R5,32 SD 8 (R6), R18

DADDU R24, R22, R23 SD 16 (R6), R21

DADDIU R6, R6,32 SD 24 (R6), R24

HÌNH 4.20 Mã Trimedia cho một vòng lặp đơn giản tổng hợp hai vectơ để tạo ra một phần ba sử dụng tốt nhiều cổng bộ nhớ
nhưng vẫn chứa một phần lớn các khe trống.Các vòng lặp với nhiều tính toán hơn bên trong cơ thể sẽ tận dụng tốt hơn các khe
hoạt động có sẵn. CácDADDUIvàSETEQcác hoạt động trong lệnh thứ hai và thứ ba (vị trí đầu tiên) dùng để tính toán kiểm tra kết
thúc vòng lặp. CácDADDUIsao chép một phần bổ sung sau đó, để việc tính toán có thể được thực hiện đủ sớm để lên lịch cho nhánh
và lấp đầy 3 vị trí trễ nhánh. Nhánh vòng lặp sử dụng lệnh JMPF để kiểm tra một thanh ghi (R25) và các nhánh tới một địa chỉ được
chỉ định bởi một thanh ghi khác (R30);

Hình 4.21 cho thấy hiệu suất và kích thước mã của TM1300, triển khai
166 MHz của kiến trúc TM-32 và NEC VR5000, 250 MHz
4.8 Góc nhìn khác: ILP trong Thị trường Nhúng và Di động 287

phiên bản của kiến trúc MIPS-32 bằng cách sử dụng các điểm chuẩn của
người tiêu dùng EEMBC hoặc các phép đo. Hiệu suất, được vẽ bằng các cột
trên trục bên trái và kích thước mã, được vẽ bằng các đường trên trục bên
phải, đều được hiển thị so với NEC VR4122, một bộ xử lý nhúng cấp thấp
triển khai tập lệnh MIPS. Hai phép đo hiệu suất khác nhau được hiển thị cho
TM1300. Phép đo “out-of-box” không cho phép thay đổi nguồn; phiên bản
được tối ưu hóa cho phép thay đổi, bao gồm cả mã hóa thủ công. Trong
trường hợp của TM1300, chỉ các loại thuốc mã nguồn và pragmas, cung cấp
hướng dẫn cho trình biên dịch, được sử dụng. Kết quả TM1300 được tối ưu
hóa tổng thể nhanh hơn gần năm lần so với kết quả ngoài hộp khi hiệu suất
được tóm tắt bằng giá trị trung bình hình học. Kết quả ngoài hộp cho
TM1300 là 1.

25.0 18.0

16.0

20.0
14.0

Kích thước mã liên quan đến VR4122


12.0

15.0
10.0
Hiệu suất so với NEC VR4122

số 8 . 0

10.0

6. 0

4.0
5. 0

2. 0

0. 0 0. 0
Nén JPEG Giải nén JPEG Quy mô xám lọc RGB sang CYMK RGB sang YIQ Trung bình Hình học

TM1300 "ra khỏi hộp" TM1300 được tối ưu hóa NEC VR5000
TM1300 "ra khỏi hộp" TM1300 được tối ưu hóa NEC VR5000

HÌNH 4.21 Hiệu suất và kích thước mã cho điểm chuẩn người tiêu dùng EEMBC chạy trên Trimedia TM1300 và NEC
VR5000 và được hiển thị so với hiệu suất và kích thước mã cho NEC VR4122 cấp thấp. Các cột và trục bên trái hiển thị
hiệu suất của các bộ xử lý được chuẩn hóa thành hiệu suất ngoài hộp của NEC VR4122. TM1300 có tốc độ đồng hồ là 166
MHz và kết quả được hiển thị cho phiên bản không có thay đổi mã nguồn (phiên bản “xuất xưởng”) và với một tập hợp các
thay đổi ở cấp nguồn (phiên bản “tối ưu hóa” ) bao gồm các thay đổi mã và pragmas, sau đó được biên dịch. Các đường và
trục bên phải hiển thị kích thước mã liên quan đến NEC VR4122 xuất xưởng bằng cách sử dụng Green Hills Compiler. các
phép đo này đều đến từ trang web của EEMBC: http://www.eembc.org/benchmark/benchmain.asp.
288 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

Một chi phí được trả cho việc đạt được hiệu suất này là sự gia tăng đáng kể về
kích thước mã. Kích thước mã của phiên bản xuất xưởng của điểm chuẩn trên
TM1300 tổng thể lớn gấp đôi kích thước mã trên VR5000. Đối với phiên bản tối ưu
hóa TM1300, kích thước mã lớn hơn bốn lần so với phiên bản VR5000. Hãy tưởng
tượng kích thước mã có thể lớn hơn bao nhiêu, nếu các kỹ thuật nén mã không
được sử dụng trong kiến trúc TM-32.
Sự cân bằng giữa kích thước mã và hiệu suất minh họa sự khác biệt cơ
bản trong mục tiêu thiết kế của kiến trúc MIPS và TM-32. Kiến trúc MIPS
là một kiến trúc có mục đích chung với một số phần mở rộng cho thị
trường nhúng. Kiến trúc TM-32 là một kiến trúc được thiết kế cho các
lớp ứng dụng nhúng cụ thể. Kích thước mã lớn hơn nhiều của TM-32 sẽ
khiến nó không phù hợp với nhiều phân khúc thị trường và tập lệnh
chuyên biệt của nó có thể không mang lại lợi ích hiệu suất đáng kể. Mặt
khác, hiệu suất cao của nó cho một số chức năng quan trọng, đặc biệt là
những chức năng trong xử lý phương tiện, có thể cho phép nó được sử
dụng thay cho các chip chuyên dụng được thiết kế cho một chức năng,
chẳng hạn như nén JPEG hoặc chuyển đổi hình ảnh. Bằng cách thay thế
một số mục đích đặc biệt.

Bộ xử lý Transmeta Crusoe
Bộ xử lý Crusoe là bộ xử lý VLIW được thiết kế cho thị trường tiêu thụ điện
năng thấp, đặc biệt là PC di động và thiết bị Internet di động, nhưng điều
khiến nó bất thường nhất là nó đạt được khả năng tương thích tập lệnh với
tập lệnh x86 thông qua hệ thống phần mềm dịch từ tập lệnh x86 thành tập
lệnh VLIW do Crusoe thực hiện.

Bộ xử lý Crusoe: Thông tin cơ bản về Bộ hướng dẫn


Bộ xử lý Crusoe là một VLIW khá đơn giản với việc thực thi theo thứ tự.
Các lệnh có hai kích thước: 64 bit (chứa hai hoạt động) và 128 bit (chứa
bốn hoạt động).
Có năm loại khe hoạt động khác nhau:

1. Các phép toán ALU: các phép toán RISC ALU điển hình với ba toán hạng thanh ghi số nguyên,
mỗi toán hạng chỉ định một trong 64 thanh ghi số nguyên.

2. Tính toán: khe cắm này có thể chỉ định bất kỳ hoạt động ALU số nguyên nào (có hai ALU
số nguyên trong đường dữ liệu), hoạt động dấu phẩy động (sử dụng 32 thanh ghi dấu
phẩy động) hoặc hoạt động đa phương tiện.

3. Bộ nhớ: một hoạt động tải hoặc lưu trữ.

4. Branch: một lệnh rẽ nhánh.

5. Ngay lập tức: 32-bit ngay lập tức được sử dụng bởi một hoạt động khác trong hướng dẫn này.
4.8 Góc nhìn khác: ILP trong Thị trường Nhúng và Di động 289

Có hai định dạng lệnh 128-bit khác nhau, được đặc trưng bởi các khe hoạt động
mà chúng có ::

Kỉ niệm Tính toán ALU Ngay tức khắc

Kỉ niệm Tính toán ALU Chi nhánh

Bộ xử lý Crusoe sử dụng một đường ống sáu giai đoạn theo thứ tự đơn giản cho các lệnh số
nguyên – hai giai đoạn tìm nạp, giải mã, đọc đăng ký, điều hành và ghi lại đăng ký – và một
đường ống mười giai đoạn cho dấu phẩy động, có thêm bốn giai đoạn thực thi.

Bộ xử lý Crusoe: dịch phần mềm và hỗ trợ phần cứng


Phần mềm chịu trách nhiệm triển khai tập lệnh x86 sử dụng nhiều kỹ thuật
khác nhau để thiết lập sự cân bằng giữa tốc độ thực thi và thời gian dịch. Ban
đầu, và để thực thi chi phí thấp nhất, mã x86 có thể được diễn giải trên cơ sở
hướng dẫn. Nếu một đoạn mã được thực thi nhiều lần, nó có thể được dịch
thành một chuỗi mã Crusoe tương đương và bản dịch có thể được lưu vào
bộ nhớ đệm. Đơn vị dịch ít nhất là một khối cơ bản, vì chúng ta biết rằng nếu
bất kỳ lệnh nào được thực thi trong khối, tất cả chúng sẽ được thực thi. Việc
dịch toàn bộ khối vừa cải thiện chất lượng mã được dịch vừa giảm chi phí
dịch, vì người dịch chỉ cần được gọi một lần cho mỗi khối cơ bản. Ngay cả
việc dịch nhanh một khối cơ bản cũng có thể tạo ra kết quả chấp nhận được,

Một trong những thách thức lớn của việc triển khai tập lệnh dựa trên phần mềm là
duy trì hành vi ngoại lệ của ISA ban đầu trong khi vẫn đạt được hiệu suất tốt. Đặc biệt,
đạt được hiệu suất tốt thường có nghĩa là sắp xếp lại các hoạt động tương ứng với các
lệnh trong chương trình gốc, có nghĩa là các hoạt động sẽ được thực hiện theo một
thứ tự khác với một cách diễn giải tuần tự nghiêm ngặt. Việc sắp xếp lại thứ tự này là
rất quan trọng để đạt được hiệu suất tốt khi mục tiêu là một VLIW. Do đó, cũng như
các bộ xử lý VLIW khác nhận thấy rằng việc hỗ trợ sắp xếp lại theo kiểu đầu cơ rất hữu
ích, thì sự hỗ trợ như vậy rất quan trọng trong Crusoe.
Sự hỗ trợ của Crusoe cho việc sắp xếp lại thứ tự suy đoán bao gồm bốn phần chính: tệp
thanh ghi bị che khuất, bộ đệm lưu trữ được chương trình điều khiển, phần cứng phát hiện
bí danh bộ nhớ có tải suy đoán và lệnh di chuyển có điều kiện (được gọi là select) được sử
dụng để thực hiện chuyển đổi if-on chuỗi mã x86.
Tệp thanh ghi bóng mờ và bộ đệm lưu trữ do chương trình điều khiển cho phép thực
hiện các hoạt động theo một thứ tự khác trong khi đảm bảo rằng trạng thái vĩnh viễn không
được cam kết cho đến khi không có ngoại lệ nào có thể xảy ra. 48 thanh ghi số nguyên và 16
thanh ghi dấu phẩy động bị che khuất. Các thanh ghi bóng được sử dụng để giữ trạng thái
chính xác và chỉ được cập nhật khi một trình tự được dịch có thể
290 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

tương ứng với một số lệnh x86 đã được thực thi mà không có ngoại lệ. Để chỉ ra rằng
các thanh ghi bóng tối nên được cập nhật, một cam kết được thực thi, điều này không
có chi phí nào vì mỗi lệnh đều có một bit được sử dụng để chỉ ra rằng một cam kết sẽ
được thực hiện ở cuối lệnh. Nếu một ngoại lệ xảy ra, tập thanh ghi chính (được gọi là
các thanh ghi làm việc) có thể được khôi phục từ các thanh ghi bóng bằng cách sử
dụng thao tác quay lui. Cơ chế này cho phép hoàn thành việc ghi thanh ghi không theo
thứ tự mà không phải hy sinh mô hình ngoại lệ chính xác của x86.

Một trong những tính năng mới nhất của bộ xử lý Crusoe là bộ đệm ghi được điều khiển
bằng chương trình. Các cửa hàng thường gây ra cập nhật trạng thái không thể thu hồi. Do
đó, trong các đường ống được lập lịch động của Chương 3, các cửa hàng được cam kết theo
thứ tự. Tương tự, trong kiến trúc IA-64, các cửa hàng không được suy đoán, vì không thể
hoàn tác cập nhật trạng thái. Kiến trúc Crusoe cung cấp một giải pháp mới cho lược đồ này:
nó bao gồm khả năng kiểm soát thời điểm bộ đệm ghi được phép cập nhật bộ nhớ. Một
hướng dẫn cổng khiến tất cả các cửa hàng được lưu giữ trong bộ đệm, cho đến khi thực
hiện một cam kết. Rollback sẽ làm cho bộ đệm bị tuôn ra. Tính năng này cho phép thực thi
cửa hàng đầu cơ mà không vi phạm mô hình ngoại lệ.
Bằng cách sử dụng các tải và cửa hàng đầu cơ đặc biệt (tương tự nhưld.svàchk.s
các cơ chế trong IA-64) cùng với khả năng khôi phục, trình dịch phần mềm có thể
sắp xếp lại thứ tự các tải và lưu trữ một cách phỏng đoán. Cácldplệnh chỉ ra một
tải suy đoán, có địa chỉ hiệu quả được lưu trữ trong một bộ đệm đặc biệt. Một cửa
hàng đặc biệt,nói lắp,cho biết một cửa hàng đã chuyển tải; nếuldpvànói lắp
chạm vào cùng một địa chỉ, thì tải suy đoán không chính xác. Quá trình khôi phục
được bắt đầu và chuỗi mã được thực hiện lại bắt đầu từ lệnh x86 theo sau cổng
cuối cùng.
Sự kết hợp này cũng có thể được sử dụng để tái sử dụng dữ liệu suy đoán trong
trường hợp một cửa hàng can thiệp giữa hai lần tải mà trình biên dịch tin là đến cùng
một địa chỉ. Bằng cách thực hiện tải đầu tiênldpvà cửa hàng anói lắp,sau đó người dịch
có thể sử dụng lại giá trị của lần tải đầu tiên, biết rằng nếu cửa hàng ở cùng địa chỉ với
tải, nó sẽ gây ra một cái bẫy. Sau đó, bẫy kết quả có thể thực hiện lại trình tự bằng
cách sử dụng cách diễn giải thận trọng hơn.

Bộ xử lý Crusoe: các biện pháp hiệu suất


Vì mục đích của bộ vi xử lý Crusoe là đạt được hiệu suất cạnh tranh ở mức công suất thấp,
nên các tiêu chuẩn đo lường cả hiệu suất và sức mạnh là rất quan trọng. Bởi vì Crusoe phụ
thuộc vào hành vi thực tế để điều chỉnh quá trình dịch mã, nó sẽ không thực hiện theo cách
dự đoán khi được chuẩn hóa bằng cách sử dụng các tập lệnh đơn giản, nhưng không thực
tế. Thật không may, các điểm chuẩn tiêu chuẩn hiện có sử dụng các tập lệnh đơn giản
không nhất thiết phản ánh hành vi thực tế của người dùng (đối với các điểm chuẩn như
Microsoft Office) về cả mức độ lặp lại và thời gian. Để khắc phục yếu tố này, Transmeta đã
đề xuất một bộ tập lệnh chuẩn mới. Thật không may, các tập lệnh này đã không được phát
hành và xác nhận bởi một nhóm các nhà cung cấp hoặc một tổ chức độc lập.
4.8 Góc nhìn khác: ILP trong Thị trường Nhúng và Di động 291

Thay vì bao gồm các kết quả như vậy, Hình 4.22 tóm tắt kết quả của các điểm chuẩn mà
hành vi của chúng được biết đến nhiều (cả hai đều là điểm chuẩn đa phương tiện). Vì thời
gian thực thi bị ràng buộc bởi các ràng buộc thời gian thực nên thời gian thực thi là giống
nhau và chúng tôi chỉ so sánh sức mạnh cần thiết.

Mô tả khối lượng công việc Công suất tiêu thụ cho khối lượng công việc (Watts) Mức tiêu thụ tương đối
TM 3200 /
Điện thoại di động Pentium III @ TM 3200 @ 400MHz Pentium III di động
500 MHz, 1,6V 1.5V
Phát lại MP3 0,672 0,214 0,32
Phát lại DVD 1.13 0,479 0,42
HÌNH 4.22 Hiệu suất năng lượng của bộ xử lý và mô-đun giao diện bộ nhớ sử dụng hai điểm chuẩn đa phương tiện
được hiển thị cho Mobile Pentium III và Transmeta 3200.Cả hai chip này đều có sẵn trong các phiên bản gần đây hơn có
các tính năng quản lý năng lượng bổ sung.

Mặc dù sự khác biệt về sức mạnh của bộ vi xử lý chắc chắn có thể ảnh hưởng đến tuổi thọ pin, nhưng
với bộ vi xử lý mới được thiết kế để giảm tiêu thụ năng lượng, bộ xử lý thường là một yếu tố góp phần nhỏ
vào việc sử dụng năng lượng tổng thể. Hình cho thấy các phép đo công suất cho một máy tính xách tay
điển hình dựa trên Mobile Pentium III. Như bạn có thể thấy những khác biệt nhỏ về mức tiêu thụ điện
năng của bộ xử lý không có khả năng tạo ra sự khác biệt lớn trong việc sử dụng điện năng tổng thể.

Hệ thống chính Thành phần Công suất (W) Phần trăm tổng công suất

Pentium III công suất thấp 0,8 số 8%

Giao diện bộ xử lý / bộ điều khiển bộ nhớ 0,65 6%


Bộ xử lý
Kỉ niệm 0,1 1%
Đồ họa 0,5 5%
Ổ cứng 0,65 6%
Ổ DVD 2,51 24%
I/O Âm thanh 0,5 5%
Kiểm soát và khác 1,3 12%
Màn hình TFT 2,8 27%
Quyền lực Nguồn cấp 0,72 7%
Tổng cộng 10.43 100%
HÌNH 4.23 Sự phân bố điện năng bên trong máy tính xách tay thực hiện hoàn vốn DVD cho thấy rằng hệ thống con
của bộ xử lý chỉ tiêu thụ 20% điện năng!Hệ thống phụ I / O tiêu thụ 74% công suất đáng kinh ngạc, chỉ riêng màn hình và
ổ DVD đã chiếm hơn 50% tổng công suất hệ thống. Bài học cho người dùng máy tính xách tay rất rõ ràng: không sử dụng ổ
đĩa và tắt màn hình! Dữ liệu này được đo bởi Intel và có sẵn trên trang web của họ.
292 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

4,9Sai lầm và cạm bẫy


Sai lầm: Có một cách tiếp cận đơn giản để xử lý nhiều vấn đề mang lại hiệu suất cao
mà không cần đầu tư đáng kể vào diện tích silicon hoặc độ phức tạp trong thiết kế.

Đây là một sự ngụy biện mà nhiều nhà thiết kế đã tin vào điều đó và cam kết nỗ lực
đáng kể để cố gắng tìm ra cách tiếp cận “viên đạn bạc” này. Mặc dù có thể xây dựng
các bộ xử lý đa vấn đề tương đối đơn giản, vì tỷ lệ vấn đề tăng khoảng cách giữa hiệu
suất cao nhất và hiệu suất bền vững sẽ tăng lên một cách nhanh chóng. Khoảng cách
này đã buộc các nhà thiết kế phải khám phá các kỹ thuật phức tạp để duy trì hiệu suất
(lập lịch động, hỗ trợ phần cứng và phần mềm để suy đoán, vấn đề linh hoạt hơn, tìm
nạp trước hướng dẫn phức tạp và dự đoán nhánh). Như Hình 4.24 - bao gồm dữ liệu
về Itanium, Pentium III và 4, và Alpha 21264 - cho thấy, kết quả là số lượng bóng bán
dẫn cao đồng đều, cũng như mức tiêu thụ điện năng cao. Hãy xem bạn có khớp các
đặc điểm với bộ xử lý hay không mà không cần đọc câu trả lời trong chú thích!

Tỷ lệ phát hành: Tổng / Tối đa Tỷ lệ khóa Linh kiện bán dẫn Bộ nhớ đệm trên chip: Quyền lực SPECbase
Bộ nhớ / Số nguyên / có sẵn có / không có Cấp 1 (Watts) CPU2000
FP / Chi nhánh (giữa năm 2001) bộ nhớ đệm Cấp độ thứ hai INT / FP

4/2/4/2/1 1 GHz 15 triệu / 6 triệu 64KB + 64KB 107 561/643


3/2/2/1/1 2 GHz 42 triệu / 23 triệu 12K mục + 8KB 67 636/648
256 KB
3/2/2/1/1 1 GHz 28 M / 9.5 M 16KB + 16KB 36 454/329
256 KB
6/2/2/2/3 0,8 GHz 25 triệu / 17 triệu 16 nghìn + 16 nghìn 130 379/714
96 KB

HÌNH 4.24 Các đặc điểm chính của bốn bộ vi xử lý nhiều vấn đề gần đây cho thấy sự đa dạng đáng kể.Chúng thay đổi
từ bộ xử lý suy đoán được lập lịch động đến bộ xử lý nhiều vấn đề lập lịch tĩnh đến VLIW. Chúng có kích thước khuôn từ chỉ
hơn 100 mm2 đến gần 300 mm2 và công suất từ 26 W đến chỉ dưới 100W, mặc dù các quy trình mạch tích hợp khác nhau
đáng kể. Các con số SPEC là con số chính thức cao nhất được báo cáo tính đến tháng 8 năm 2001 và tốc độ đồng hồ của hệ
thống đó được hiển thị. Bạn có đoán được bốn bộ vi xử lý này là gì không?
Trả lời: Alpha 21264, Intel Pentium 4, Intel Pentium III, Intel Itanium.

Ngoài sự phức tạp của phần cứng, rõ ràng là việc biên dịch cho các bộ
xử lý có lượng ILP đáng kể đã trở nên cực kỳ phức tạp. Không chỉ trình
biên dịch phải hỗ trợ một loạt các chuyển đổi phức tạp, mà việc điều
chỉnh trình biên dịch để đạt được hiệu suất tốt trên một loạt các điểm
chuẩn dường như là rất khó.
4.10 Nhận xét kết luận 293

Việc đạt được hiệu suất tốt cũng bị ảnh hưởng bởi các quyết định thiết kế ở
cấp hệ thống và những lựa chọn như vậy có thể phức tạp. Ví dụ, đối với máy đầu
tiên trong Hình 4.24, số SPECInt cao nhất đến từ phần 1 GHz, nhưng số SPECFP
cao nhất đến từ hệ thống có phần 833 MHz!
.

4,10Kết luận
Phương pháp EPIC dựa trên việc áp dụng các nguồn tài nguyên khổng lồ. Các tài nguyên
này bao gồm nhiều đơn vị lưu trữ tải, tính toán và chi nhánh hơn, cũng như các bộ nhớ đệm
lớn hơn, có độ trễ thấp hơn so với yêu cầu đối với bộ xử lý siêu thanh. Do đó, IA-64 đánh
cược rằng, trong tương lai, sức mạnh sẽ không phải là giới hạn quan trọng và nguồn tài
nguyên khổng lồ, cùng với máy móc để khai thác chúng, sẽ không ảnh hưởng xấu đến hiệu
suất của chúng đối với tốc độ đồng hồ, độ dài đường dẫn hoặc CPI các nhân tố.

M. Hopkins [2000], trong một bài bình luận về cách tiếp cận EPIC và kiến trúc IA-64
.

Giá trị tương đối của các phương pháp tiếp cận chuyên sâu về phần mềm và phần
cứng để khai thác ILP tiếp tục được tranh luận. Theo thời gian, có vẻ như các yếu
tố có lợi từ “trại đối phương” đang dần được kết hợp vào mỗi cách tiếp cận.
Những ví dụ bao gồm:

Các kỹ thuật "phần mềm" trong cách tiếp cận lấy phần cứng làm trung tâm Các kỹ thuật “phần cứng” trong các phương pháp tiếp cận chuyên sâu về phần mềm

Hỗ trợ cho các hướng dẫn có điều kiện. Bảng điểm lên lịch trình hướng dẫn.
Tìm nạp trước hướng dẫn và "gợi ý" bộ nhớ cache khác. Dự đoán nhánh động.
Gợi ý dự đoán rẽ nhánh. Hỗ trợ khôi phục hoặc bẫy và sửa chữa cho đầu cơ.

Hỗ trợ đặc biệt cho tải đầu cơ (không ngoại lệ). Phần cứng để kiểm tra độ chính xác của tải suy đoán.

Ban đầu, các phương pháp tiếp cận chuyên sâu về phần mềm và chuyên sâu về phần cứng
là khá khác nhau, và khả năng quản lý mức độ phức tạp của các phương pháp tiếp cận
chuyên sâu về phần cứng còn nhiều nghi ngờ. Sự phát triển của một số bộ xử lý đầu cơ
động hiệu suất cao, có tốc độ xung nhịp cao, đã làm giảm bớt mối lo ngại này. Sự phức tạp
của kiến trúc IA-64 và thiết kế Itanium đã chỉ ra cho nhiều nhà thiết kế rằng không chắc
rằng phương pháp tiếp cận chuyên sâu về phần mềm sẽ tạo ra các bộ xử lý nhanh hơn, nhỏ
hơn nhiều (về số lượng bóng bán dẫn hoặc kích thước khuôn), đơn giản hơn nhiều, hoặc tiết
kiệm điện hơn nhiều. Tương tự như vậy, sự phát triển của các trình biên dịch cho các bộ vi
xử lý này đã tỏ ra đầy thách thức. Mặc dù có khả năng cả hai trình biên dịch trong tương lai
cho IA-64 và các triển khai trong tương lai sẽ hiệu quả hơn, nhưng kiến trúc IA-64 không
không phảidường như đại diện cho một bước đột phá đáng kể trong
294 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

mở rộng ILP hoặc trong việc tránh các vấn đề phức tạp và tiêu thụ điện năng trong các
bộ xử lý hiệu suất cao.
Vì cả hai cách tiếp cận đã được chứng minh là có lợi thế, nên mỗi cách đều có
xu hướng kết hợp các kỹ thuật với nhau. Vẫn chưa rõ liệu hai cách tiếp cận sẽ tiếp
tục đi về phía giữa hay liệu một cách tiếp cận kiến trúc mới thực sự kết hợp
những gì tốt nhất của mỗi cách sẽ được phát triển.
Giải pháp thay thế để cố gắng tiếp tục thúc đẩy các bộ xử lý đơn khai thác ILP là
hướng tới các bộ xử lý đa xử lý, chủ đề của Chương 6. Hướng tới các bộ xử lý đa xử lý
để tận dụng tính song song khắc phục được một vấn đề cơ bản trong bộ xử lý ILP: xây
dựng một hệ thống bộ nhớ hiệu quả về chi phí. Hệ thống bộ nhớ đa xử lý vốn có tính
đa cổng và như chúng ta sẽ thấy, thậm chí có thể được phân phối trong một bộ xử lý
lớn hơn.
Việc sử dụng đa xử lý để khai thác song song gặp phải hai khó khăn. Đầu tiên, có
khả năng là mô hình phần mềm sẽ cần phải thay đổi. Thứ hai, các bộ đa xử lý có thể
gặp khó khăn trong việc khai thác song song mức độ nhỏ, chi tiết. Mặc dù có vẻ rõ
ràng rằng việc sử dụng một số lượng lớn các bộ xử lý yêu cầu các phương pháp lập
trình mới, nhưng việc sử dụng một số lượng nhỏ các bộ xử lý một cách hiệu quả có thể
dựa trên các phương pháp tiếp cận trình biên dịch hoặc ngôn ngữ, hoặc thậm chí có
thể được sử dụng cho nhiều quá trình độc lập. Việc khai thác kiểu song song chi tiết
mà trình biên dịch có thể dễ dàng phát hiện ra có thể khá khó khăn trong một bộ đa
xử lý, vì các bộ xử lý tương đối xa nhau. Đa luồng đồng thời (xem Chương 6) có thể là
bước trung gian giữa ILP và đa xử lý thực sự.
Vào năm 2000, IBM đã công bố bộ vi xử lý đa dụng chung-chip đơn thương
mại đầu tiên, IBM Power4, chứa hai bộ xử lý Power3 và một bộ nhớ đệm cấp hai
tích hợp, với tổng số bóng bán dẫn là 174 triệu! Bởi vì chip Power4 cũng chứa
giao diện bộ nhớ, giao diện bộ đệm cấp ba và kết nối đa bộ xử lý trực tiếp, IBM đã
sử dụng Power4 để xây dựng mô-đun 8 bộ xử lý sử dụng bốn chip Power4. Mô-
đun có tổng kích thước khoảng 64 in2và có khả năng đạt hiệu suất cao nhất là 32
tỷ phép toán dấu phẩy động mỗi giây! Thách thức đối với các bộ đa xử lý dường
như cũng giống như đối với các bộ xử lý đơn ILPintensive: chuyển hiệu suất cao
nhất khổng lồ này thành hiệu suất được phân phối trên các ứng dụng thực tế.
Trong trường hợp thiết kế của IBM, thị trường dự kiến là các máy chủ quy mô
lớn, nơi tính song song của ứng dụng có sẵn có thể làm cho một bộ đa xử lý trở
nên hấp dẫn.
Thế giới nhúng thực sự đã phân phối nhiều bộ xử lý trên một khuôn đầu tiên! TI
TMS320C80 cung cấp bốn DSP và một bộ xử lý RISC, hoạt động như một bộ điều khiển, trên
một khuôn duy nhất. Tương tự như vậy, một số phiên bản nhúng của bộ xử lý MIPS sử dụng
nhiều bộ xử lý trên mỗi khuôn. Sự song song rõ ràng trong các ứng dụng nhúng và việc
thiếu các yêu cầu nghiêm ngặt về khả năng tương thích phần mềm có thể cho phép thế giới
nhúng tiếp nhận quá trình đa xử lý trên chip nhanh hơn so với môi trường máy tính để bàn.
Chúng ta sẽ trở lại thảo luận này trong Chương 6.
4.11 Quan điểm lịch sử và tài liệu tham khảo 295

4,11Quan điểm lịch sử và tài liệu tham khảo


Phần này mô tả sự phát triển lịch sử của các phương pháp tiếp cận nhiều vấn đề, bắt
đầu với nhiều vấn đề tĩnh và tiến tới công việc gần đây nhất dẫn đến IA-64. Tương tự,
chúng ta nhìn vào. lịch sử lâu đời của công nghệ trình biên dịch trong lĩnh vực này.

Sự phát triển của các bộ xử lý nhiều vấn đề


Hầu hết các bộ xử lý nhiều vấn đề ban đầu đều tuân theo cách tiếp cận thiết
kế LIW hoặc VLIW. Charlesworth [1981] báo cáo về Hệ thống dấu chấm động
AP-120B, một trong những bộ xử lý lệnh rộng đầu tiên chứa nhiều thao tác
trên mỗi lệnh. Floating Point Systems đã áp dụng khái niệm tổng hợp phần
mềm trong cả trình biên dịch và thư viện hợp ngữ viết tay để sử dụng bộ xử
lý một cách hiệu quả. Vì bộ xử lý là một bộ xử lý gắn liền, nên có thể bỏ qua
nhiều khó khăn khi triển khai nhiều vấn đề trong các bộ xử lý đa năng, ví dụ,
bộ nhớ ảo và xử lý ngoại lệ.
Bộ xử lý Stanford MIPS có khả năng thực hiện hai hoạt động trong một lệnh
duy nhất, mặc dù khả năng này đã bị loại bỏ trong các biến thể thương mại của
kiến trúc, chủ yếu vì lý do hiệu suất. Cùng với các đồng nghiệp của mình tại Yale,
Fisher [1983] đã đề xuất tạo ra một bộ xử lý có lệnh rất rộng (512 bit), và đặt tên
cho loại bộ xử lý này là VLIW. Mã được tạo cho bộ xử lý bằng cách sử dụng lập
lịch theo dõi, mà Fisher [1981] đã phát triển ban đầu để tạo vi mã ngang. Việc
thực hiện lập lịch theo dõi cho bộ xử lý Yale được mô tả bởi Fisher et al. [1984] và
bởi Ellis [1986]. Bộ xử lý Đa luồng (xem Colwell và cộng sự [1987]) dựa trên các
khái niệm được phát triển tại Yale, mặc dù nhiều cải tiến quan trọng đã được thực
hiện để tăng tính thực tiễn của phương pháp. Trong số này có một bộ đệm lưu
trữ có thể kiểm soát được cung cấp hỗ trợ cho một hình thức đầu cơ. Mặc dù hơn
100 bộ vi xử lý Multiflow đã được bán, nhưng nhiều vấn đề, bao gồm khó khăn
khi giới thiệu bộ hướng dẫn mới từ một công ty nhỏ và sự cạnh tranh cung cấp từ
các bộ vi xử lý RISC thương mại đã làm thay đổi tính kinh tế trong thị trường máy
tính mini, dẫn đến sự thất bại của Multiflow như một công ty.

Cùng khoảng thời gian với Multiflow, Cydrome được thành lập để xây dựng bộ
xử lý VLIWstyle (xem Rau và cộng sự [1989]), cũng không thành công về mặt
thương mại. Dehnert, Hsu, và Bratt [1989] giải thích kiến trúc và hiệu suất của
Cydrome Cydra 5, một bộ xử lý với từ hướng dẫn rộng cung cấp khả năng đổi tên
thanh ghi động và hỗ trợ bổ sung cho đường dẫn phần mềm. Cydra 5 là sự pha
trộn độc đáo giữa phần cứng và phần mềm, bao gồm các lệnh có điều kiện và
xoay thanh ghi, nhằm mục đích trích xuất ILP. Cydrome dựa vào nhiều phần cứng
hơn bộ xử lý Đa luồng và đạt được hiệu suất cạnh tranh chủ yếu dựa trên mã kiểu
vectơ. Cuối cùng, Cydrome gặp phải vấn đề
296 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

tương tự như Multiflow và không phải là một thành công thương mại. Cả Multiflow và
Cydrome, mặc dù không thành công với tư cách là các thực thể thương mại, nhưng đã sản
sinh ra một số người có nhiều kinh nghiệm trong việc khai thác ILP cũng như công nghệ
trình biên dịch tiên tiến; nhiều người trong số đó đã tiếp tục kết hợp kinh nghiệm của họ và
các phần của công nghệ vào các bộ vi xử lý mới hơn. Fisher và Rau [1993] đã biên tập một bộ
sưu tập toàn diện các bài báo về phần cứng và phần mềm của hai bộ vi xử lý quan trọng
này.
Rau cũng đã phát triển một kỹ thuật lập lịch có tên làlập lịch đa vòng, là cơ sở cho
hầu hết các kế hoạch tổng hợp phần mềm (xem Rau, Glaeser và Picard [1982]). Công
trình của Rau được xây dựng dựa trên công trình trước đó của Davidson và các đồng
nghiệp của ông về việc thiết kế các bộ lập lịch phần cứng tối ưu cho bộ vi xử lý
pipelined. Các bộ vi xử lý LIW lịch sử khác bao gồm Apollo DN 10000 và Intel i860, cả
hai đều có thể tạo ra hai phép toán FP và số nguyên.
Một trong những cách tiếp cận thú vị được sử dụng trong các bộ xử lý VLIW đời
đầu, chẳng hạn như AP-120B và i860, là ý tưởng về một tổ chức đường ống yêu cầu
các hoạt động phải được “đẩy qua” một đơn vị chức năng và kết quả được ghi lại ở cuối
đường ống dẫn. Trong các bộ xử lý như vậy, các hoạt động chỉ tiến lên khi một hoạt
động khác đẩy chúng từ phía sau (theo trình tự). Hơn nữa, một lệnh chỉ định đích cho
một lệnh được phát hành trước đó sẽ được đẩy ra khỏi đường ống khi thao tác mới
này được đẩy vào. Cách tiếp cận như vậy có ưu điểm là nó không chỉ định đích kết quả
khi một thao tác phát hành lần đầu mà chỉ khi thanh ghi kết quả thực sự được viết. Sự
tách biệt này giúp loại bỏ sự cần thiết phải phát hiện các mối nguy hiểm WAW và WAR
trong phần cứng. Điểm bất lợi là nó làm tăng kích thước mã vì có thể cần các thao tác
không cần thiết để đẩy kết quả ra ngoài khi có sự phụ thuộc vào một thao tác vẫn
đang trong quá trình xử lý và không cần thao tác nào khác thuộc loại đó ngay lập tức.
Thay vì cách tiếp cận "push-and-catch" được sử dụng trong hai bộ xử lý này, hầu hết
các nhà thiết kế đã chọn sử dụngđường ống tự rútchỉ định đích đến trong chỉ thị phát
hành và trong đó một chỉ thị đã phát hành sẽ hoàn thành mà không cần thực hiện
thêm hành động nào. Những lợi thế về mật độ mã và sự đơn giản hóa trong quá trình
tạo mã dường như vượt trội hơn những lợi thế của cấu trúc khác thường hơn.

Công nghệ biên dịch và phần cứng hỗ trợ lập lịch trình
Phân tích sự phụ thuộc và song song mức vòng lặp được phát triển chủ yếu bởi D. Kuck và
các đồng nghiệp của ông tại Đại học Illinois vào những năm 1970. Họ cũng đặt ra thuật ngữ
thường được sử dụng làchống phụ thuộcvàphụ thuộc đầu ravà phát triển một số bài kiểm
tra phụ thuộc tiêu chuẩn, bao gồm các bài kiểm tra GCD và Banerjee. Thử nghiệm thứ hai
được đặt theo tên của Uptal Banerjee và có nhiều hương vị khác nhau. Công việc gần đây về
phân tích sự phụ thuộc đã tập trung vào việc sử dụng nhiều phép thử chính xác kết thúc
bằng một thuật toán gọi là Fourier-Motzkin, là một thuật toán lập trình tuyến tính. D.
Maydan và W. Pugh đều chỉ ra rằng trình tự của các thử nghiệm chính xác là một giải pháp
thực tế.
4.11 Quan điểm lịch sử và tài liệu tham khảo 297

Trong lĩnh vực khám phá và lập lịch ILP, phần lớn công việc ban đầu được kết nối
với sự phát triển của các bộ xử lý VLIW, được mô tả trước đó. Lam [1988] đã phát triển
các thuật toán cho phần mềm và đánh giá việc sử dụng chúng trên Warp, một bộ xử lý
văn bản hướng dẫn rộng được thiết kế cho các ứng dụng có mục đích đặc biệt. Weiss
và JE Smith [1987] so sánh phần mềm pipelining với việc giải nén vòng lặp như là các
kỹ thuật lập lịch trình mã trên một bộ xử lý pipelined. Rau [1994] đã phát triển lập lịch
modulo để giải quyết các vấn đề của vòng lặp đường ống phần mềm và đồng thời xử
lý việc cấp phát thanh ghi.
Hỗ trợ lập lịch mã đầu cơ đã được khám phá trong nhiều ngữ cảnh khác nhau,
bao gồm một số bộ xử lý cung cấp một chế độ trong đó các ngoại lệ bị bỏ qua,
cho phép lập lịch tải tích cực hơn (ví dụ: bộ xử lý MIPS TFP, xem [Hsu 1994].). Một
số nhóm đã khám phá các ý tưởng để hỗ trợ phần cứng tích cực hơn cho việc lập
lịch mã đầu cơ. Ví dụ, Smith, Horowitz và Lam [1992] đã tạo ra một khái niệm gọi
là tăng cường chứa một cơ sở phần cứng để hỗ trợ đầu cơ nhưng cung cấp một
cơ chế kiểm tra và phục hồi, tương tự như trong IA-64 và Crusoe. Ý tưởng lập lịch
trình cho lính canh, cũng tương tự như phương pháp suy đoán và kiểm tra được
sử dụng trong cả kiến trúc Crusoe và IA-64, được phát triển bởi các nhà nghiên
cứu tại Phòng thí nghiệm U. of Illinois và HP (xem [Mahlke et al. 1992] ).

Vào đầu những năm 1990, Wen-Mei Hwu và các đồng nghiệp của ông tại Đại học
Illinois đã phát triển một khung trình biên dịch, được gọi là IMPACT (xem [Chang, et al.
1991]), để khám phá sự tương tác giữa kiến trúc nhiều vấn đề và công nghệ trình
biên dịch. Dự án này đã dẫn đến một số ý tưởng quan trọng, bao gồm: lập lịch siêu
khối (xem [Hwu và cộng sự 1993]), sử dụng rộng rãi cấu hình để hướng dẫn nhiều cách
tối ưu hóa khác nhau (ví dụ: nội tuyến thủ tục) và sử dụng một bộ đệm đặc biệt (tương
tự vào ALAT hoặc bộ đệm lưu trữ được chương trình kiểm soát) để phát hiện xung đột
bộ nhớ hỗ trợ biên dịch (xem [Gallagher, et. 1994]). Họ cũng khám phá sự cân bằng
hiệu suất giữa hỗ trợ một phần và hỗ trợ toàn bộ cho dự đoán trong [Mahlke, et. al.
1995].
Các bộ xử lý RISC ban đầu đều có các nhánh bị trễ, một sơ đồ lấy cảm hứng từ lập trình vi
mô và một số nghiên cứu về dự đoán nhánh theo thời gian biên dịch được lấy cảm hứng từ
các cơ chế nhánh bị trễ. McFarling và Hennessy [1986] đã thực hiện một so sánh định lượng
của một loạt các sơ đồ dự đoán nhánh thời gian biên dịch và thời gian chạy. Fisher và
Freudenberger [1992] đã đánh giá một loạt các sơ đồ dự đoán nhánh thời gian biên dịch
bằng cách sử dụng thước đo khoảng cách giữa các lần xác định sai.

EPIC và Phát triển IA-64


Nguồn gốc của cách tiếp cận EPIC nằm ở những nỗ lực trước đó để xây dựng các máy LIW và
VLIW – đặc biệt là các máy tại Cydrome và Multiflow – và trong một lịch sử lâu dài của công
việc biên dịch tiếp tục sau khi các công ty này thất bại tại HP, Đại học Illinois và các nơi khác.
Những hiểu biết sâu sắc có được từ công việc đó đã khiến các nhà thiết kế tại HP đề xuất
kiến trúc 64 bit kiểu VLIW để tiếp nối với lưu trữ HP-PA RISC-
298 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

kiến trúc. Intel đang tìm kiếm một kiến trúc mới để thay thế kiến trúc x86
(bây giờ được gọi là IA-32) và cung cấp khả năng 64-bit. Năm 1995, họ đã
hợp tác để thiết kế một kiến trúc mới, IA-64, và xây dựng các bộ xử lý dựa
trên nó. Itanium là bộ xử lý đầu tiên như vậy. Mô tả về kiến trúc IA-64 có sẵn
trực tuyến tại: http://devresource.hp.com/devresource/Docs/Refs/IA64ISA/.
Mô tả về những điểm nổi bật của bộ xử lý Itanium có tại: http: //
www.intel.com/design/itanium/microarch_ovw/index.htm.

Người giới thiệu

BTẤT CẢ CÁC, T.VÀJR LARUS[1993]. “Dự đoán chi nhánh miễn phí”Proc. SIGPLAN 1993 Conf. trên Pro-
thiết kế và triển khai ngôn ngữ gramming, Tháng 6, 300-313.
CHANG, PP, MAHLKE, SA, CHEN, WY, WNGHỆ SỸ, NJ,VÀWW HWU[1991], “IMPACT: An
khung kiến trúc cho bộ xử lý vấn đề nhiều lệnh, ”Kỷ yếu của Hội nghị chuyên đề quốc tế
về kiến trúc máy tính lần thứ 18 (tháng 5), trang 266--275.
CHARLESWORTH, AE [1981]. “Một cách tiếp cận để xử lý mảng khoa học: Thiết kế kiến trúc
thuộc họ AP-120B / FPS-164, ”Máy tính14: 9 (tháng 9), 18–27.
COLWELL, RP, RP NIX, JJ O'DONNELL, DB PTHÁNG 4,VÀPK RODMAN[1987]. "MỘT
Kiến trúc VLIW cho trình biên dịch lập lịch theo dõi, ”Proc. Lời thú nhận thứ hai. về Hỗ trợ Kiến
trúc cho Ngôn ngữ Lập trình và Hệ điều hành,IEEE / ACM (tháng 3), Palo Alto, California, 180–192.

DEHNERT, JC, PY-T. HSU,VÀJP BRATT[1989]. “Hỗ trợ vòng lặp chồng chéo trên Cydra 5,”
Proc. Lời thú nhận thứ ba. về Hỗ trợ Kiến trúc cho Ngôn ngữ Lập trình và Hệ điều hành (Tháng 4),
IEEE / ACM, Boston, 26–39.
ELLIS, JR [1986].Bulldog: Trình biên dịch cho kiến trúc VLIW, MIT Press, Cambridge, Mass.
FLÀ CÔ ẤY, JA [1981]. “Lập lịch theo dõi: Một kỹ thuật để nén vi mã toàn cầu,”IEEE
Dịch. trên Máy tính30: 7 (tháng 7), 478–490.
FLÀ CÔ ẤY, JA [1983]. “Kiến trúc từ hướng dẫn rất dài và ELI-512,”Proc. Sympo thứ mười-
sium trên Kiến trúc máy tính(Tháng 6), Stockholm, 140–150.
FLÀ CÔ ẤY, JA, JR ELLIS, JC RUTTENBERG,VÀMỘTICOLAU[Năm 1984]. “Xử lý song song: Một
trình biên dịch và một bộ xử lý ngu ngốc, ”Proc. SIGPLAN Conf. về Xây dựng trình biên dịch(Tháng 6), Palo Alto,
Calif., 11–16.

FLÀ CÔ ẤY, JAVÀSM FREUDENBERGER[1992]. “Dự đoán các nhánh có điều kiện từ trước
chạy một chương trình, ”Proc. Lời thú nhận thứ năm. về Hỗ trợ Kiến trúc cho Ngôn ngữ Lập trình
và Hệ điều hành,IEEE / ACM (tháng 10), Boston, 85-95.
FLÀ CÔ ẤY, JAVÀBR RAU[1993].Tạp chí Siêu máy tính (tháng Giêng),Kluwer.
FQUÁI VẬT, CCVÀEM RISEMAN[Năm 1972]. “Phần nhỏ mã để tăng cường điều phối song song và
chấp hành,"IEEE Trans. trên Máy tínhC-21: 12 (tháng 12), 1411–1415.
GNGƯỜI CHO PHÉP, DM, CHEN, WY, MAHLKE, SA, GYLLENHAAL, JC,VÀWW HWU[1994]. “Dy-
định dạng bộ nhớ namic bằng cách sử dụng bộ đệm xung đột bộ nhớ. ” Proc. Hội nghị quốc tế
lần thứ sáu về hỗ trợ kiến trúc cho ngôn ngữ lập trình và hệ điều hành (tháng 10), Santa Clara.

HOPKINS, M. [2000]. “Một cái nhìn quan trọng về IA-64: Nguồn lực khổng lồ, ILP khổng lồ, nhưng liệu nó có thể phân phối-
ờ? ” Báo cáo bộ vi xử lý, tháng 2
PHSU[1994]. “Thiết kế bộ vi xử lý TFP”, IEEE Micro, Vol.18 Nr.2 (April), trang 2333. HWU, WW, M
AHLKE, SA, CHEN, WY, CHANG, PP, WNGHỆ SỸ, NJ, BRINGMANN, RA,
4.11 Quan điểm lịch sử và tài liệu tham khảo 299

OUELLETTE, RO, HANK, RE, KIYOHARA, THỨ TỰAAB, GE, HOLM, JG,VÀDM LHÀNG KHÔNG
[1993]. “The superblock: Một kỹ thuật hiệu quả để biên dịch VLIW và siêu địa chỉ.” Tạp chí Siêu
máy tính, 7 (1,2) (Tháng 3),: 229--248.
Lsáng, M. [1988]. “Đường ống phần mềm: Một kỹ thuật lập lịch hiệu quả cho bộ xử lý VLIW,”
SIGPLAN Conf. về Thiết kế và Triển khai Ngôn ngữ Lập trình, ACM (Tháng 6), Atlanta, Ga.,
318–328.
MAHLKE, SA, WY CHEN, W.-M. HWU, BR RAU,VÀMS SCHLANSKER[1992]. “Sentinel
lập lịch cho các bộ xử lý VLIW và superscalar, ”Proc. Lời thú nhận thứ năm. về Hỗ trợ Kiến trúc
cho Ngôn ngữ Lập trình và Hệ điều hành(Tháng 10), Boston, IEEE / ACM, 238–247.
MAHLKE, SA, HANK, RE MCCORMICK, JE AUGUST, DIVÀHWU.WW [1995]. “Một Compari-
con trai của Hỗ trợ Thực thi Dự đoán Một phần và Toàn bộ cho các Bộ xử lý ILP. ” Kỷ yếu Hội thảo
Quốc tế Thường niên lần thứ 22 về Kiến trúc Máy tính (Tháng 6), trang 138--149, Santa
Margherita Ligure, Ý.,
MCFARLING, S.VÀJ. HENNESSY[1986]. "Giảm chi phí của các chi nhánh,"Proc. Hội nghị chuyên đề lần thứ 13
trên Kiến trúc máy tính(Tháng 6), Tokyo, 396–403.
NICOLAU, MỘT.VÀJA FLÀ CÔ ẤY[Năm 1984]. “Đo độ song song có sẵn cho các chỉ dẫn rất dài
kiến trúc từ ngữ, ”IEEE Trans. trên Máy tínhC-33: 11 (tháng 11), 968–976.
BR RAU[1994]. “Lập lịch mô đun lặp lại: Một thuật toán cho các vòng lặp đường ống phần mềm.” Proc. Hội
nghị chuyên đề quốc tế thường niên lần thứ 27 về vi kiến trúc (tháng 11), trang 63--74, San Jose, CA.

RAU, BR, CD GLAESER,VÀRL PICARD[Năm 1982]. “Tạo mã hiệu quả cho chiều ngang
kiến trúc: Kỹ thuật biên dịch và hỗ trợ kiến trúc, ”Proc. Hội nghị chuyên đề lần thứ chín về kiến trúc
máy tính(Tháng 4), 131–139.
RAU, BR, DWL YEN, W. YEN,VÀCON CHUỘTOWLE[1989]. “Siêu phẩm phòng ban Cydra 5-
puter: Triết lý thiết kế, quyết định và sự đánh đổi, ”Máy tính IEEE22: 1 (tháng 1), 12–34.
RISEMAN, EMVÀCC FQUÁI VẬT[Năm 1972]. “Phần nhỏ mã để tăng cường điều phối song song và
chấp hành,"IEEE Trans. trên Máy tínhC-21: 12 (tháng 12), 1411–1415.
THORLIN, JF [1967]. “Tạo mã cho máy tính PIE (thực thi lệnh song song),”Proc.
Spring Joint Computer Conf.27.
WILSON, RPVÀMONICAS. Lsáng[1995]. “Phân tích con trỏ nhạy cảm theo ngữ cảnh hiệu quả cho C Pro-
gam, ”Proc. Hội nghị ACM SIGPLAN'95 về thiết kế và triển khai ngôn ngữ lập trình, La Jolla,
CA, tháng 6, trang 1-12.

BÀI TẬP

Hầu hết các bài tập này vẫn tốt. Những gì chúng ta cần là các bài tập khám phá các khái niệm về dự đoán và
lập lịch suy đoán.

Bổ sung mới: xem xét vòng lặp đơn giản trong Phần 4.1. Giả sử số lần lặp là không xác định, nhưng lớn. Tìm số lần giải nén
tối ưu về mặt lý thuyết bằng cách sử dụng thời gian của vòng lặp trong Phần 4.1 Gợi ý: hãy nhớ lại rằng bạn sẽ cần hai vòng
lặp: một vòng chưa được cuộn và một không được cuộn!

4.1[15] <4.1> Liệt kê tất cả các phụ thuộc (đầu ra, phản và đúng) trong đoạn mã sau. Cho biết liệu các phụ
thuộc thực sự có được thực hiện theo vòng lặp hay không. Chỉ ra lý do tại sao vòng lặp không song song.

vì(i = 2; i <100; i = i + 1) {
300 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

a [i] = b [i] + a [i]; / * S1 * /


c [i-1] = a [i] + d [i]; / * S2 * / a [i-1] = 2 * b
[i]; / * S3 * /
b [i + 1] = 2 * b [i]; / * S4 * /
}
4.2[15] <4.1> Đây là một vòng lặp bất thường. Đầu tiên, liệt kê các phụ thuộc và sau đó viết lại vòng lặp sao
cho nó song song.

vì(i = 1; i <100; i = i + 1) {
a [i] = b [i] + c [i]; b [i] = a / * S1 * /
[i] + d [i]; / * S2 * /
a [i + 1] = a [i] + e [i]; / * S3 * /
}
4.3[15] <4.1> Giả sử độ trễ đường ống từ Hình 4.1, hãy bỏ cuộn vòng lặp sau nhiều lần nếu cần để
lên lịch cho nó mà không có bất kỳ sự chậm trễ nào, thu gọn các hướng dẫn trên đầu của vòng lặp.
Giả sử một nhánh bị trễ một chu kỳ. Hiển thị lịch trình. Vòng lặp tính Y [i] = a×X [i] + Y [i], bước quan
trọng trong quá trình loại bỏ Gaussian.

vòng: LD F0,0 (R1)


MUL.D F0, F0, F2
LD F4,0 (R2)
ADD.D F0, F0, F4
SD F0,0 (R2)
DADDUI R1, R1, # - 8
DADDUI R1, R1, # - 8
BNE R1, R3, vòng lặp

4.4[15] <4.1> Giả sử độ trễ đường ống từ Hình 4.1 và một nhánh trễ một chu kỳ. Mở vòng
lặp sau đủ số lần để lập lịch trình mà không có bất kỳ sự chậm trễ nào. Hiển thị lịch trình sau
khi loại bỏ bất kỳ hướng dẫn chi phí dư thừa nào. Vòng lặp là một tích số chấm (giả sử F2
ban đầu là 0) và chứa một lần lặp lại. Mặc dù thực tế là vòng lặp không song song, nó có thể
được lên lịch mà không bị chậm trễ.
vòng: LD F0,0 (R1)
LD F4,0 (R2)
MUL.D F0, F0, F4
ADD.D F2, F0, F2
DADDUI R1, R1, # - 8
DADDUI R1, R1, # - 8
BNE R1, R3, vòng lặp

4,5[20/22/22/22/22/25/25/25/20/22/22] <4.1,4.2,4.3> Trong bài tập này, chúng ta sẽ xem xét


cách một vòng lặp vectơ chung chạy trên nhiều phiên bản pipelined khác nhau của MẸO.
Vòng lặp được gọi là vòng lặp SAXPY (được thảo luận nhiều trong Phụ lục B) và hoạt động
trung tâm trong loại bỏ Gaussian. Vòng lặp thực hiện phép toán vectơ Y = a×X + Y cho vectơ
có độ dài 100. Đây là mã MIPS cho vòng lặp:
foo: LD F2,0 (R1) ; tải X (i)
MUL.D F4, F2, F0 ; nhân a * X (i)
LD F6,0 (R2) ; tải Y (i)
ADD.D F6, F4, F6 ; thêm a * X (i) + Y (i); lưu
SD F6,0 (R2) trữ Y (i)
ADDI R1, R1, # 8 ;tăng X mục lục
ADDI R2, R2, # 8 ;tăng Y mục lục
SGTI R3, R1, hoàn thành ; kiểm tra nếu hoàn thành
BEQZ R3, foo ; lặp lại nếu chưa xong
4.11 Quan điểm lịch sử và tài liệu tham khảo 301

Đối với (a) - (e), giả sử rằng các phép toán số nguyên phát sinh và hoàn thành trong một chu kỳ đồng hồ
(bao gồm cả tải) và kết quả của chúng hoàn toàn bị bỏ qua. Bỏ qua độ trễ của nhánh. Bạn sẽ sử dụng độ
trễ FP được hiển thị trong Hình 4.1 trên trang 222. Giả sử rằng đơn vị FP được kết nối hoàn toàn.

một. [20] <4.1> Đối với sự cố này, hãy sử dụng đường ống MIPS đơn vấn đề tiêu chuẩn với
độ trễ đường ống từ Hình 4.1. Hiển thị số chu kỳ dừng cho mỗi lệnh và chu kỳ xung
nhịp nào mà mỗi lệnh bắt đầu thực hiện (tức là đi vào chu kỳ EX đầu tiên của nó) trong
lần lặp đầu tiên của vòng lặp. Mỗi lần lặp vòng lặp mất bao nhiêu chu kỳ đồng hồ?

b. [22] <4.1> Giải nén mã MIPS cho SAXPY để tạo bốn bản sao của phần thân và lên lịch cho
đường dẫn số nguyên MIPS tiêu chuẩn và một FPU được tổng hợp đầy đủ với
Độ trễ FP của Hình 4.1 trên trang 222. Khi giải nén, bạn nên tối ưu hóa mã như
chúng ta đã làm trong phần 4.1. Cần phải sắp xếp lại mã đáng kể để tối đa hóa
hiệu suất.

c. [25] <4.1,4.3> Giả sử một kiến trúc siêu địa phương có thể đưa ra hai hoạt động độc lập
bất kỳ trong một chu kỳ đồng hồ (bao gồm hai hoạt động số nguyên). Rút mã MIPS cho
SAXPY để tạo bốn bản sao của phần thân và lên lịch cho nó giả sử độ trễ FP của Hình
4.1 trên trang 222. Giả sử một bản sao hoàn chỉnh của mỗi đơn vị chức năng (ví dụ: bộ
cộng FP, bộ nhân FP) và hai đơn vị chức năng số nguyên với độ trễ để sử dụng là 0. Mỗi
lần lặp trên mã gốc sẽ mất bao nhiêu chu kỳ đồng hồ? Khi giải nén, bạn nên tối ưu hóa
mã như trong phần 4.1. Tốc độ tăng so với mã gốc là gì?

d. [25] <4.3> Để tăng tốc độ xung nhịp hơn nữa, một số bộ xử lý đã thêm pipelining bổ sung vào
các đơn vị truyền thống chỉ được chỉ định một giai đoạn trong đường ống, dẫn đến đường
ống có độ sâu 10-14 chu kỳ cho đường ống số nguyên. Giả sử chúng ta đã thiết kế một bộ xử
lý MIPS có đường dẫn sâu có tốc độ đồng hồ gấp đôi tốc độ xung nhịp của đường ống MIPS
tiêu chuẩn của chúng ta và có thể đưa ra hai lệnh không liên quan bất kỳ trong cùng thời
điểm mà đường ống MIPS thông thường đã phát hành một hoạt động. Nếu lệnh thứ hai phụ
thuộc vào lệnh đầu tiên, chỉ lệnh đầu tiên sẽ phát hành. Giải nén mã MIPS SAXPY để tạo bốn
bản sao của nội dung vòng lặp và lập lịch cho bộ xử lý có đường dẫn sâu này, giả sử độ trễ FP
của Hình 4.1 trên trang 222. Cũng giả sử tải để sử dụng độ trễ là 1 chu kỳ, nhưng độ trễ đơn
vị số nguyên khác là 0 chu kỳ. Mỗi lần lặp vòng lặp mất bao nhiêu chu kỳ đồng hồ? Hãy nhớ
rằng các chu kỳ đồng hồ này dài bằng một nửa các chu kỳ đồng hồ trên đường ống MIPS tiêu
chuẩn hoặc MIPS siêu phương.

e. [20] <4.3> Bắt đầu với mã SAXPY và bộ xử lý được sử dụng trong Hình 4.5. Mở vòng lặp SAXPY để
tạo bốn bản sao của phần thân, thực hiện tối ưu hóa đơn giản (như trong phần 4.1). Giả sử
tất cả các độ trễ đơn vị số nguyên là 0 chu kỳ và độ trễ FP được cho trong Hình 4.1. Điền vào
một bảng như Hình 4.28 cho vòng lặp chưa được cuộn. Mỗi lần lặp vòng lặp mất bao nhiêu
chu kỳ đồng hồ?

4,6[15] <4.4> Đây là một đoạn mã đơn giản:


vì(i = 2; i <= 100; i + = 2)
a [i] = a [50 * i + 1];

Để sử dụng bài kiểm tra GCD, vòng lặp này trước tiên phải được “chuẩn hóa” —được viết sao cho chỉ mục
bắt đầu từ 1 và tăng lên 1 sau mỗi lần lặp. Viết một phiên bản chuẩn hóa của vòng lặp (thay đổi các chỉ số
khi cần thiết), sau đó sử dụng bài kiểm tra GCD để xem liệu có sự phụ thuộc hay không.
302 Chương 4 Khai thác song song mức hướng dẫn với các phương pháp tiếp cận phần mềm

4,7[15] <4.1,4.4> Đây là một vòng lặp khác:

vì(i = 2, i <= 100; i + = 2)


a [i] = a [i-1];

Chuẩn hóa vòng lặp và sử dụng bài kiểm tra GCD để phát hiện sự phụ thuộc. Có sự phụ thuộc thực sự được thực
hiện trong vòng lặp này không?

4.8[25] <4.4> Chứng tỏ rằng nếu đối với hai phần tử mảng A (a×i + b) và A (c×i + d) có một sự phụ
thuộc thực sự thì GCD (c, a) chia cho (d - b).

4,9[15] <4.4> Viết lại vòng lặp pipelining phần mềm được hiển thị trong Ví dụ trên trang 249, để nó
có thể được chạy bằng cách giảm R1 đi 16 trước khi bắt đầu vòng lặp. Sau khi viết lại vòng lặp, hãy
hiển thị mã khởi động và kết thúc.Dấu: Để vòng lặp chạy đúng cách khi R1 giảm,SDnên lưu trữ kết
quả củanguyên bảnfilần lặp đầu tiên. Bạn có thể đạt được điều này bằng cách điều chỉnh hiệu số
cửa hàng phụ tải.

4,10[20] <4.4> Hãy xem xét vòng lặp mà phần mềm chúng tôi tạo ra ở trang 249. Giả sử độ trễ của
ADD.Dlà năm chu kỳ. Vòng lặp pipelined của phần mềm hiện đã bị đình trệ. Chỉ ra cách có thể viết
vòng lặp này bằng cách sử dụng cả phần mềm và giải nén vòng lặp để loại bỏ bất kỳ lỗi nào. Vòng
lặp nên được hủy cuộn càng ít lần càng tốt (một lần là đủ). Bạn không cần hiển thị khởi động hoặc
dọn dẹp vòng lặp.

4,11[15] <4.5> Thực hiện chuyển đổi tương tự (di chuyển lên nhánh) như ví dụ ở trang 262, nhưng
chỉ sử dụng di chuyển có điều kiện. Hãy cẩn thận rằng các tải của bạn, không còn phụ thuộc vào
điều khiển, không thể tạo ra một ngoại lệ nếu chúng đáng lẽ không được thực thi!

4,12[Thảo luận] <4.3-4.5> Thảo luận về những ưu điểm và nhược điểm của việc triển khai siêu
phương pháp và cách tiếp cận VLIW trong bối cảnh của MIPS. Mức độ nào của ILP ưu tiên cho mỗi
cách tiếp cận? Bạn sẽ cân nhắc những mối quan tâm nào khác khi chọn loại bộ xử lý nào để xây
dựng? Suy đoán ảnh hưởng đến kết quả như thế nào?
4.11 Quan điểm lịch sử và tài liệu tham khảo 303

You might also like