Поглед в процесора – на какво се дължи различната производителност?
Едва ли има човек, на когото да не се е случвала ситуацията, в която е поставен да избира какъв процесор да си купи. Допреди няколко години нещата около този избор бяха дори още по-сложни, тъй като прякото съпоставяне на отделните модели на AMD и Intel беше невъзможно поради огромните разлики в честотите, на които работеха. Въпреки тези разлики като цяло производителността на моделите от еднакъв клас беше съпоставима и този факт объркваше много хора – което и стана причина за въвеждането на известната PR стратегия на AMD. Макар и да не беше харесвана от много хора, на практика PR рейтингите на процесорите на AMD до известна степен улесни купувачите в избора на нов процесор, тъй като направи възможно съпоставянето на отделните модели. Въпреки това доста често се срещаха „разбирачи“, според които неизмеримо по-високата честота на Intel-ските процесори беше сигурен залог за по-високата производителност. Че това не е така, вече е ясно на всеки – но каква е причината?
В тази статия ще разясним принципните положения около работата на един процесор, архитектурата, по която е построен, както и хитрините, прилагани от производителите с цел повишаване на неговата производителност.
![]()
Именно благодарение на тези хитрини вече повече от 20 години процесорите не са подложени на по-сериозна промяна, която според предвижданията от миналия век вече трябваше да е наложителна. Преди да пристъпим към разглеждането на тези хитрини и резултатите от тях, нека първо видим какво е най-основното и общо в дизайна на всички х86 (а и не само на тях) процесори, останало непроменено през всички години на тяхното съществуване.
Запознайте се с фон Нюман
Погледнато като цяло, компютърните процесори в момента са изградени с използването на математически модел, разработен преди повече от сто години от математика Джон фон Нюман. В този модел процесорът на системата и паметта, с която той оперира, представляват отделени един от друг модули, като към тях не влиза общата оперативна памет на системата. Първите версии на фон Нюмановата архитектура се използват в появилите се през 70-те и 80-те години електронни устройства и уреди с фиксирана функция (например калкулатори). При този тип уреди процесорът се контролира изцяло от декодиращия модул, като на разположение имаме само няколко фиксирани операции, които можем да извършим с него.
![]()
Първоначално този модел е неподходящ за употреба в универсалните персонални компютри, тъй като не притежава необходимата гъвкавост за изпълнение на произволни задачи. Тази ситуация се променя напълно с представянето на концепцията Instruction Set Architecture (ISA), в която чрез стандартен за процесорите набор от инструкции потребителят може да изпълни почти всяка задача. Споделянето на обща ISA е напълно възможно от различните модели процесори, което и може да се онагледи чрез сравняването на моделите Pentium и Athlon съответно на Intel и AMD. Макар и в същината си тези процесори да са различни един от друг, използването на общ ISA набор (в случая дериватив на х86) позволява на процесорите да изпълняват общ и за двата вида софтуерен код.
Един от най-основните недостатъци на фон Нюмановата архитектура се явява „тясното място“ в шината за комуникация между процесора и системната памет, където се съхраняват данните и инструкциите, които следва да се изпълнят. Този проблем е наличен дори до днес, когато тактовата честота, с която работят процесорите, надхвърля няколко пъти скоростта, с която системната памет е способна да достави необходимите им данни. Преодоляването на този проблем представлява предизвикателство за производителите още от самото създаване на персоналните компютри като такива и разграничаването на скоростта на процесора от тази на останалата система.
За заобикалянето на това тясно място в системата дизайнерите на системи започват да използват на кеш памет от първо, второ, а напоследък дори и трeто ниво, функцията „branch-prediction“ (буквално „предсказване на преходите“), удължаване на конвейра, въвеждане на суперскаларност, увеличаване на броя ядра и др.
Как работи процесорът?
Преди да разгледаме различните хитрости, използвани с цел ускоряване на работата на процесора, нека обърнем за кратко внимание на няколкото прости стъпки, чрез които той работи. Казано най-просто, същността на работата на всеки един процесор (дори графичните) се състои в последователното изпълняване на отделни инструкции, обединяването на които съставлява програмния код като цяло. Самите инструкции могат да притежават най-разнообразна форма, като се започне от елементарното събиране на стойностите, намерени в посочен в инструкцията адрес от паметта, до делението им или преход към друг адрес, където се намира следващата инструкция. Като цяло операциите са разделени в 4 стъпки, като схемата е валидна за 99% от процесорите, използващи архитектура на фон Нюман. Тези стъпки са следните: извличане на инструкцията (fetch), декодиране, изпълняване и обратен запис на резултатите към I/O модула.
Първата стъпка – извличане на инструкцията, се осъществява от специален модул, занимаващ се единствено с тази задача. Адресът в паметта, откъдето той извлича данните, записан в кода на самата програма, който от своя страна буквално се следи от програмен брояч (ПБ). Положението на процесора в течащата програма се управлява и контролира от ПБ, като след всяка извършена операция той прави стъпка напред към следващия цикъл. След като инструкцията бъде извлечена от паметта, тя се предава към модула, занимаващ се с нейното декодиране. Декодиращият модул разделя инструкцията на няколко части, които се подават на съответния Arithmetic Logic Unit (ALU) модул за изпълнение. Във фрагментите на самата инструкция се съдържат както операциите, които следва да се извършат от ALU, данните, с които да се работи, така и адресите, в които да се запишат готовите резултати.
При третата стъпка – изпълнение на кода, модулите ALU или FPU (Floating Point Unit) изпълняват посочените в инструкцията действия, след което при последната, четвърта стъпка записват резултатите в посочените в инструкцията координати. За ускоряването на тези 4 стъпки има много варианти, всеки от които пряко свързан с тясното място на фон Нюмановата архитектура. Първият и най-широко навлязъл метод е въвеждането на конвейерното изпълнение на инструкциите (pipelining).
Инструкции на конвейeр – NetBurst
Един от най-ярките представители на доведената до крайност конвейeрна архитектура е именно дизайнът на процесорите на Intel от предишното поколение – става въпрос именно за моделите, използващи т.нар. NetBurst. Този дизайн е следствие на един от опитите за избягване на тясното място в комуникацията между процесора и останалите елементи на системата, в частност паметта.
За да представим нагледно идеята за конвейeрното изпълнение на инструкциите в процесора, най-просто можем да си представим ситуацията по следния начин: преминаването на инструкцията през 4-те основни стъпки изисква 4 такта от честотата на процесора. В случай че не разполагаме с конвейeрно изпълнение, във всеки един от 4-те такта процесорът е изцяло зает с една-единствена инструкция, макар и от 4-те му модула (fetcher, decoder, ALU/FPU, writeback) да се използва само по един във времето. След като инструкцията бъде извлечена и предадена на декодера, извличащият модул трябва да изчака 3 такта, докато инструкцията премине по цялата верига, преди да извлече следващата порция. Въвеждането на конвейeр елиминира този момент, като във 2-рия такт от 4-те стъпки извличащият модул прихваща следващата порция от данните. Тъй като в 3-тия такт декодиращият модул вече е предал инструкцията за изпълнение към двойката ALU/FPU, той е свободен да приеме извлечената във 2-рия такт инструкция.
Обикновено дълбочината на конвейeра в различните процесорни архитектури варира, като в последните поколения се движи от 10 за Pentium 3 до невероятните 31 за последния представител на семейство NetBurst, използващ ядро Prescott. Именно повишеният брой на стъпките в конвейeра на Prescott позволява на Intel да извиси тактовата му честота до невероятните 3+GHz. Най-просто казано, по-дългият конвейeр позволява по-безпроблемна комуникация между модулите, занимаващи се с обмена на данните между процесора и външните елементи.
За съжаление удължаването на конвейeра има и един много голям недостатък, свързан с модула, занимаващ се с предсказването на бъдещите операции (branch prediction unit). Поради увеличената дължина на конвейера изпълнението на излишна инструкция ще забави процесора с повече време, Intel усъвършенстват алгоритмите на работа на модула за предсказване на преходите. Въпреки това грешка в неговата работа означава сериозна загуба на процесорно време, тъй като, колкото е по-дълъг конвейерът, при появата на грешка или излишни операции се налага изчистването и повторното въвеждане на данни в толкова повече клетки.
Реално погледнато, единствените области, в които един процесор може да се възползва без проблем от конвейер със значителна дълбочина на стъпките, е кодирането или декодирането на мултимедиа. Тъй като там branch prediction модулът има огромна успеваемост на своята работа, процесорът работи при почти 100% заетост на своя конвейер, което се изразява в значително по-малкото на брой излишни нейни цикли. За съжаление в реалната употреба подобно приложение е силно ограничено, което, както се вижда, се отрази негативно на NetBurst подхода. Това се дължи на факт, че в приложения от сорта на 3D моделиране или игри преходите и операциите са значително по-разнообразни, вследствие на което branch prediction модулът не постига добра успеваемост на предсказанията си.
Тук именно се корени и една от най-големите разлики между процесорите от тези години – макар моделите на AMD да бяха с почти два пъти по-ниска тактова честота, тяхната производителност беше равна или дори по-висока от тази на моделите на Intel. Причината за това се крие в по-краткия брой стъпки в конвейера на K7, наброяващи едва 10 за ALU и 15 за FPU модула. Благодарение на по-малкото стъпки в конвейера процесорите с К7 архитектура могат да изпълняват повече инструкции за такт, макар и при по-ниска тактова честота. В допълнение към това една евентуална грешка на branch prediction модула не би имала толкова голямо влияние върху производителността поради по-малкото на брой грешни стъпки, които ще се извършат от процесора.
Суперскаларни процесори
Суперскаларните процесори представляват първата стъпка към въвеждането на паралелната обработка на данни, по-късно прерастваща в добавянето на още ядра в кристала на чипа. На практика суперскаларната работа на един процесор означава, че той е способен да работи едновременно с повече от една инструкция за такт. Макар да е в пряко отношение към конвейерната обработка на инструкциите, суперскаларността е напълно отделна от нея технология и не бива да се бъркат двете техники. Обикновено суперскаларното изпълнение на инструкциите се постига чрез добавянето на определени допълнителни модули (но не цялостно дублиране на целия процесор), които могат да се използват и за други цели.
По време на работа изпълнението на повече инструкции се осъществява, като се използват модули, които за момента не са активни, макар и да имат друго предназначение. Като подобен случай може да се посочи използването на математическия копроцесор за изпълнение на някои операции с цели числа. В някои случаи това позволява постигането на суперскаларна архитектура почти без добавяне на допълнителни модули освен изискващите се за контрол на операциите и проверка на зависимостите (което е от голямо значение).
Въвеждането на суперскаларната работа на процесорите предизвиква парадокс от гледна точка на изпълняващия се на тях програмен код. В подобен случай става възможна ситуация, при която резултатите от инструкция, изпълнявана на единия конвейер на суперскаларен процесор, да са в противоречие с тези на данните от втория конвейер. Подобен случай би могъл да причини доста главоболия на програмистите, ето защо в процесора са въведени специфични модули, следящи за зависимостите между различните инструкции и резултатите от тяхното изпълнение, както и обезпечаващи правилното записване на данните в паметта, за да се избегне припокриване.
На теория въвеждането на суперскаларността би трябвало да повиши поне 2 пъти производителността на процесорите, но както често се случва в практиката, това съвсем не е така. За да може напълно да се използват възможностите на един суперскаларен чип, изпълняваният на него софтуер трябва да е предвиден и написан специално за тази цел. За съжаление това е невъзможно, тъй като, за да се запази обратната съвместимост с по-старите модели процесори, програмите не могат да се напишат по такъв начин.
Кеш памет
Както вече споменахме в началото, един от основните недостатъци на архитектурата на фон Нюман е наличието на тясно място в комуникацията между процесора и паметта на системата. Тъй като употребата на изключително бърза памет със скорост, равна на тази на процесора, е неоправдано от икономическа гледна точка, производителите разработват друга система – кеш паметта. Тя представлява изключително бърза памет с малък обем, намираща се на кристала на самия процесор (за сегашните и близки процесорни поколения), работеща със същата тактова честота като него.
Според вида и предназначението си кеш паметта може да е от първо (L1), второ (L2) или трето (L3) ниво, но нейната задача винаги е една и съща – да предотврати изчакването на процесора, докато изисканите от него данни се доставят от бавната системна памет. Разбира се, в кеш паметта не се съхраняват същинските данни, а инструкциите, опериращи с тях. Според вида и логиката на организация на кеша тя може да задържа вече използваните инструкции определен брой процесорни цикли, тъй като те биха могли да потрябват отново. В допълнение към това кеш паметта е в пряко взаимодействие с branch prediction модула – инструкциите, които според него се очаква да бъдат изпълнени скоро, биват извличани предварително, а данните от тях се записват в кеш паметта на процесора.
Бъдещето
Както стана ясно от изоставянето на NetBurst в полза на Core 2 от страна на Intel, бъдещето явно ще бъде не в увеличаване на тактовата честота за сметка на по-дълбок конвейер, а в повишаването на паралелизма на изпълнение. Въвеждането на суперскаларни процесори, едновременно изпълняващи 4 или повече инструкции за такт, заедно с повишаването на броя ядра в системата сочи недвусмислено пътя, по който ще поемат производители като Intel и AMD. За момента Intel отново притежава водещото място по отношение на производителността на процесорите, тъй като комбинирането на опита, придобит от NetBurst, с по- късия конвейер доведе до наистина впечатляващ скок в производителността. Очакваният след няколко месеца Nehalem ще покаже какви са възможностите на моделите с 4 ядра при 45nm технология, а с какво ще отговори AMD можем само да гадаем. Във всеки случай посоката е ясна – повишаване на броя паралелно изпълнявани инструкции, остава да се изясни само начинът за постигането му.