Architektura procesora zorientowana na opóźnienia
Architektura procesora zorientowana na opóźnienia to mikroarchitektura mikroprocesora zaprojektowana do obsługi szeregowego wątku obliczeniowego z niskim opóźnieniem. Jest to typowe dla większości jednostek centralnych (CPU) opracowywanych od lat 70. XX wieku. Ogólnie rzecz biorąc, architektury te mają na celu wykonanie jak największej liczby instrukcji należących do pojedynczego wątku szeregowego w określonym oknie czasu; jednakże czas pełnego wykonania pojedynczej instrukcji od etapu pobrania do wycofania może wahać się od kilku cykli do nawet kilkuset cykli w niektórych przypadkach. [ potrzebna strona ] Architektury procesorów zorientowane na opóźnienia są przeciwieństwem procesorów zorientowanych na przepustowość, które bardziej skupiają się na całkowitej przepustowości systemu niż na opóźnieniach usług dla wszystkich poszczególnych wątków, nad którymi pracują. [ potrzebna strona ]
taksonomia Flynna
Zazwyczaj architektury procesorów zorientowane na opóźnienia wykonują pojedyncze zadanie działające na pojedynczym strumieniu danych, a więc są SISD w taksonomii Flynna. Architektury procesorów zorientowane na opóźnienia mogą również zawierać SIMD , takie jak Intel MMX i SSE ; chociaż te rozszerzenia działają na dużych zestawach danych, ich głównym celem jest zmniejszenie ogólnego opóźnienia.
Techniki wdrażania
Istnieje wiele technik architektonicznych stosowanych w celu zmniejszenia ogólnego opóźnienia dla pojedynczego zadania obliczeniowego. Zwykle polegają one na dodawaniu dodatkowego sprzętu w potoku w celu obsługi instrukcji, gdy tylko zostaną one pobrane z pamięci lub pamięci podręcznej instrukcji . Godną uwagi cechą tych architektur jest to, że znaczna część chipa jest wykorzystywana w częściach innych niż jednostki wykonawcze sobie. Dzieje się tak dlatego, że celem jest skrócenie czasu wymaganego do wykonania „typowego” zadania w środowisku komputerowym. Typowe zadanie obliczeniowe to szeregowy zestaw instrukcji, w którym istnieje duża zależność od wyników uzyskanych przez poprzednie instrukcje tego samego zadania. Dlatego logiczne jest, że mikroprocesor będzie spędzał czas na wykonywaniu wielu innych zadań niż obliczenia wymagane przez same instrukcje. Jeśli zagrożenia napotkane podczas obliczeń nie są szybko rozwiązywane, wówczas zwiększa się opóźnienie dla wątku. Dzieje się tak, ponieważ zagrożenia blokują wykonanie kolejnych instrukcji i, w zależności od implementacji potoku, mogą całkowicie zatrzymać postęp do czasu rozwiązania zależności lub doprowadzić do lawiny kolejnych zagrożeń w przyszłych instrukcjach; dalsze wydłużanie czasu wykonywania wątku.
Przestrzeń projektowa technik mikroarchitektonicznych jest bardzo duża. Poniżej przedstawiono niektóre z najczęściej stosowanych technik zmniejszania ogólnego opóźnienia wątku.
Architektura zestawu instrukcji (ISA)
Większość współczesnych architektur używa krótszych i prostszych instrukcji, takich jak architektura ładowania/zapisywania , które pomagają w optymalizacji potoku instrukcji w celu szybszego wykonania. Instrukcje są zwykle tego samego rozmiaru, co pomaga również w optymalizacji logiki pobierania instrukcji. Taki ISA nazywany jest RISC .
Potokowanie instrukcji
Przetwarzanie potokowe nakłada się na wykonywanie wielu instrukcji z tego samego wykonującego się wątku w celu zwiększenia częstotliwości zegara lub zwiększenia liczby instrukcji wykonywanych w jednostce czasu; zmniejszając w ten sposób całkowity czas wykonywania wątku. Zamiast czekać, aż pojedyncza instrukcja zakończy wszystkie etapy wykonania, wiele instrukcji jest przetwarzanych jednocześnie na odpowiednich etapach wewnątrz potoku.
Zmiana nazwy rejestru
Ta technika jest wykorzystywana do efektywnego zwiększania całkowitego rozmiaru pliku rejestrów, niż określono w ISA dla programistów, oraz do eliminowania fałszywych zależności. Załóżmy, że mamy dwie kolejne instrukcje, które odwołują się do tego samego rejestru. Pierwszy odczytuje rejestr, a drugi zapisuje do niego. Aby zachować poprawność programu, należy pilnować, aby druga instrukcja nie zapisała do rejestru, zanim pierwsza nie będzie mogła odczytać swojej pierwotnej wartości. To jest przykład zapisu po odczycie (WAR) zależność. Aby wyeliminować tę zależność, potok „zmieniłby” nazwę instrukcji wewnętrznie, przypisując ją do rejestru wewnętrznego. Instrukcja może zatem zostać wykonana, a wyniki przez nią wytworzone będą teraz natychmiast dostępne dla wszystkich kolejnych instrukcji, nawet jeśli rzeczywisty rejestr docelowy zamierzony przez program zostanie zapisany później. Podobnie, jeśli obie instrukcje miały po prostu zapisywać do tego samego rejestru Write-After-Write (WAW) , potok zmieniłby ich nazwy i zapewniłby, że ich wyniki będą dostępne dla przyszłych instrukcji bez konieczności serializacji ich wykonania.
Organizacja pamięci
Różne poziomy pamięci, które obejmują pamięci podręczne , pamięć główną i pamięć nieulotną, taką jak dyski twarde (gdzie znajdują się instrukcje programu i dane), mają na celu wykorzystanie lokalności przestrzennej i lokalności czasowej w celu skrócenia całkowitego czasu dostępu do pamięci . Im mniej czasu procesor spędza na oczekiwaniu na pobranie danych z pamięci, tym mniejsza liczba instrukcji zużywa zasoby potoku podczas bezczynności i niewykonywania żadnej użytecznej pracy. Potok instrukcji zostanie całkowicie zatrzymany, jeśli wszystkie jego wewnętrzne bufory (np stacje rezerwacyjne ) są zapełnione do ich odpowiednich pojemności. W związku z tym, jeśli instrukcje zużywają mniej cykli bezczynności w potoku, istnieje większa szansa na wykorzystanie równoległości na poziomie instrukcji (ILP), ponieważ logika pobierania może pobierać większą liczbę instrukcji z pamięci podręcznej/pamięci na jednostkę czasu.
Wykonanie spekulacyjne
Główną przyczyną przestojów potoku są zależności przepływu sterowania, tj. gdy wynik instrukcji rozgałęzienia nie jest z góry znany (co zwykle ma miejsce). Wiele współczesnych architektur wykorzystuje komponenty predykcyjne rozgałęzień do odgadywania wyniku rozgałęzienia. Wykonywanie jest kontynuowane wzdłuż przewidywanej ścieżki dla programu, ale instrukcje są oznaczone jako spekulatywne. Jeśli przypuszczenie okaże się poprawne, instrukcje mogą zakończyć się pomyślnie i zaktualizować swoje wyniki z powrotem do rejestru pliku/pamięci. Jeśli odgadnięcie było niepoprawne, wszystkie spekulatywne instrukcje są usuwane z potoku, a wykonywanie (ponownie) rozpoczyna się wzdłuż rzeczywistej poprawnej ścieżki dla programu. Utrzymując wysoką dokładność predykcji, potok jest w stanie znacznie zwiększyć przepustowość wykonywanego wątku.
Wykonanie poza kolejnością
Nie wszystkie instrukcje w wątku wymagają takiej samej ilości czasu na wykonanie. Potoki superskalarne zwykle mają wiele możliwych ścieżek dla instrukcji w zależności od bieżącego stanu i samego typu instrukcji. W związku z tym, aby zwiększyć liczbę instrukcji na cykl (IPC), potok umożliwia wykonywanie instrukcji poza kolejnością, dzięki czemu instrukcje w dalszej części programu nie są blokowane z powodu instrukcji, której wykonanie zajmie więcej czasu. Wszystkie instrukcje są rejestrowane w buforze ponownego zamawiania, gdy są pobierane przez potok i mogą wycofać się (tj. zapisać swoje wyniki) w kolejności oryginalnego programu, aby zachować poprawność.
Wykonanie superskalarne
Superskalarny potok instrukcji pobiera wiele instrukcji w każdym cyklu zegara, w przeciwieństwie do prostego potoku skalarnego. Zwiększa to równoległość poziomu instrukcji (ILP) tyle razy, ile wynosi liczba instrukcji pobieranych w każdym cyklu, z wyjątkiem sytuacji, gdy potok jest zablokowany z powodu zależności przepływu danych lub sterowania. Chociaż szybkość wycofywania potoków superskalarnych jest zwykle mniejsza niż ich szybkość pobierania, ogólna liczba instrukcji wykonywanych w jednostce czasu (> 1) jest na ogół większa niż w potoku skalarnym.
Porównaj z architekturami procesorów zorientowanymi na przepustowość
W przeciwieństwie do tego architektura procesora zorientowana na przepustowość jest zaprojektowana tak, aby zmaksymalizować ilość „użytecznej pracy” wykonanej w znaczącym przedziale czasu. Użyteczna praca odnosi się do dużych obliczeń na znacznej ilości danych. Robią to poprzez zrównoleglenie obciążenia pracą, dzięki czemu wiele obliczeń może być wykonywanych jednocześnie. Obliczenia mogą należeć do pojedynczego zadania lub ograniczonej liczby wielu zadań. Całkowity czas potrzebny do wykonania 1 wykonania jest znacznie dłuższy niż w przypadku architektury procesora zorientowanej na opóźnienia, jednak całkowity czas wykonania dużego zestawu obliczeń jest znacznie skrócony. Opóźnienie jest często poświęcane w celu osiągnięcia wyższej przepustowości na cykl. W rezultacie procesor zorientowany na opóźnienia może wykonać pojedyncze obliczenie znacznie szybciej niż procesor zorientowany na przepustowość; jednak procesor zorientowany na przepustowość może być w połowie setek takich obliczeń, zanim procesor zorientowany na opóźnienie zakończy 1 obliczenie.
Procesory zorientowane na opóźnienia zużywają znaczną część chipa na wyrafinowane struktury kontrolne, takie jak przewidywanie rozgałęzień, przekazywanie danych , bufor zmiany kolejności , duże pliki rejestrów i pamięci podręczne w każdym procesorze. Struktury te pomagają zmniejszyć opóźnienia operacyjne i czas dostępu do pamięci na instrukcję oraz udostępniać wyniki tak szybko, jak to możliwe. Z drugiej strony architektury zorientowane na przepustowość zwykle mają wiele procesorów ze znacznie mniejszymi pamięciami podręcznymi i prostszą logiką sterowania. Pomaga to efektywnie wykorzystać przepustowość pamięci i zwiększyć łączną liczbę jednostek wykonawczych na tym samym obszarze chipa.
Procesory graficzne są typowym przykładem architektur procesorów zorientowanych na przepustowość.