Последната актуализация на този раздел е от 2021 година.

 

6.1.1  Регистрова памет

 

 

      Регистровата памет, като върхов структурен елемент в йерархията на запомнящата система (вижте фигура 6.1.1), се реализира върху кристалната подложка на процесора, т.е. говорим, че тя е изпълнена в елементната база на процесора. Регистрите, които са свързани със структурата и с обслужването на АЛУ, обикновено имат размерите на разрядната мрежа (вижте глава 3, пункт 3.8.1 и 3.8.2). Наборът от регистри с общо предназначение може да бъде организиран като запомнящо устройство с произволен достъп. Съществуват реализации, в които наборът от такива регистри е организиран като запомнящо устройство с последователен достъп (като например в АЛУ за работа с плаваща запетая). Обемът на отделните набори регистрова памет е малък, най-често в пределите максимум до 128 клетки за тези с общо предназначение или в обем, определен според функционалното предназначение и вида на устройството в чиято структура се намират.

      Поради малкият обем на регистровата памет, достъпът до нейните клетки се осъществява с адрес, който има много малка дължина - 4, 5 бита. Това води до намаляване на дължината на машинните команди, адресиращи тези клетки, а от там и до намаляване на обема на програмите. Регистровата памет осигурява на операционните и на функционалните устройства възможно най-бързия достъп до необходимите им данни. От една страна това се дължи на непосредствената близост, т.е. на късите логически връзки, а от друга страна на еднотактните микрооперации четене и запис. В резултат на всичко това се получава допълнителен ефект, изразяващ се в повишаване на скоростта на изчислителния процес.

      Регистрите с общо (и/или специално) предназначение се използуват от програмиста най-често за временно съхраняване на данни, представляващи междинни резултати (начални стойности, служебни данни, константи, адреси или части от адреси) или най-общо казано информация, до която е необходим възможно най-бърз достъп. По тази причина регистрите с общо предназначение се определят като програмно достъпни. Освен това обикновено в системата машинни команди съществува група специални команди за работа с тези регистри. Поради непосредствената връзка на тези регистри с операционните устройства, командите за работа с тях могат да реализират често необходими действия (операции) върху тяхното съдържание. Така например, за тези регистри са обичайни операциите от вида инкремент (декремент) на съдържанието (+1), (-1), запис на нула, прехвърляне на съдържанието от един в друг регистър, зареждане с начални стойности и други операции, специфични за всеки отделен процесор. Тези възможности ги правят удобни за използване и в качеството им на базови, или на индексни регистри, което улеснява програмиста при реализация на необходимите му алгоритмични структури. Машинните команди, които адресират операндите си в регистрите с общо предназначение бяха определени като команди от тип регистър/регистър (вижте глава 3, пункт 3.8.2).

      При програмиране на дадена задача, обикновено отсъства априорна информация за честотата, с която данните ще се използуват в процеса на изчисляване, а това затруднява оптималното натоварване на регистровата памет. Особена сложност придобива този проблем при автоматизираното програмиране, когато машинните програми се съставят по алгоритми, записани в термините на процедурно-ориентираните езици. Във връзка с това, регистровата памет може ефективно да бъде използувана само на нивото на стандартните и системните подпрограми.

      Може да се твърди, че големият брой оператори от тип <за присвояване> , които представляват съществения дял в една програма, изискват от процесорите в които се реализират, специална организация за бърз достъп до операндите. Тъй като голяма част от операндите представляват стойности на локални и в същото време скаларни променливи, няма нищо по-естествено отговарящо на изявеното изискване, от извода за увеличен брой на регистрите с общо предназначение. Освен тях в процесорите винаги съществува и неголяма група регистри, които са предназначени да съхраняват стойностите на глобални променливи. За програмиста това означава, че той следва да прилага такава политика (стратегия), която би довела до максимално използване на регистровата памет (както в смисъла на нейния обем, така и във времето) и би довела още до минимизиране броя на операциите за трансфер на данни между оперативната и регистровата памети. Тъй като съвременният приложен програмист е освободен от задачата за разпределение на паметта, задачата за ефективното използване на регистровата памет се възлага на компилиращите програми. В същото време обаче, в противоречие с желанието за по-голям обем на регистровата памет, влиза желанието за бърз преход от един набор променливи към друг набор променливи. Такава подмяна на съдържанието на цялата регистрова памет се налага при преход към подпрограма и обратно при връщане от подпрограма. Използването на голям обем регистрова памет би довело в този случай до значително забавяне на преходите, вследствие на продължителното “спасяване" (съхраняване) и възстановяване на съдържанието на регистровата памет в/от програмния стек.

A)  Техника на регистровите прозорци

      Описаното по-горе противоречие някои процесори се опитват да преодолеят чрез така наречената техника на регистровите прозорци. Техниката на регистровите прозорци се постига чрез допълнителни апаратни разходи и нови специални алгоритми за управление на регистровата памет. Тази техника се основава на статистическите оценки и изводи, че в болшинството случаи подпрограмите (като декомпозиционни инструменти) използват неголям брой локални параметри и връщат най-често още по-малък брой резултантни стойности. Така възниква идеята за частично предаване в разпореждане на програмната единица на част (област) от регистровата памет, достатъчна по обем, с която тя може да работи. Тази именно област се нарича регистров прозорец. При извикване на поредната подпрограма, процесорът следва автоматично да заделя за нея нов регистров прозорец и да ѝ го предоставя за трансфер на действителните параметри и резултати, вместо да обработва цялата регистрова памет чрез стека. Регистровите прозорци на вложените подпрограми частично се припокриват, тъй като автоматичното предаване на параметрите в извиканата подпрограма изисква някои от регистрите да влизат в състава на два регистрови прозореца.

      Описаната техника е илюстрирана на фигура 6.1.1.1.

 

Фиг. 6.1.1.1.  Припокриване на регистровите прозорци

 

      По време на изпълнение на програмата процесорът “вижда” само един регистров прозорец. Така той може да се обръща (чете и записва) единствено към регистрите, принадлежащи на този текущ прозорец. Можем да приемем, че относителните им адреси са техните номера (от 0 до N-1), където с N е означен техният брой. Регистровият прозорец се състои от три части:

       1. Област за параметрите на извиканата подпрограма от ниво №k (действителни) – предавани и връщани ;

       2. Област на локалните променливи. Тук подпрограмата съхранява стойностите на вътрешните (работни) променливи. Таблицата на съответствие на всеки от тези регистри се съставя от компилатора ;

       3. Област за временни стойности. Тази област от текущия прозорец (ниво № k) е предназначена за връзка с евентуално извикана от текущата подпрограма следваща подпрограма (т.е. следващото ниво № k+1). За извиканата подпрограма (от следващото ниво) областта за временни стойности в текущата (викащата) подпрограма се явява областта на параметрите, т.е. мястото през което се предават действителните параметри и се връщат получените резултати. Именно това припокриване на регистровите прозорци позволява предаване на параметрите в подпрограмата без да се изпълняват фактически операции по трансфер на данни (вижте по-горе фигура 6.1.1.1).

      За да е възможно използването на тази техника при произволна последователност от извиквания и връщания в една приложна програма, броят на регистровите прозорци не трябва да бъде ограничен. Тъй като това изискване е практически нереализуемо, регистровите прозорци осигуряват определен брой от последните най-дълбоко вложени подпрограми. Всички предидущи нива, с по-малки номера, използват оперативната памет. Те започват да използват регистровата памет когато нивото на вложеност се понижи. Описваната техника за използване на регистровата памет наподобява работата на кръговия буфер, която ние описахме тук в §4.3.

      Като пример ще поясним кръговата организация за управление на 6 регистрови прозореца (k=6) чрез рисунката от фигура 6.1.1.2.

 

Фиг. 6.1.1.2.  Кръгова схема на 6 регистрови прозореца с ниво на вложеност 4

 

      Приемаме, че при изпълнението на програмата текущото ниво на вложени една в друга подпрограми е 4 – П1®П2®П3®П4 (вижте например фигура 2.1.4). Така текущо активната подпрограма е П4. За да бъде видим (адресируем) регистровият прозорец на тази подпрограма е необходим регистър, съдържащ указател – указател на текущия прозорец CWP (Current Window Pointer). Обръщението към определен регистър се осъществява по физически адрес, чиято стойност се определя по закона на относителното адресиране. Това означава, че съдържанието на указателя CWP се събира с номера на регистъра в прозореца, т.е. Адр=(CWP)+№Рг. Съдържанието на указателя на текущия прозорец представлява отместването на текущия прозорец спрямо началото на регистровата памет. Последното се определя автоматично при извикването на подпрограмата като сума от предидущото отместване и обема на регистровия прозорец. Ако се приеме всички прозорци да са с еднакъв обем, то при преминаване от един прозорец в друг този указател ще се модифицира с константа. Тогава е удобно тя да се приема като модул за броене.

      В логическата структура на регистровата памет следва да се съдържа още един регистър-указател – указател на съхранения прозорец (SWP). Този указател сочи началото на регистровия прозорец, съдържанието на чиито регистри са съхранени в стека последно. Необходимостта от използването на стека ще обясним така: ако подпрограма П4 извика подпрограма А, като следващо (5-то) по вложеност ниво, то параметрите на тази подпрограма ще бъдат поместени в областта на временните регистри на П4, а съдържанието на указателя CWP ще бъде увеличено с броя на регистрите, заделени за П4, т.е. този указател ще се придвижи на един прозорец напред по кръговата схема (вижте по-горе фигура 6.1.1.2). Ако подпрограма А от своя страна се опита да извика подпрограма Б като следващо ниво на вложеност, това няма да бъде възможно, тъй като прозорецът й се припокрива с този на вече извиканата П1. Ако все пак подпрограма Б бъде извикана като П6, то тя ще разположи областта на временните си стойности върху входните на П1, с което ще ги повреди, което естествено не е редно. Ето защо, когато съдържанието на указателя CWP бъде модифицирано и се изравни с това на указателя SWP, ще възникне апаратно прекъсване (вижте поясненията свързани с фигура 4.3.2 и фигура 4.3.3). При обработването на това прекъсване съдържанието на “застигнатия” регистров прозорец П1 ще бъде съхранен в стека, след което съдържанието на указателя SWP ще бъде инкрементирано. На запис в стека подлежат само регистрите от областта на входните и на локалните параметри.

      Алгоритъма за управление на регистровата памет при връщане от подпрограма е аналогичен, но в обратна посока. Например, след връщане от подпрограма Б и всички преди нея (А, П4, П3, П2), за да се активира подпрограма П1, следва нейният прозорец да се възстанови от стека. Така се отнема препълването на кръговата схема на регистровите прозорци. При връщане, указателят CWP се движи в обратна посока. Когато подпрограма П2 поиска връщане към подпрограма П1, указателят CWP се модифицира за пореден път, при което съдържанието му се изравняване на с това указателя SWP. В резултат на това се генерира прекъсване. Обслужващата това прекъсване програма възстановява прозореца на подпрограма П1 в регистровата памет.

      В заключение ще обобщим, че техниката на регистровите прозорци (k на брой) осигурява ниво на вложеност k-1. Известни са изследвания на научни колективи, които твърдят, че при k=8 и N=16 съхраняване на регистрови прозорци в стека се налага едва в 1% от извикванията на подпрограми в работещи приложения.

Б)  Глобални променливи

      Описаната по-горе техника за използване на регистровата памет осигурява ефективното й използване от страна на локалните променливи на подпрограмите. Тя обаче не отчита факта, че много подпрограми работят с глобални променливи.

      Глобални променливи са онези променливи, които са “видими” за по-голям брой подпрограми включително и главната, което се постига чрез съответното им деклариране. Последното позволява използването на едно и също име (адрес) на променливата в отделните и самостоятелни текстове на подпрограмите. Всъщност става дума за стойност, която се използва (чете/записва) чрез един и същи адрес (име) и точно в това се състои проблемът. Осигуряването на глобалния достъп обикновено е задача на компилатора. Той я решава като съставя отделна таблица за съответствие, в която на глобалните променливи се назначават адреси не в регистровата памет, а в оперативната памет. Така за машинните команди, чиито операнди са глобални, се назначават само методи за адресиране в основната памет. В случаи когато глобалните променливи се използват интензивно, обръщенията към оперативната памет снижават производителността на изчислителния процес. Така ползата от регистровата памет не може да бъде реализирана.

      Алтернативата на описаното разпределение на променливите в оперативната памет е разпределението в регистровата памет. Глобалността на променливите обаче изисква отделен (общ) регистров файл. Номерата (адресите) на глобалните регистри трябва да бъдат фиксирани и достъпът до тяхното съдържание трябва да бъде разрешен за всяка подпрограма.

      Регистровият файл в структурата на процесора може да бъде и един. Това обаче налага неговото структуриране. Например, предназначението на първите 8 регистъра може да бъде фиксирано за съхраняване на стойностите на глобални променливи, а следващите регистри – за техниката на регистровите прозорци:

 

 

      Номерата на тези регистри могат да се интерпретират като отместване спрямо значението на указателя на текущия регистров прозорец. Разбира се структурирането на регистровия адрес усложнява дешифриращата схема, а компилаторът се натоварва с допълнителната задача да избере кои от глобалните променливи ще разпредели в регистровата памет и кои – в оперативната.

В)  Регистрова памет срещу кеш памет

      Регистровата памет с голям обем и техника на регистровите прозорци фактически работи като свръх оперативен буфер за съхраняване на интензивно използвани променливи. В този смисъл функциите на регистровата памет са сходни с функциите на кеш паметта. Така възниква въпросът коя структура е по-добра. За всяка от възможностите съществуват както достойнства, така и недостатъци. Например:

·         Съвкупността от регистрови прозорци позволява съхраняването на всички локални променливи на текущите k-1 подпрограми. В кеш паметта се съхраняват онези скаларни променливи, към които в последно време е извършвано обръщение. Така регистровите прозорци осигуряват по-бърз достъп до данните. В същото време кеш паметта осигурява по-ефективно използване на паметта, тъй като нейното запълване е следствие от реалната динамика в програмата. Освен това управлението на кеш паметта не се интересува от вида на данните.

·         При работа с регистровата памет има вероятност от непълно използване на регистровите прозорци, тъй като отделните подпрограми използват различен брой локални променливи. В кеш паметта също има излишество – съхраняват се повече данни, тъй като те се четат по блокове от оперативната памет.

·         Глобалните променливи се съхраняват в кеша така като и локалните. Обикновено в програмите има достатъчно много глобални променливи, но не към всички от обръщението е интензивно. Тъй като съдържанието на кеша отразява динамиката на изчислителния процес, то в кеш паметта се оказват именно тези глобални променливи, които имат висока честота на използване. В същото време при използване на глобални регистри, задачата за поместването в тях на подходящите променливи се възлага на компилатора, а това за него не е естествена задача.

·         Алгоритъмът за съхраняване/възстановяване на данните от регистровите прозорци се основава на текущото ниво на вложеност на подпрограмите. Тъй като дълбочината на влагане обикновено се изменя в тесни граници, то обръщение към оперативната памет се налага да се извършва рядко. В същото време, типичната структурна организация на кеш паметта е частично асоциативна и размерът на рамката е сравнително малък (вижте фигура 6.3.2.10). Така в нея съществува опасност нужните променливи да бъдат изместени от други данни или машинни команди.

      Казаното до момента означава, че нито един от обсъжданите по-горе техники за организация на регистровата памет не може да бъде признат за безусловно по-добър. Все пак съществува една характеристика, според която техниката на регистровите прозорци има безспорно предимство по бързодействие, в сравнение с кеш-паметта. Става дума за допълнителните апаратни разходи, свързани с определяне на адреса на операнда – регистров или оперативен. Сравнението в този именно смисъл е илюстрирано на следващата фигура 6.1.1.3.

 

 

 

Фиг. 6.1.1.3.  Адресен достъп до скаларни данни

 

      Адресирането на скаларен операнд в регистровата памет се постига чрез “виртуалния” номер на регистър, който го съдържа. Физическият адрес на регистъра в текущия прозорец се получава апаратно (вижте рисунка А)). В същото време алтернативата е в пълноразрядният оперативен адрес (вижте рисунка Б)), който минава през “невидимата” кеш памет, и ако данните се съдържат в нея, могат да бъдат доставени сравнително бързо. Въпреки очевидното предимство на регистровата памет, реалните процесори комбинират използването ѝ съвместно с това на кеш паметта.

      Провеждани са различни научни изследвания и експерименти, целящи да бъде определена оптималната в някакъв смисъл логическа структура на регистровата памет. Получените резултати са сходни и показват, че бързодействието и производителността на процесорите се влияят положително от наличието в логическата им структура на регистрова памет, като нейният обем не е голям и най-често е в размер до 32 регистъра. Все пак на практика се срещат структури, в които има отклонения от това правило. В съвременната 64-битова архитектура IA-64 имаме следния внушителен набор от регистри, илюстриран на следващата фигура.

 

Фиг. 6.1.1.4.  Регистров набор на архитектурата IA-64

 

      Освен показаните набори в архитектурата на процесора се съдържат и други регистри с фиксирано предназначение, като например:

·         Current Frame Marker (CFM) ;

·         Instruction Pointer (IP) ;

·         Control and Status registers ;

·         19 Application registers (AR) ;

·         User Mask (UM) ;

·         CPU Identifiers (CPUID) ;

·         Performance Monitors (PMC,PMD) .

 

 

 

Следващият раздел е:

 

6.2.  Особености в структурата на основната памет