background image

Techniki zwiększania wydajności  procesorów  

 

 
 

czas /zadanie =(czas /takt) x (takty /rozkaz) x (rozkazy /zadanie) = Cx T x R 
 
gdzie  C: czas przypadający na takt zegarowy, 
 

T: liczba taktów zegarowych na rozkaz, 

 

R: liczba rozkazów na zadanie 

 

Zwiększenie wydajności procesora może być osiągnięte przez 

zmniejszenie dowolnego z tych czynników, przy czym iloczyn dwóch 
pierwszych czyli C x T jest czasem trwania cyklu rozkazowego. Czynniki te 
są od siebie zależne: zwiększenie częstotliwości generatora zegarowego 
(zmniejszenie taktu) powoduje zmniejszenie liczby operacji elementarnych, 
jakie mogą być wykonane w jednym takcie przy danej technologii i 
architekturze. To z kolei powoduje zwiększenie liczby taktów dla realizacji 
rozkazu. W klasycznych procesorach, CISC (Complex Instruction Set 
Computer) czas trwania taktu jest dobierany tak, aby w okresie jego trwania 
było możliwe wykonanie operacji elementarnej. Prostsze rozkazy, składające się 
z mniejszej liczby operacji elementarnych będą wymagały mniejszej liczby 
taktów, bardziej złożone – więcej. 

 

Rozkazy: 

prosty  

złożony prosty 

prosty 

 

Liczba taktów na rozkaz:  zmniejszenie liczby taktów zegarowych w 

cyklu rozkazowym prowadzi na ogół do wydłużenia taktu zegarowego. Metodą, 
pozwalającą na zmniejszenie średniej  liczby taktów na rozkaz bez wydłużania 
taktu zegarowego (czyli nie “więcej krótkich albo mniej długich”, ale mniej 
krótkich) jest metoda strumieniowego wykonywania rozkazów, tzw. pipelining 
processing.
  

Jeśli cały proces przetwarzania rozkazu podzielić na prostsze fazy, które 

mogą być  niezależnie wykonywane przez różne podzespoły, to wydajność 
procesu się zwiększy. Istotą takiego sposobu przetwarzania jest obecność w 
procesorze kilku rozkazów w różnych fazach przetwarzania, maksymalnie tylu, 
ile jest niezależnych elementów przetwarzających.  

 

Czas przetwarzania pojedynczego rozkazu nie zmienia się w porównaniu 

z indywidualnym przetwarzaniem każdego rozkazu, ale “gotowe” rozkazy 
pojawiają się na wyjściu z większą częstotliwością. Zwiększa się więc średnia 
liczba przetwarzanych rozkazów w jednostce czasu.  

 
 

background image

Strategia przetwarzania potokowego 
 

Rozpatrzymy prosty podział przetwarzania rozkazu na dwa etapy: 

!"

pobranie rozkazu, 

!"

dekodowanie rozkazu. 

 
Potok przebiega na 2 niezależnych etapach (dwa stanowiska obsługi): 

!"

pobranie i zbuforowanie rozkazu, 

!"

wykonywanie rozkazu. 

 

 
 
 
 
 
 
Schemat poszerzony: 
 
 
 
 
 
 
 
 
 
Ograniczenia: 
 

1.  Czas wykonywania jest na ogół dłuższy niż czas pobierania. 
2.  Rozkaz skoku warunkowego powoduje, że adres następnego rozkazu 

przewidzianego do pobrania jest nieznany. Wobec tego realizacja 
etapu pobierania może nastąpić dopiero po otrzymaniu adresu 
następnego rozkazu, który zostanie określony po zakończeniu etapu 
wykonywania. 

 
Strata czasu z drugiego powodu może być zmniejszona przez proste 
zgadywanie. Gdy rozkaz rozgałęzienia warunkowego przechodzi z etapu 
pobierania do etapu wykonywania, na etapie pobierania następuje 
pobranie następnego rozkazu z pamięci (po rozkazie rozgałęzienia). 
Jeśli nie nastąpi rozgałęzienie, czas nie jest stracony. Gdy jednak 
rozgałęzienie nastąpi, pobrany rozkaz musi być usunięty, a pobrany 
nowy. 

Pobieranie

 

Wykonywanie

 

Pobieranie 

Wykonywanie

 

Rozkaz 

Wynik 

Rozkaz

 

Wynik 

Rozkaz 

Rozkaz 

Oczekiwanie 

Oczekiwanie

 

Nowy adres 

Rozkaz odrzucony 

background image

Kluczowym zagadnieniem w organizacji potokowego przetwarzania 

rozkazów jest podział cyklu rozkazowego na fazy. Minimalnie liczba faz 
wynosi 4, a niekiedy jest ich kilkanaście !. 

 
 
Fetch
: faza pobrania rozkazów z PAO do wewnętrznego rejestru 

rozkazów lub wewnętrznej kolejki rozkazów, umieszczonej w pamięci 
cache instrukcji; 

Decode: faza dekodowania rozkazów, w czasie której następuje 

dekodowanie rozkazu i ustalane jest połączenie arytmometru z 
rejestrami, zawierającymi argumenty. Niekiedy do tej fazy zalicza się 
także pobranie argumentów z rejestrów uniwersalnych do rejestrów 
roboczych arytmometru; 

Execute: faza wykonania rozkazu. W przypadku rozkazów 

arytmetyczno-logicznych, w arytmometrze wykonywana jest operacja, 
ustalona na podstawie kodu rozkazu. W przypadku

 rozkazów komunikacji z 

pamięcią w fazie tej jest obliczany adres fizyczny argumentu. Niekiedy faza ta może 
trwać więcej niż jeden takt zegarowy. 

Write: faza zapisu wyniku. W przypadku rozkazu arytmetyczno-

logicznego wynik operacji zapisywany jest w docelowym rejestrze 
uniwersalnym, dla rozkazów komunikacji z PAO realizowany jest cykl 
odczytu / zapisu. 

background image

Proces przetwarzania potokowego będzie najbardziej efektywny, jeśli 

wszystkie fazy będą miały taki sam czas trwania, który może być przyjęty jako 
czas taktu zegarowego. 

 

F D E W  
 F 

 

 F 

 
Przetwarzanie sekwencyjne (skalarne) - w obserwowanym czasie zostaną 
wykonane 3 rozkazy. 
 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
Przetwarzanie potokowe
 - w obserwowanym czasie wykonanych 
zostanie 9 rozkazów, a 3 dalsze zostaną rozpoczęte. Proces 
przetwarzania rozpoczyna się tu od momentu, gdy linia przetwarzania 
była pusta. Początkowo nie wszystkie fazy są obciążone, stan ustalony 
rozpoczyna się dopiero od wykonania rozkazu czwartego.  
W stanie ustalonym w czasie jednego cyklu rozkazowego kończone 
są 4 rozkazy !!!
  

 

Rozkaz 1 

Takty  zegara 

Rozkaz 2 

background image

Oznacza to, że maksymalna efektywność przetwarzania potokowego 
wzrasta z krotnością, równą liczbie faz. Średnia liczba taktów na rozkaz 
wynosi wtedy jeden. Tak więc średni czas zakończenia rozkazu wynosi 
wtedy 1 takt zegarowy !!!  

 

Należy podkreślić,  że wynik tez uzyskuje się przy dwóch bardzo 
ważnych w rzeczywistych systemach założeniach:  
1 - jednakowy czas trwania wszystkich faz równy jeden takt,  
2 - brak konfliktów. 
 
 Przy zastosowaniu środków, wprowadzających nadmiarowości np. kilka 
takich samych zasobów, część konfliktów zasobów można rozwiązać i 
uzyskać  średni prawdziwy wynik powyżej jednego zakończonego 
rozkazu na jeden takt zegarowy. 

 

 
 

background image

W przetwarzaniu potokowym pojawiają się nowe problemy, nie 
występujące przy przetwarzaniu indywidualnym: 
elementy przetwarzające, pracujące na różnych warstwach (stage- etap, 
okres, stadium), mogą odwoływać się do tych samych elementów 
architektury komputera. Jeśli elementy te są zajęte, dana faza 
przetwarzania musi zostać wstrzymana, co powoduje wydłużenie czasu 
trwania fazy.  

 

Dany element przetwarzający może rozpocząć swoją pracę 

dopiero wtedy, gdy zakończył ją poprzednik, wobec tego wydłużenie faz 
może się propagować na następne warstwy.  

 
Wreszcie warunki pracy w potoku mogą być takie, że element 

przetwarzający, który zakończył swoją pracę nad danym rozkazem może 
rozpocząć przetwarzanie następnego dopiero wtedy, gdy następca 
odbierze obsłużony obiekt. Wykonanie następnego rozkazu może też 
zależeć od wyników rozkazu poprzedniego, który nie został jeszcze 
zakończony. Zależność taka ma miejsce, gdy argumentem pewnego 
rozkazu jest wynik rozkazu poprzedniego, lub gdy wykonanie 
następnego rozkazu jest zależne od stanu flag, ustawionych w rozkazie 
poprzednim - przypadek skoków warunkowych, od których zależy wybór 
drogi wykonania programu. 

 

background image

Konflikty, występujące w czasie przetwarzania potokowego, które 

w literaturze nosi również nazwę strumieniowego, muszą być 
rozstrzygane jak najszybciej, a więc w sposób sprzętowy i można je 
podzielić na 3 kategorie: 

1.  Konflikt zasobów: ten sam zasób (np. arytmometr, rejestr 

uniwersalny, magistrala lub pamięć) jest wykorzystywany przez 2 lub 
więcej fazy równocześnie. W co najmniej jednej z nich musi więc 
wystąpić czas oczekiwania. 

2. Konflikt danych: argumentem następnego rozkazu jest rezultat 

poprzedniego, jeszcze nie zakończonego 

3.  Konflikt sterowania: rozkaz skoku warunkowego, zależny od 

stanu wskaźników, ustawianych przez rozkaz poprzedni. 

 

Można wyróżnić jeszcze czwarty rodzaj konfliktów, wynikający z faktu, że w trakcie 

wykonania każdego rozkazu mogą powstać sytuacje wyjątkowe, uniemożliwiające poprawne 
zakończenie rozkazu (np. błędy adresacji czy dzielenie przez zero). Sytuacje takie są zwykle 
obsługiwane w procesorze za pomocą mechanizmu przerwań wewnętrznych, zwanych w 
nomenklaturze Intela wyjątkami (exeptions). Dla zapewnienia prawidłowej obsługi takich 
sytuacji, które są de facto wykonaniami niejawnych skoków do procedur obsługi wyjątków, 
wszystkie rozkazy, znajdujące się w głównym strumieniu rozkazów przed rozkazem, który 
spowodował wyjątek, muszą zostać zakończone. 

 
 

 
 

background image

Rozwiązywanie konfliktów 
 
Konflikt zasobów
: dwie lub więcej faz usiłuje skorzystać z tego samego 
zasobu. Jeśli przyjąć podział rozkazu na 4 omówione wcześniej fazy, to konflikt 
do arytmometru nie wystąpi nigdy, bowiem fazy Execute różnych rozkazów nie 
nakładają się w czasie. Dostęp do rejestrów może być konfliktowy, gdyż w fazie 
Execute pobierane są z nich argumenty, a w fazie Write są do nich zapisywane 
wyniki.  

 

Rozwiązaniem jest tzw. multiple port register file, czyli udostępnienie każdemu 
rejestrowi niezależnych połączeń z każdą fazą. Wtedy konflikt miałby miejsce 
tylko przy próbie użycia tego samego rejestru, ale to już zadanie kompilatorów 
optymalizujących lub samodzielnej uważnej gospodarki rejestrami.  

 
Najtrudniejsze do usunięcia są konflikty w dostępie do pamięci, gdyż kontakt z PAO zachodzi 
w fazach Fetch i Write. W celu zmniejszenia częstotliwości występowania takich konfliktów 
wyposaża się procesor w dodatkowy blok rejestrów, zwany kolejką pobierania wstępnego lub 
prefetcherem, do której są pobierane na zapas rozkazy do wykonania w czasie, gdy pamięć nie 
jest zajęta w fazie Write.  
 
Oczywiście faza Write może nastąpić w sytuacji, gdy kolejka jest pusta i wtedy musi być 
wprowadzony takt oczekiwania.  
 

Całkowitą eliminację  konfliktów w dostępie do pamięci można 
uzyskać poprzez niezależne stworzenie dróg dostępu dla pobierania 
rozkazów i osobno dla odczytu/ zapisu danych. Ponieważ zwykle 
rozkazy są w segmencie kodu, a dane w segmencie danych, to konflikt 
dostępu do tej samej komórki nie powinien wystąpić. Rozwiązanie to 
wymaga zastosowanie specjalnego bloku pamięci, umożliwiającego 
jednoczesny dostęp do dwóch różnych komórek - tzw. pamięć 
dwuportowa.  

 

Architektura z rozdzieloną pamięcią danych i rozkazów nazywa się 
architekturą typu Harvard..  
 

background image

Konflikt danych: występuje, gdy wykonywanie rozkazu musi być 
wstrzymane z powodu niedostępności argumentu, będącego rezultatem 
wcześniejszego, nie zakończonego jeszcze rozkazu. Rozważmy 
przykład obliczania średniej arytmetycznej dwóch liczb, znajdujących się 
w rejestrach r1 i r2: 
 

add  r1, r2 ;  

r1 := r1 + r2 

 

shr  r1, 1  ;  

r1 := r1 / 2 

Jeżeli rozkazy te są wykonywane w trybie potokowym, to argument w r1 
jest wymagany przez shr w czasie, gdy jest on dopiero obliczany w add: 

 

F D E argument w 

r1 obliczany 

W  argument 
do r1 
zapisywany 

 

 F 

argument w 

r1 potrzebny 

E  W 

 
 

Poprawność działania procesora można uzyskać w tej sytuacji przez wstawienie taktów 
oczekiwania za pomocą instrukcji pustej NOP, dzielącej oba rozważane rozkazy, ale 
spowoduje to obniżenie wydajności. Gdyby można wykonać w tym czasie inny, użyteczny 
rozkaz, nie powodujący konfliktów, spadek wydajności by nie wystąpił, ale często nie ma 
takiej możliwości. W bardziej wyrafinowanych konstrukcjach stosuje się inne rozwiązanie 
tego problemu, a mianowicie zmianę przez procesor kolejności wykonania rozkazów w 
stosunku do tej, jaka była zapisana w programie (out of order execution). Jeśli mechanizm 
kontroli gotowości argumentów wskaże, że oczekujący rozkaz nie może go otrzymać, jest on 
wyłączany z głównego ciągu przetwarzania i oczekuje “z boku” na dostępność “swojego” 
argumentu. Po zaistnieniu odpowiednich warunków jego wykonanie jest wznawiane. Pojawia 
się tu jedna problem obsługi wyjątków powodowanych przez rozkazy znajdujące się poza 
kolejnością, co wymaga stosowania mechanizmów synchronizacji programu. 

 

background image

Konflikt sterowania:  prawidłowa realizacja rozkazów, zmieniających 
kolejność pobierania rozkazów (jump, call, ret) stanowi najtrudniejszy 
problem w przetwarzaniu potokowym. W czasie wykonywania rozkazu 
skoku jest obliczony adres następnego rozkazu, który staje się dostępny 
później, niż wymaga tego faza pobrania następnego rozkazu. 

 

F D 

po 

zakończeniu  
adres 
docelowy jest 
dostępny 

E W 

 

 

X X  X  szczelina 

czasowa 

 

   F D 

 

Aby zmniejszyć wpływ tego opóźnienia, adres skoku powinien być obliczany w fazie 
dekodowania rozkazu skokowego. Można też stosować tzw. metodę skoku opóźnionego 
(delayed branch), która polega na wykonaniu przed rozkazem skoku jednego rozkazu, 
występującego w programie bezpośrednio za rozkazem skokowym. 
Przy skokach warunkowych wprowadza się kilka kopii rejestru flag i jeśli zawartość 
odpowiedniego rejestru warunku nie jest ustalona przed rozpoczęciem wykonywania skoku, to 
wykonywana jest sprzętowa predykcja skuteczności skoku i zgodnie z tym przewidywaniem 
pobierane są kolejne rozkazy do przetwarzania. Po zakończeniu cyklu rozkazowego rozkazu 
skoku warunkowego następuje sprawdzenie zgodności warunku przewidywanego z 
zaistniałym i jeśli zgodność istnieje, to przetwarzanie jest kontynuowane bez straty czasu.  
W przypadku błędnej predykcji operacje we wszystkich fazach są kasowane i proces 
przetwarzania potokowego wykonywany jest od początku - bardzo kosztowne czasowo 
!!!
 

 
 

background image

Postępowanie z rozgałęzieniami 

 

!"

zwielokrotnienie strumienia, 

!"

pobieranie docelowego rozkazu z wyprzedzaniem, 

!"

bufor pętli, 

!"

przewidywanie rozgałęzienia, 

!"

opóźnione rozgałęzienie. 

 

 
 
Zwielokrotnienie strumienia 
 
Polega na powieleniu początkowych etapów potoku i umożliwieniu 
równoczesnego pobrania obu rozkazów za pomocą dwóch strumieni. 
Rozwiązanie to stwarza pewne problemy: 
1. W przypadku zwielokrotnionego strumienia występują opóźnienia, 

wynikające z rywalizacji o dostęp do rejestrów i pamięci; 

2. Mogą pojawić się następne rozkazy rozgałęzienia, zanim zostanie 

rozstrzygnięte dane rozgałęzienie. Każdy taki rozkaz wymaga 
dodatkowego strumienia. 

 
Przykład maszyn w dwoma i większą liczbą strumieni: 
IBM 370/168, IBM 3033. 
 
 
Pobieranie docelowego rozkazu z wyprzedzaniem 
Gdy rozpoznany jest rozkaz rozgałęzienia warunkowego, następuje 
wyprzedzające pobranie rozkazu docelowego razem z rozkazem 
następującym po rozgałęzieniu. Rozkaz docelowy jest następnie 
zachowywany, aż do czasu wykonania rozgałęzienia.  
 
Rozwiązanie to zastosowano w IBM 360/91 
 

background image

Bufor pętli 
 
Bufor pętli jest małą, bardzo szybką pamięcią związaną z etapem 
pobierania rozkazów potoku. Zawiera on n  ostatnio pobranych 
rozkazów. Jeśli ma nastąpić rozgałęzienie, sprawdza się najpierw, czy 
cel rozgałęzienia znajduje się wewnątrz bufora. Jeśli tak, to pobierany 
jest rozkaz z bufora.  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Trzy podstawowe zalety bufora pętli: 
1. Dzięki pobieraniu z wyprzedzeniem bufor pętli zawiera rozkazy 

następujące kolejno po adresie bieżącego rozkazu. 

2. Jeśli następuje rozgałęzienie do rozkazu znajdującego się o kilka 

pozycji dalej od adresu rozkazu rozgałęzienia, to rozkaz docelowy 
będzie już znajdował się w buforze. Szczególnie użyteczne dla 
sekwencji IF-THEN oraz IF-THEN-ELSE. 

3. Jeżeli bufor zmieści wszystkie rozkazy składające się na pętlę, to 

rozkazy te musza być pobrane tylko raz, przy pierwszej iteracji. 

 
Bufor pętli jest w zasadzie podobny do dedykowanej rozkazom pamięci 
podręcznej. Różnica polega na tym, że bufor pętli zawiera tylko 
sekwencje rozkazów i jest o wiele mniejszy. 
 
Przykłady zastosowania: maszyny CDC (Star 660, 7600) oraz CRAY-1. 
 
 
 
 
 
 

Adres rozgałęzienia 

Bufor pętli 

(256 bajtów) 

Porównanie najbardziej znaczących bitów 
adresu w celu stwierdzenia trafienia 

Rozkaz, który ma być 
dekodowany w przypadku 
trafienia 

background image

Przewidywanie rozgałęzienia 
Strategie statyczne: 
-  przewidywanie zawsze następującego rozgałęzienia, 
-  przewidywanie nigdy nie następującego rozgałęzienia, 
-  przewidywanie za pomocą kodu operacji. 
 
Strategie dynamiczne: 
-  przełącznik nastąpiło /nie nastąpiło, 
-  tablica historii rozgałęzień. 
 
Tablica historii rozgałęzień jest małą pamięcią podręczną, powiązaną z 
etapem pobierania rozkazu w potoku. Każdy zapis w tablicy składa się z 
trzech elementów: 
-  adresu rozkazu rozgałęzienia, 
-  pewnej liczby bitów historii, 
-  informacji o rozkazie docelowym (adres rozkazu lub sam rozkaz). 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Adres 

rozkazu 

rozgałęzienia 

 

Adres 

celu 

 

Stan 

 

 

 

 

 

 

 

 

 

 

 

 



 



 



 

Wy

IPFAR 

Następny 
adres  
w kolejności 

Pamięć 

Układy logiczne 

BHT

Skieruj ponownie

 

Aktualizuj stan 

Dodaj nowy 

zapis 

E

 

background image

Czy są granice zwiększania wydajności poprzez wydzielenie 
większej liczby faz wykonania rozkazu? 

 
1. Na każdym etapie potoku występuje pewien narzut związany z 

przenoszeniem danych z bufora do bufora oraz z wykonywaniem 
różnych działań przygotowawczych. 

2. Liczba układów logicznych wymaganych do zapobiegania 

konfliktom rejestrów i pamięci oraz do optymalizacji potoku 
wzrasta znacząco wraz z liczba faz (etapów). Może to prowadzić 
do sytuacji, gdy układy logiczne sterujące przejściami między 
etapami są bardziej złożone niż układy sterujące wykonaniem 
etapów.