wtorek, sierpnia 26, 2008

Celeron M353 900MHz vs. Intel Atom 1.6GHz, czyli o tym czemu jest remis? ;-)

Szukałem dziś w sieci porównania wydajności Asus EEE 900 z Asus EEE 901. Na pierwszy rzut oka wygląda, że EEE 901 powinien być niemal dwa razy szybszy od EEE 900 bo w EEE 901 mamy procesor Intel Atom 1.6GHz, a w EEE 900 "tylko" Celeron M353 900MHz.

Okazuje się jednak, że procesory te mają praktycznie identyczną moc obliczeniową! Z tym, że Atom w porównaniu do Celerona M praktycznie nie zużywa prądu ;p

Ciekaw byłem czemu tak jest i zacząłem studiować opisy obu procesorów w Wikipedii.

Tutaj mała dygresja historyczna ;-) Kiedyś, dawno temu [tak jakoś do czasów pierwszych Pentium chyba] procesory z rodziny x86 mówiły i myślały w języku x86. Gdy procesor dostał taki kod:
mov ax,03h
mov bx,10h
add ax,bx
int 10h
To działały w taki sposób, że do swojego kawałka zwanego rejestrem ax [a tak naprawdę od czasów 80386 do połówki rejestru eax] wrzucał wartość 3 [to h oznacza, że jest to wartość hexadecymalna, czyli szesnastkowa, ale akurat 03h to 3 ;-)], później do rejestru bx wrzucał 10h [16], następnie dodawał wartość z ax i bx, a wynik wstawiał do ax, by w końcu wywołać przerwanie 10h [16], które odpowiadało za wywołanie funkcji BIOSu związanych z trybem graficznym....... tak naprawdę wywołanie przerwania oznaczało tylko coś takiego, odłóż na stos co popadnie ;-) i skocz do miejsca którego adres wpisany jest pod pozycją 10h w tabeli przerwań.....
Ale takie rozwiązanie miało wady. Te polecenia były zbyt duże by można było je wygodnie zrównoleglać, do tego x86 miał bardzo mało rejestrów co utrudniało optymalizację jeszcze bardziej........ Dlatego uznano, że x86 się przeżył.... W każdym bądź razie na zewnątrz ;-)

Od tego momentu procesory x86 mówią, a właściwie to rozumieją w x86, ale myślą w swoich własnych RISCowych językach. Naprawdę procesor nie musi mieć w ogóle rejestru eax, może mieć za to kilkadziesiąt innych. Ważne by na zewnątrz wyglądało, że ma rejestr eax.

Kończąc dygresję ;-) W okolicach Pentium było tak, że 1 rozkaz procesora wyrażony w x86 był średnio wykonywany w 1 takcie procesora [a taktów było tyle ile wynikało z częstotliwości procesora, czyli dla 120MHz było to 120 milionów taktów]..... Nie do końca tak ;-) po pierwsze Pentium w pewnych okolicznościach umiało wykonać naraz 2 rozkazy... a po drugie wykonanie rozkazu to nie tylko jego wykonanie, a cała obróbka ;-) ale to szczegóły ;-)

Teraz jednak procesory jak mówiłem w środku są RISCami. I w tym tkwi pierwszy powód czemu 1.6GHz może być tak samo wydajne jak 900Mhz. Po prostu jeden procesor może zmienić dane rozkazy x86 w np. 20 swoich rozkazów RISC, a inny w 40. Wtedy ten z 40 rozkazami jeżeli oba wykonują 1 rozkaz na takt potrzebuje 2 razy więcej taktów.

Do tego dochodzi to, że czasem może się okazać, że szybciej wykona się dany zestaw rozkazów RISC jeżeli się je trochę poprzestawia.

Do tego dochodzi jeszcze to, że w celu przyśpieszenia pracy procesora stosuje się coś co zwie się potokiem. W końcu w procesorze jest wiele jednostek, z których jedna potrafi wykonywać obliczenia, inna potrafi wczytać rozkaz, jeszcze inna zapisać coś do pamięci, a inna odczytać. Jest tego trochę i szkoda by było żeby w czasie wykonywania pojedynczego rozkazu pracował tylko 1 kawałek procesora gdy reszta leży odłogiem, dlatego wprowadzono potok. W skrócie wygląda to tak, że gdy 1 rozkaz jest w fazie wykonywania [np. dodaje dwie wartości z rejestrów] to drugi jest w fazie zapisywania operandów do rejestrów, a inny w fazie wczytywania i tak dalej. I teraz pojawia się problem. W kodzie programów występują skoki. A skoki mają to do siebie, że często nie wykonuje się po nich kod, który leży w pamięci bezpośrednio za nimi, a jakiś inny na jaki wskazują... i jeżeli właśnie wykonaliśmy skok, to może się okazać, że cała obróbka rozkazów które obrabialiśmy w potoku była niepotrzebna, bo wykonać mamy inny kod. A to oznacza, że musimy chwilę poczekać...
I tu pojawia się predykcja skoków, czyli przewidywanie gdzie pójdziemy w momencie skoku, czyli przewidywanie czy bardziej opłaca się w potoku przetwarzać kod rozkazów za skokiem, czy tych na które wskazuje skok.... Jeżeli jeden procesor jest w tym lepszy, to nawet przy niższym taktowaniu może być w pewnych warunkach bardziej wydajny.
Do tego dochodzi jeszcze to, że przewidywanie skoków nie zawsze się udaje, a co by było gdyby część procesora próbowała wykonać kod zza skoku, a druga część kod na który wskazuje skok? Wtedy można by było w momencie uzyskania wartości decydującej gdzie wykonać skok [czyli w momencie wyliczenia wyrażenia] unieważnić niewłaściwą linię kodu i udawać, że od początku chciało się iść tą ścieżką ;-)

Tu dochodzi jeszcze to, że w procesorze możemy mieć więcej "kawałków" które np. umieją liczyć, wtedy można część rozkazów RISC przesyłać do jednej jednostki, a część do drugiej, trzeciej czy dziesiątej... z tego co pamiętam wg. teorii 6-7 to maksimum które ma sens, w praktyce to pewnie 3-4.

I to są w skrócie powody tego, że Atom 1.6GHz może mieć taką samą wydajność jak Celeron M z dużo niższym taktowaniem 900MHz.
Po prostu Celeron M to zubożona wersja Pentium M [czyli tego procesora który pogrzebał Pentium 4 [które zawaliło sprawę tym, że miało zbyt długi potok]], wraz z wszelkimi usprawnieniami takimi jak predykcja skoków, wykonywanie spekultatywne, przestawianie kolejności wykonania rozkazów, zrównoleglenie rozkazów.
Intel Atom to za to procesor, który nie ma tych ficzerów. Ale dzięki temu nie zużywa tyle prądu, bo "inteligencja" kosztuje.Przez to jego współczynnik moc obliczeniowa/MHz jest niższy niż dla Celerona M. Za to współczynnikiem moc obliczeniowa/W bije Celerona M na całej linii ;-)

Ktoś doczytał do tego momentu? ;-)


Podobne postybeta
"Powszechnie znane" prawdy o wydajności to często bujdy na resorach
.asm - to było fajne rozszerzenie plików z programami ;-)
Przesyłanie "obcych" na odległość, albo uniwersalny format danych ;-)
Amd64, Intel64, EMT64, WTF64? ;-)
C# i Java okazały się szybsza od Pythona :-) [było Java okazała się szybsza od C# i Pythona]