Конфликти проточне обраде

Из Википедије, слободне енциклопедије

У дизајну процесора, конфликти су проблеми са проточном обрадом инструкција у архитектури централне процесорске јединице када се следећа инструкција не може извршити у следећем циклусу клока.[1] Потенцијално, може доћи до добијања нетачних резултата израчунавања. Постоје три типа конфликта:[2]

  • конфликти података
  • структурни конфликти
  • конфликти контроле (гранања)

Постоји неколико метода које се баве конфликтима, укључујући одугловлачења проточне обраде (енгл. pipeline stalls), "пенушање" проточне обраде (енгл. pipeline bubbling), прослеђивање регистара и, у случају ванредног извршавања (енгл. out-of-order execution, ООЕ'), scoreboarding метода и Томасулио алгоритам.

Позадина[уреди]

Vista-xmag.png За више информација погледајте чланак Проточна обрада инструкција

Инструкције у процесору са проточном обрадом се извршавају у неколико фаза тако да се, у било ком тренутку, неколико инструкција обрађују у различитим фазама проточне обраде (нпр. fetch (донеси) и execute (изврши)). Постоји више различитих архитектура за проточну обраду инструкција и инструкције могу бити ванредне (ООЕ). До конфликта долази када две или више ових инструкција (вероватно нека ООЕ) дођу у сукоб.

Типови[уреди]

Конфликти података[уреди]

До конфликта података долази када инструкција која излаже зависност податка модификује податак у другој фази проточне обраде. Игнорисање потенцијалних конфликта може довести до стања трке (енгл. race conditions). Постоје три симулације у којима може доћи до конфликта података:

  1. Читај после писања (енгл. read after write, RAW), права зависност
  2. Пиши после читања (енгл. write after read, WAR), анти-зависност
  3. Пиши после писања (енгл. write after write, WAW), зависност излаза

Разматрамо две инструкције: i1 и i2, где се i1 дешава пре i2 по редоследу програма.

Читај после писања (RAW)[уреди]

(i2 покушава да чита извор пре него што i1 запише на податку) "Читај после писања" конфликт се односи на ситуацију где једна инструкција покушава да приступи резултату који се још увек није или учитао или израчунао. Ово се може догодити зато што, иако се једна инструкција извршила после претходне инструкције, претходна инструкција се није још увек потпуно обрадила у процесу проточне обраде.

Пример[уреди]

i1. R2 <- R1 + R3
i2. R4 <- R2 + R3

Прва инструкција рачуна вредност која се чува у регистру R2, а друга хоће да искористи ову вредност да израчуна резултат за регистар R4. Међутим, код проточне обраде, када се доносе (fetch) операнди за другу операцију, резултати из прве неће још увек бити сачувани чиме имамо зависност података.

Кажемо да постоји зависност података са инструкцијом i2, јер она зависи од тога да ли је i1 потпуно завршена.

Пиши после читања (WAR)[уреди]

(i2 покушава да пише на некој локацији пре него што је i1 прочита) "Пиши после читања" конфликт представља проблем са истовременим извршавањем.

Пример[уреди]

i1. R4 <- R1 + R5
i2. R5 <- R1 + R2

Ако се нађемо у ситуацији где постоји шанса да се i2 заврши пре i1 (нпр. код истовременог извршавања), морамо се осигурати да се сачува резултат регистра R5 пре него што i1 добије шансу да преузме операнде.

Пиши после писања (WAW)[уреди]

(i2 покушава да напише операнд пре него што га је написао i1) До "пиши после писања" конфликта може доћи у окружењу са истовременим извршавањем.

Пример[уреди]

i1. R2 <- R4 + R7
i2. R2 <- R1 + R3

Морамо одложити WB (Write Back) i2 док не дође до извршавања tt>i1.

Структурни конфликти[уреди]

До структурних конфликата долази када је двема или више инструкција, у исто време, потребан део процесоровог хардвера. Канонски пример би била једна јединица меморије којој се приступа и у фази доношења (fetch), где се из меморије тражи нека инструкција, и у фази када се податак пише и/или чита са меморије.[3] Обично ово може решити одвајањем компонената у ортогоналне јединице (као што су одвојени кешеви) или "пенушањем" проточне обраде (енгл. bubbling the pipeline).

Конфликти контроле (гранања)[уреди]

Конфликти гранања (још познати као и конфликти контроле) се дешавају, као што назив каже, када имамо гранања (односно гране). На многим архитектурама проточне обраде инструкција, процесор неће знати исход гране када је потребно да се унесе нова инструкција у проточну обраду (обично у фази доношења (fetch)).

Елеминисање конфликта[уреди]

Општи случај[уреди]

"Пенушање" проточне обраде[уреди]

Vista-xmag.png За више информација погледајте чланак Bubble (computing)

"Пенушање" проточне обраде (познато и као прекид проточне обраде или одугловлачење проточне обраде) је метод за спречавање структурних конфликта, конфликта података и конфликта гранања. Како се доносе инструкције (fetch), контролна логика одређује до ког конфликта може доћи или не. Контролна логика онда убацује NOP-ове (енгл. no operations) у проточну обраду. Тако, пре извршења следеће инструкције (која би изазвала конфликт), претходна инструкција ће иматии довољно времена да се заврши и тиме спречи конфликт. Ако је број NOP-ова једнак броју фаза проточне обраде, процесор ће бити очишћен од свих инструкција које би могле да наставе са радом без конфликта. Ово се назива "испирање проточне обраде" (енгл. flushing the pipeline). Све форме одуговлачења уводе кашњење пре него што процесор може да настави са извршавањем.

Конфликти података[уреди]

Постоји неколико главних решења и алгоритама који се користе да се реше конфликти података:

  • додавање "мехурића" проточне обраде кад год се наиђе на "читај после писања" зависност, која гарантује повећање кашњења
  • искоришћавање ванредног извршавања (ООЕ) да би се, потенцијално, спречила потреба за "мехурићима" проточне обраде
  • искоришћавање прослеђивања регистара ради коришћења података из каснијих фаза проточне обраде

У случају ООЕ, алгоритам који се користи би могао бити:

  • scoreboarding, у чијем случају ће "мехурић" проточне обраде бити потребан само тамо где нема функционалне јединице
  • Томасулио алгоритам, који искоришћава преименовање регистара и тиме дозвољавајући континуално издавање инструкција

Можемо пребацити задатак уклањања зависности података на компајлер, који онда може да попуни прикладан број NOP инструкција између зависних инструкција да би осигурао тачну операцију или реогранизовао редослед инструкција где је то могуће.

Прослеђивање регистара[уреди]

Прослеђивање укључује преусмеравање излазних података у претходну фазу проточне обраде. Прослеђивање се имплементира преусмеравањем излазних података инструкције у претходне фазе проточне обраде чим излазни подаци те инструкције постану доступни.

Пример[уреди]
Белешка: У следећем примеру, израчунате вредноси су означене болдовано док бројеви регистара нису.

На пример, рецимо да желимо да упишемо вредност 3 у регистар 1 (који већ садржи вредност 6) и да онда додамо 7 регистру 1 и ускладиштимо резултат у регистар 2:

Инструкција 0: Регистар 1 = 6
Инструкција 1: Регистар 1 = 3
Инструкција 2: Регистар 2 = Регистар 1 + 7 = 10

После извршавања, регистар 2 би требало да садржи вредност 10. Међутим, ако иструкција 1 не напусти проточну обраду у потпуности пре него што инструкција 2 почне извршавање, онда регистар 1 неће садржати вредност 3 када инструкција 2 обави своју функцију сабирања. Овако, инструкција 2 додаје 7 на стару вредност регистра 1 (6) тако да ће сада регистар 2 садржати вредност 13:

Инструкција 0: Регистар 1 = 6
Инструкција 2: Регистар 2 = Регистар 1 + 7 = 13
Инструкција 1: Регистар 1 = 3

До ове грешке долази зато што инструкција 2 чита регистар 1 пре него што је инструкција 1 сачувала резултат своје операције писања у регистар 1. Када инструкција 2 прочита садржај регистра 1, регистар 1 ће и даље садржати 6, а не 3.

Прослеђивање (описано доле) помаже исправљању оваквих грешака јер излазни податак инструкције 1 (који је 3) може користити следећа инструкција пре него што се вредност 3 сачува у регистар 1.

Прослеђивање које се примењује у нашем примеру значи да ми не желимо да чекамо на складиштење излазних података инструкције 1 у регистру 1 (у овом примеру, излазни податак је 3) пре него што тај излазни податак постане доступан следећој инструкцији (у овом случају, инструцији 2). Добијени ефекат је да инструкција 2 користи тачну (последњу) вредност регистра 1, односно, складиштење је обављено непосредно и није проточно обрађено.

Са укљученим преусмеравањем, фаза за декодовање/извршавање инструкција (енгл. Instruction Decode/Execution, ID/EX) сада има два улазна податка: вредност учитану из регистра (у овом примеру вреност је 6) и нову вредност регистра 1 (у овом примеру вредност је 3), који је прослеђен са следеће фазе извршавања/меморијског приступа инструкција. Додатна контролна логика се користи да одреди који улазни податак се користи.

Конфликти контроле (гранања)[уреди]

Да би се избегли конфликти гранања архитектуре могу:

  • убацити "мехурић" проточне обраде (више о томе изнад), што гарантује повећање кашњења
  • користити предикцију грана(ња) и у суштини направити нагађања о томе које инструкције да убаци. У том случају би "мехурић" проточне обраде био потребан само у случају лоше предикције.

У случају да грана изазове "мехурић" проточне обраде пошто су некоректне инструкције ушле у проточну обраду, мора се водити рачуна о спречавању да било каква погрешно учитана инструкција има ефекат на стање процесора (искључујући узалудну обраду инструкција пре него што је откривено да су учитане погрешне).

Види још[уреди]

Референце[уреди]

  1. ^ Patterson & Hennessy (2009), стр. 335.
  2. ^ Patterson & Hennessy (2009), стр. 335-343.
  3. ^ Patterson & Hennessy (2009), стр. 336.

Литература[уреди]