Vous êtes sur la page 1sur 16

Capítulo 1

Paralelismo a nivel de instru ión

1.1. Introdu ión

El tiempo de eje u ión de un programa sabemos que depende del número de instru iones,
del número de i los por instru ión y de la dura ión del i lo, según la siguiente expresión:

Tejecución = N I × CP I × Ciclo

Para una determinada arquite tura y una apli a ión, tanto el número de instru iones omo la
dura ión del i lo son jos, on lo que el úni o fa tor sobre el que se puede in idir para redu ir
su tiempo de eje u ión es el número de i los por instru ión. Sin embargo, el número de i los
por instru ión está dire tamente inuen iado por el número de i los de deten ión que tiene
esa apli a ión en esa arquite tura. Como sabemos, este número de i los por instru ión
depende del CPI base del pro esador y del número de i los de deten ión en media por
instru ión. Éstos, a su vez, son las deten iones (SCPI) que provo a el au e del pro esador
y las que provo a la jerarquía de memoria.

CP I = CP Ibase + (SCP Iprocesador + SCP Imemoria )

En otras asignaturas anteriores se ha estudiado detalladamente ómo redu ir el número de


i los de deten ión que supone la jerarquía de memoria. En lo que sigue, salvo que se indique lo
ontrario, vamos a suponer que la jerarquía de memoria no introdu e deten iones, y nos vamos
a entrar en las deten iones que introdu e la eje u ión de las instru iones en el pro esador.

Como también se ha estudiado en asignaturas anteriores, la segmenta ión mejora el ren-


dimiento mediante la superposi ión de la eje u ión de varias instru iones de forma que éstas
utili en re ursos distintos del pro esador en los mismos i los de reloj. De esta forma se di-
vide el au e del pro esador en distintas etapas o segmentos y en ada uno de ellos tenemos
instru iones distintas. El sistema fun iona de forma sín rona de manera que las instru iones
van pasando por las distintas etapas uando están listos los re ursos que le ha en falta a la
instru ión en esa etapa. Si los re ursos no están disponibles la instru ión debe esperar y
por tanto se provo a uno o más i los de deten ión. Evidentemente, estos i los de deten-
ión de rementan las presta iones del pro esador pues ha en que la apli a ión tarde más en
eje utarse de lo que es estri tamente ne esario.

19
20 CAPÍTULO 1. PARALELISMO A NIVEL DE INSTRUCCIÓN

Este solape poten ial entre las instru iones se llama paralelismo a nivel de instru ión
(ILP), ya que las instru iones pueden eje utarse en paralelo. Sin embargo, el ILP se ve di-
re tamente limitado por las dependen ias entre instru iones. Buena parte de estos i los de
deten ión son debidos a riesgos de datos por distintos tipos de dependen ias entre las instru -
iones. Así pues, para in rementar las presta iones va a ser fundamental eliminar el máximo
posible de dependen ias para obtener el máximo número de instru iones independientes.

El objetivo de la mayoría de las propuestas que se van a estudiar a lo largo de esta


asignatura es redu ir el número de i los de deten ión por instru ión para aumentar así las
presta iones del sistema.

Así pues, sin tener en uenta la jerarquía de memoria, el número de i los por instru ión
en un pro esador segmentado es la suma del CPI base y las deten iones por instru ión que
provo an los distintos tipos de riesgos:

CP I = CP Ibase + (SCP Iestructurales + SCP Iriesgos datos + SCP Iriesgos control )

El CPI ideal es una medida de las presta iones máximas al anzables por una implementa ión
dada. Mediante la redu ión de las deten iones que introdu en los distintos tipos de riesgos, se
puede minimizar el número de i los por instru ión total, y por tanto in rementar el número
de instru iones por i los (IPC). En este apítulo se verá que las té ni as que se pueden
usar para in rementar el IPC ideal pueden aumentar la importan ia de solu ionar uando sea
posible los riesgos estru turales, de datos y de ontrol.

Casi todas las té ni as que se van a estudiar a lo largo de los siguientes apítulos explotan
el paralelismo existente entre las instru iones. Normalmente, la antidad de paralelismo en
un bloque bási o (una se uen ia de instru iones onse utivas sin saltos) es bastante pequeña.
Para los programas SPEC la fre uen ia media de saltos está entre un 15 % y un 25 %, lo que
signi a que en media sólo entre uatro y siete instru iones se pueden eje utar antes de que
o urra un salto. Además, hay que tener en uenta que entre estas instru iones es probable que
también o urran dependen ias de datos. Por tanto, el solape entre instru iones que se puede
explotar es bastante pequeño. Así pues, para obtener mejoras importantes de presta iones, se
debe explotar el ILP disponible a través de múltiples bloques bási os.

Para redu ir los riesgos existentes entre las instru iones y por tanto aumentar el ILP
disponible en las apli a iones se suelen utilizar té ni as de análisis en tiempo de ompila ión
y de análisis en tiempo de eje u ión. Así por ejemplo, para redu ir los riesgos estru turales se
pueden repli ar o segmentar las unidades fun ionales, y para redu ir las deten iones por riesgos
de ontrol se puede utilizar la té ni a de saltos retardados. Hay que señalar que ambas té ni as
son estáti as puesto que no dependen de de isiones que se tomen en tiempo de eje u ión. En la
tabla 1.1 pueden observase diversas té ni as que pueden apli arse para mejorar las presta iones
de un pro esador segmentado, y qué ara terísti a redu e ada una de ellas.

El número de i los por instru ión que onsigue una determinada apli a ión en una arqui-
te tura dada tiene una estre ha rela ión on la antidad de paralelismo a nivel de instru ión
disponible en esa apli a ión. De he ho, el paralelismo a nivel de instru ión nos indi a la
posibilidad de solapamiento en las se uen ias de instru iones, y depende del grado de depen-
den ia entre las instru iones. Hay que señalar que dos instru iones son independientes si se
pueden eje utar simultáneamente sin que existan oni tos entre ellas. Así, uando se tiene
un alto paralelismo entre las instru iones es que hay po as dependen ias y por tanto po os
oni tos entre ellas, on lo que se produ irán po as deten iones durante la eje u ión y omo
1.2. TIPOS DE DEPENDENCIAS 21

Té ni a Redu e
Desenrollamiento de bu les Riesgos de ontrol
Plani a ión dinámi a on mar ador Riesgos RAW
Plani a ión dinámi a on renombramiento Riesgos WAR y WAW
Predi ión dinámi a de saltos Riesgos de ontrol
Emisión múltiple de instru iones CPI ideal
Análisis de dependen ias del ompilador CPI ideal y riesgos de datos
Segmenta ión software CPI ideal y riesgos de datos
Plani a ión de trazas CPI ideal y riesgos de datos
Espe ula ión Riesgos de datos y de ontrol
Elimina ión dinámi a de ambigüedad en memoria Riesgos RAW on memoria

Cuadro 1.1: Diversas té ni as que pueden apli arse para mejorar las presta iones y qué a-
ra terísti a redu e ada una de ellas.

onse uen ia el número de i los por instru ión onseguido estará bastante próximo al base
de la arquite tura utilizada.

1.2. Tipos de dependen ias


Poder determinar ómo una instru ión depende de otra resulta ríti o para determinar
uánto paralelismo existe en una apli a ión, y ómo puede explotarse ese paralelismo. En
parti ular, para explotar el paralelismo a nivel de instru ión se debe determinar qué ins-
tru iones pueden eje utarse en paralelo. Si dos instru iones son independientes se pueden
eje utar de forma solapada sin ausar deten iones, en un au e que tenga los re ursos ne esa-
rios para que no haya riesgos estru turales. Si dos instru iones son dependientes no pueden
eje utarse de forma solapada y deben eje utarse en orden, aunque quizás se puedan solapar
partes de sus eje u iones.

Hay tres tipos diferentes de dependen ias: dependen ias de datos (también llamadas de-
penden ias verdaderas), dependen ias de nombre y dependen ias de ontrol. Vamos a ver de
forma detallada ada uno de estos tipos de dependen ias.

1.2.1. Dependen ias de datos


Dadas dos instru iones I y J (J situada después de I ), existe una dependen ia de datos
entre ellas si:

la instru ión I produ e un resultado que usa la instru ión J

o si hay dependen ia de datos entre la instru ión I y otra instru ión K , y la instru ión
K produ e un resultado que usa la instru ión J

La segunda ondi ión indi a una adena de dependen ias del primer tipo entre varias
instru iones. Evidentemente, esta adena de instru iones puede prolongarse durante mu has
instru iones a lo largo de todo el programa.
22 CAPÍTULO 1. PARALELISMO A NIVEL DE INSTRUCCIÓN

Ejemplo 1.1 Considerar la siguiente se uen ia de ódigo que in rementa los valores de un
ve tor en memoria ( omenzando en la posi ión 0(R1)) sumándole un es alar alma enado
en F2:

loop: LD F0, 0(R1)


ADDD F4, F0, F2
SD 0(R1), F4
SUBI R1, R1, #8
BNEZ R1, loop
. . .

Las dependen ias de datos en esta se uen ia de ódigo involu ran tanto a los datos de
punto otante (PF) omo a los enteros. En uanto a los datos de punto otante hay
una dependen ia de datos en rela ión a F0 entre el resultado que produ e la arga y
su utiliza ión en la suma, y otra dependen ia en rela ión a F4 entre el dato produ ido
por la suma y su utiliza ión en el alma enamiento. En uanto a los datos enteros, la
dependen ia es en rela ión a R1 entre el dato produ ido por la resta de enteros y la
instru ión de salto.

Si dos instru iones tienen dependen ias de datos eso signi a que no se pueden eje utar
simultáneamente, o por lo menos de forma ompletamente solapada. La dependen ia nos di e
que hay una posible adena de uno o más riesgos de datos entre instru iones. Si se intentan
eje utar esas instru iones al mismo tiempo en un pro esador que in orpora dete ión de
riesgos, eso va a provo ar deten iones en la segunda de las instru iones para evitar el riesgo,
on lo que se redu e el solape entre las instru iones, y por tanto también las presta iones
al anzadas por el pro esador.

Si por ontra las instru iones se van a eje utar en un pro esador que no in orpora de-
te ión de riesgos, esa tarea re ae en el ompilador, que debe ha er una plani a ión de
instru iones tal que no se eje uten las instru iones dependientes de forma solapada, pues la
eje u ión del programa no sería orre ta. La plani a ión del ompilador tratará de reordenar
el orden de eje u ión de las instru iones sin afe tar al resultado nal, y uando ni aún así se
onsigan resolver las dependen ias habrá que in luir instru iones NOP para separar entre sí
las instru iones dependientes y de esa manera evitar que surja el riesgo de datos.

Hay que señalar que las dependen ias de datos son propias de los programas, pero si
esas dependen ias terminan onvirtiéndose en riesgos de datos depende de la organiza ión
del au e que tenga el pro esador. Así, podemos en ontrar dependen ias de datos que ausen
riesgos en unos pro esadores mientras que en otros no. Así pues, si unas dependen ias de
datos terminan provo ando deten iones y degradando las presta iones ideales dependerá de
la organiza ión on reta del au e del pro esador donde se va a eje utar esa se uen ia de
instru iones. Esta diferen ia entre dependen ias y riesgos es fundamental para entender ómo
se puede explotar el paralelismo a nivel de instru ión.

En nuestro ejemplo, hay una dependen ia de datos entre las instru iones SUBI y BNEZ,
que ausa una deten ión si el salto se resuelve en la etapa ID, pero que no ausaría ninguna
deten ión si el salto se resuelve en la etapa MEM, pues en ese aso la ondi ión del salto se
evaluaría en la etapa EX y podría apli arse adelantamiento, tal y omo puede verse en la
1.2. TIPOS DE DEPENDENCIAS 23

gura 1.1. En di ha gura se ha mar ado el adelantamiento que se produ iría en uanto está
listo el resultado de SUBI a la etapa que debe utilizarlo.

SUBI IF ID EX MEM WB SUBI IF ID EX MEM WB

BNEZ IF ID EX MEM WB BNEZ IF ID EX MEM WB

(a) (b)

Figura 1.1: Situa ión entre las instru iones SUBI y BNEZ del ejemplo, (a) uando el salto
se resuelve en ID, y (b) uando el salto se resuelve en la etapa MEM.

La presen ia de una dependen ia indi a un riesgo poten ial, pero si realmente hay un
riesgo, y el número de i los de deten ión que eso involu ra, depende del au e del pro esador.
La importan ia de las dependen ias de datos es que una dependen ia de datos:

1. Indi a la posibilidad de un riesgo.

2. Determina el orden en que deben al ularse los resultados.

3. Estable e un límite superior de uánto paralelismo puede explotarse en la se uen ia de


instru iones.

Puesto que una dependen ia de datos puede limitar la antidad de paralelismo a nivel
de instru ión que se puede explotar, en varios apítulos de esta asignatura se va a tratar
este tema intentando limitar los efe tos de esas dependen ias de datos. Estos efe tos pueden
limitarse de dos formas distintas: manteniendo la dependen ia pero evitando que pueda surgir
un riesgo, o eliminando la dependen ia mediante la transforma ión del ódigo. En este sentido,
el primer método que se suele utilizar para evitar los riesgos de datos es plani ar el ódigo sin
eliminar las dependen ias. Como se verá más adelante, algunos tipos de dependen ias pueden
eliminarse por software y/o mediante té ni as hardware.

Un valor de un dato puede pasar entre instru iones bien mediante registros, bien por la
memoria. Si para ello se utilizan los registros, es bastante sen illo dete tar la dependen ia
pues los nombres de los registros son jos en las instru iones. Sin embargo, los saltos pueden
ompli ar esa dete ión, pues dependiendo del resultado nal del salto, las dependen ias
variarán. En estos asos, tanto el ompilador omo el hardware suelen tomar una postura más
onservadora para no arriesgar y asegurar la orre ión del resultado nal.

Las dependen ias que involu ran posi iones de memoria son más difí iles de dete tar,
puesto que dos dire iones distintas pueden estar reriéndose realmente a la misma posi ión
de memoria. Por ejemplo, las dire iones 100(R4) y 20(R6) podrían referirse a la misma
posi ión físi a dependiendo de los valores de R4 y R6. Además, la dire ión efe tiva de una
arga o un alma enamiento podría ambiar entre distintas eje u iones de la misma instru ión
(por ejemplo, en un bu le), ompli ando aún más la dete ión de posibles dependen ias. En
su momento estudiaremos té ni as hardware para dete tar las dependen ias de datos que
involu ran posi iones de memoria, aunque in luso esas té ni as tienen sus limita iones.
24 CAPÍTULO 1. PARALELISMO A NIVEL DE INSTRUCCIÓN

1.2.2. Dependen ias de nombres


El segundo tipo de dependen ias son las dependen ias de nombre. Este tipo de depen-
den ias apare e uando dos instru iones usan el mismo registro o posi ión de memoria, a lo
que llamaremos nombre, pero no hay ujo de datos entre las instru iones aso iadas on ese
nombre.

Dadas dos instru iones I y J (J situada después de I ), podemos tener dos tipos de
dependen ias de nombre:

1. una antidependen ia entre la instru ión I y la instru ión J o urre si la instru ión
J es ribe sobre un registro o una posi ión de memoria que lee la instru ión I . El
orden original debe preservarse para asegurar que la instru ión I lee el valor orre to.
Podemos observar este tipo de dependen ia en la siguiente se uen ia de instru iones:

I ≡ R1 ← R2 + R3
J ≡ R2 ← R5 + R6

2. una dependen ia de salida o urre uando las dos instru iones I y J es riben sobre el
mismo registro o posi ión de memoria. El orden original debe preservarse para asegurar
que el valor que al nal se es ribe orresponde a la instru ión J . Podemos observar este
tipo de dependen ia en la siguiente se uen ia de instru iones:

I ≡ R1 ← R2 + R3
J ≡ R1 ← R4 + R5

En ualquiera de los dos asos, puede observarse que no hay una ne esidad real de omu-
ni a ión entre las dos instru iones involu radas en la dependen ia, y se trata tan sólo de la
reutiliza ión del mismo nombre para dos osas distintas. Como una dependen ia de nombres
no es una dependen ia real, las instru iones involu radas en este tipo de referen ias pueden
eje utarse simultáneamente o reordenarse, siempre y uando se ambie el nombre (el regis-
tro o la posi ión de memoria) usado en las instru iones, para que no haya oni to. Este
renombramiento puede ha erse más fá ilmente si los operandos son registros, en uyo aso
se llama renombramiento de registros. Este renombramiento de registros puede ha er-
se tanto estáti amente por el ompilador, omo dire tamente por el hardware en tiempo de
eje u ión.

1.2.3. Dependen ias de ontrol


El último tipo de dependen ias son las dependen ias de ontrol. Una dependen ia de
ontrol determina el orden de una instru ión I on respe to a una instru ión de salto, de
forma que la instru ión I se eje ute en el orden mar ado por el programa y sólo uando deba
eje utarse. Todas las instru iones, a ex ep ión de las primeras en la se uen ia del programa,
tienen alguna dependen ia de ontrol on algún salto y, en general, esas dependen ias deben
respetarse para mantener el orden de eje u ión de las instru iones del programa.

Uno de los ejemplos más sen illos de dependen ia de ontrol se da entre las instru iones
de la parte then de una instru ión if:
1.2. TIPOS DE DEPENDENCIAS 25

if p1 {
S1;
};
if p2 {
S2;
};

Las instru iones del bloque S1 tienen una dependen ia de ontrol on p1, y las instru -
iones del bloque S2 tienen otra dependen ia de ontrol on p2, pero no on p1.

En general, hay dos normas que imponen las dependen ias de ontrol:

1. Una instru ión que tiene una dependen ia de ontrol on un determinado salto no
puede ser situada delante del salto de forma que su eje u ión ya no esté ontrolada por
ese salto. Por ejemplo, no se puede tomar una instru ión de la parte then y situarla
delante de la parte if.

2. Una instru ión que no tiene una dependen ia de ontrol on un determinado salto no
puede ser situada detrás de ese salto de forma que su eje u ión ahora esté ontrolada
por el salto. Continuando on el ejemplo, no se puede ambiar una instru ión desde
delante de la parte if a la parte then.

Al ontrario de lo que podría pare er, las dependen ias de ontrol no tienen por qué
suponer una pérdida de presta iones si se puede realizar eje u ión espe ulativa. Es de ir,
si podemos eje utar instru iones que no deberían de haberse eje utado, violando de esa
forma las dependen ias de ontrol, sin afe tar a la orre ión del programa. En ese aso
las dependen ias de ontrol no son un fa tor ríti o que deba mantenerse. En su lugar, las
dos propiedades que sí deben mantenerse para asegurar la orre ión del programa son el
omportamiento de las ex ep iones y el ujo de los datos. Normalmente, esto se onsigue
manteniendo tanto las dependen ias de ontrol omo las de datos.

Mantener el omportamiento de las ex ep iones signi a que ualquier ambio que


se haga en el orden de eje u ión de las instru iones no puede suponer que surjan nuevas
ex ep iones, ni que se ambie el orden en que éstas se a tivan. El ujo de datos es el ujo
real entre instru iones que produ en resultados y las que los onsumen. Los saltos ha en que
este ujo de datos sea dinámi o, pues dependiendo de los saltos, la fuente de un dato puede
provenir desde puntos distintos. En ese sentido, no es su iente mantener las dependen ias de
datos, pues una instru ión puede tener dependen ias on más de una instru ión prede esora.
Será el orden de eje u ión dinámi o del programa el que determine qué prede esora será
realmente la que suministre el operando fuente a una instru ión. Este orden de eje u ión se
asegura manteniendo las dependen ias de ontrol.

Ejemplo 1.2 Consideremos el siguiente ódigo:

ADD R1, R2, R3


BEQZ R4, L
SUB R1, R5, R6
L: ...
OR R7, R1, R8
26 CAPÍTULO 1. PARALELISMO A NIVEL DE INSTRUCCIÓN

El valor de R1 usado en la instru ión OR depende de si el salto se toma o no. En


este aso las dependen ias de datos no son su ientes para mantener la orre ión del
programa. La instru ión OR tiene dependen ia de datos on las instru iones ADD
y SUB, pero mantener las dependen ias de datos no es su iente para una eje u ión
orre ta. En su lugar, uando se eje utan las instru iones lo que se debe mantener es el
ujo de datos. Si el salto no se toma el valor al ulado por la instru ión SUB es el que
se tiene que usar en la instru ión OR, mientras que si el salto se toma el valor a usar
es el al ulado por la instru ión ADD. Sólo si se mantiene la dependen ia de ontrol de
la instru ión OR on el salto, se puede mantener el ujo de datos orre to. Por razones
similares, la instru ión SUB no puede trasladarse delante del salto.

Las dependen ias de ontrol se mantienen implementando en el au e la dete ión de los


riesgos de ontrol, que provo arán deten iones uando sea ne esario. Esas deten iones pueden
eliminarse o redu irse mediante una variedad de té ni as hardware y software (salto retardado,
predi ión estáti a, predi ión dinámi a, et .), que serán revisadas en el apítulo 3.

1.3. Tipos de riesgos


Los riesgos de datos se presentan uando hay una dependen ia de datos entre las instru -
iones, y éstas están situadas lo su ientemente er a para que la superposi ión debida a la
segmenta ión ambie el orden de a eso a los operandos on rela ión al orden normal que se
sigue en las instru iones que se eje utan se uen ialmente. Los riesgos por dependen ias de
datos pueden lasi arse dependiendo del orden de los a esos de le tura y es ritura en las
instru iones. Por onvenio, los riesgos se denominan por el orden que siguen las instru iones
en el programa, que debe ser preservado por la segmenta ión.

Consideremos dos instru iones I y J de forma que según el ódigo fuente la instru ión
I se eje uta antes que la instru ión J , y por tanto también se pondrá la instru ión I antes
que la instru ión J en el au e de eje u ión. Los posibles riesgos por dependen ia de datos
entre estas dos instru iones son:

RAW (Read After Write, le tura después de es ritura): la instru ión J trata de leer un
operando fuente antes de que lo es riba la instru ión I . De esta forma la instru ión
J toma in orre tamente el valor antiguo, tal y omo puede verse en la gura 1.2. Este
es el aso más omún de riesgo de datos, y viene provo ado por una ne esidad real de
omuni a ión, pues la segunda instru ión ne esita para su eje u ión el dato que está
al ulando la primera.
I: ADD R1, R2, R3

J: SUB R4, R1, R3

Figura 1.2: Riesgo de datos tipo RAW.

WAR (Write After Read, es ritura después de le tura): en este aso la instru ión J intenta
es ribir un destino antes que sea leído por la instru ión I . Esta instru ión toma in o-
rre tamente el nuevo valor, tal y omo puede verse en la gura 1.3. Este tipo de riesgo
1.3. TIPOS DE RIESGOS 27

no puede darse en el DLX segmentado para enteros (aunque sí que se dará en el aso de
opera iones en punto otante) porque todas las le turas se ha en antes (en ID) y todas
las es rituras después (en WB) (gura 1.5). Este riesgo o urre uando hay instru iones
que es riben en un i lo ini ial sus resultados, e instru iones que leen sus operandos
fuente en un i lo más tardío, y resulta que la le tura se produ e en el tiempo después
que la otra instru ión posterior reali e su es ritura.

I: SUB R4, R1, R3

J: ADD R1, R2, R3

Figura 1.3: Riesgo de datos tipo WAR.

Este riesgo viene provo ado por una antidependen ia que se produ e por una reutiliza-
ión, en este aso de R1. Los ompiladores suelen resolver las antidependen ias mediante
el renombramiento de registros que utilizan las instru iones. Así por ejemplo, en el a-
so anterior el riesgo desapare ería si la instru ión ADD utilizara omo registro destino
R32, y se ambiara en todas las instru iones siguientes a J que utili en omo operando
fuente R1 por ese nuevo R32. En este sentido, mu hos pro esadores tienen más registros
de los que son a esibles por el usuario. Es bastante habitual que tengan 64 registros,
de los uales 32 pueden ser usados por el usuario y los otros 32 los utiliza el ompilador
o dire tamente el hardware, para los renombramientos que sean ne esarios para resolver
las antidependen ias.

WAW (Write After Write, es ritura después de es ritura): ahora la instru ión J intenta
es ribir un operando antes que sea es rito por la instru ión I . Las es rituras se están
realizando en un orden in orre to, dejando en el destino el valor es rito por la instru ión
I en lugar del es rito por la instru ión J , tal y omo puede verse en la gura 1.4.

I: SUB R1, R4, R3

J: ADD R1, R2, R3

Figura 1.4: Riesgo de datos tipo WAW.

Este riesgo orresponde a una dependen ia de salida, y se presenta solamente uando en


la segmenta ión se permiten es rituras en más de una etapa, o se permite que pro eda
una instru ión posterior aún uando se en uentre detenida una instru ión anterior.
En el pro esador DLX de enteros segmentado solamente se es ribe en los registros en la
etapa WB y de esta forma se evita esta lase de riesgos (gura 1.5), que, sin embargo,
sí que se presentará on instru iones punto otante.
En general, los ompiladores no suelen generar este tipo de situa iones, pues se evita
generar una instru ión uyo resultado no vaya a ser utilizado. Sin embargo, podría
haber situa iones inesperadas donde, debido a un ambio en el ujo del programa (un
salto, una interrup ión, et .) se llegara a produ ir que dos instru iones onse utivas
es riban sobre el mismo registro, y evidentemente esta situa ión no se puede ontrolar
por parte del ompilador.

Claramente el aso RAR (Read After Read, le tura después de le tura) no es un riesgo, ya
que evidentemente no modi amos en ningún momento el valor de la fuente. Por otra parte,
28 CAPÍTULO 1. PARALELISMO A NIVEL DE INSTRUCCIÓN

IF ID EX MEM WB IF ID EX MEM WB
IF ID EX MEM WB IF ID EX MEM WB

Figura 1.5: En el pro esador DLX segmentado todas las le turas de registros fuente se realizan
en la etapa ID y las es rituras de resultados en la etapa WB.

omo ya se ha omentado, en la gura 1.5 puede observarse la situa ión de las etapas en el
au e DLX de enteros, y por qué no pueden plantearse riesgos WAR ni WAW.

En general, estos riesgos de datos, que hemos planteado en el a eso a los registros, también
pueden su eder en el aso de a eso a una posi ión de memoria. En el pro esador DLX, al
tener sólo un anal de a eso a memoria, los a esos se ha en en orden. Sin embargo, este
problema podría apare er si tuviéramos dos o más anales de a eso a memoria.

Estos riesgos que hemos estudiado ha en que en los programas haya menos paralelismo a
nivel de instru ión, lo que a su vez a arrea que haya más instru iones dependientes en el
au e de eje u ión del pro esador. Para evitar estos riesgos, durante la eje u ión se provo an
deten iones, lo que ha e que aumente el número de i los por instru ión que el au e ne esita
para eje utar el programa.

1.4. Aumentando el paralelismo a nivel de instru ión


Ya se ha omentado que las presta iones que al anza un pro esador dependen dire tamente
del grado de paralelismo a nivel de instru ión disponible en las apli a iones. A mayor grado
de paralelismo, y si hay re ursos su ientes, se redu en los oni tos entre instru iones y por
tanto las deten iones, lo que ha e que disminuya el número de i los medio por instru ión.
Se trata, por tanto, de aumentar el paralelismo a nivel de instru ión de las instru iones
que están en ada momento en la unidad segmentada, para de esa manera aumentar las
presta iones del sistema.

Como se ha indi ado en la se ión 1.1, la antidad de paralelismo en un bloque bási o


(una se uen ia de instru iones onse utivas sin saltos) es bastante pequeña. Para los pro-
gramas SPEC la fre uen ia media de saltos varía entre el 15 % y 25 %, lo que signi a que
en media sólo entre uatro y siete instru iones se pueden eje utar antes de que o urra un
salto. Además, hay que tener en uenta que entre estas instru iones es probable que también
o urran dependen ias de datos. Por tanto, el solape entre instru iones que se puede explotar
es bastante pequeño. Así pues, para obtener mejoras importantes de presta iones, se debe
explotar el paralelismo disponible a través de múltiples bloques bási os.

En este sentido, en el siguiente apítulo nos vamos a apoyar en el paralelismo a nivel de


bu le para aumentar el paralelismo a nivel de instru ión solapando varios bloques bási os,
de forma que se onsiga independen ia entre las itera iones de un bu le. Para poder explotar
el paralelismo a nivel de bu le es ne esario dete tar las dependen ias para plani ar el ódi-
go, determinar las itera iones de un bu le que pueden eje utarse en paralelo, y eliminar las
dependen ias de nombre.

El paralelismo a nivel de bu le se suele analizar sobre el ódigo fuente, mientras que


la mayoría de los análisis del paralelismo a nivel de instru ión se realiza una vez que el
1.4. AUMENTANDO EL PARALELISMO A NIVEL DE INSTRUCCIÓN 29

ompilador ha generado las instru iones. El análisis a nivel de bu le realiza una dete ión
de las dependen ias existentes entre los operandos que intervienen entre las itera iones de
ese bu le. Como veremos, si no hay dependen ias se puede desenrollar el bu le, lo que nos
permitirá al anzar mejores presta iones. En lo que sigue sólo vamos a onsiderar dependen ias
de datos (se al ula un valor que se utiliza omo operando fuente más adelante), pues aunque
también pueden su eder dependen ias de nombres, éstas pueden eliminarse mediante té ni as
de renombramiento.

El análisis del paralelismo a nivel de bu le se entra en estudiar si los a esos a los datos
en las itera iones su esivas son dependientes de valores al ulados en itera iones previas. Este
tipo de dependen ia entre itera iones se llama loop- arried dependen e.

Ejemplo 1.3 El siguiente ódigo no presenta dependen ia entre itera iones:

for (i=1; i<=1000; i++)


x[i℄ = x[i℄ + k;

En este bu le hay una dependen ia entre las dos ve es que se usa x[i℄, pero esta
dependen ia es en una misma itera ión, no entre distintas itera iones. De esta forma, el
bu le puede ser fá ilmente paralelizable. Como un ejemplo de este tipo de paraleliza ión
el siguiente ódigo presenta el mismo ódigo anterior donde el bu le se ha desenrollado
uatro ve es:

for (i=1; i<=1000; i+=4)


{
x[i℄ = x[i℄ + k;
x[i+1℄ = x[i+1℄ + k;
x[i+2℄ = x[i+2℄ + k;
x[i+3℄ = x[i+3℄ + k;
}

Sin embargo, en mu hos bu les sí que tenemos dependen ias entre itera iones, lo que
ompli ará o in luso impedirá su desenrollamiento.

Ejemplo 1.4 El siguiente ódigo presenta dependen ia entre itera iones:

for (i=1; i<=1000; i++)


{
x[i+1℄ = x[i℄ + z[i℄;
y[i+1℄ = y[i℄ + x[i+1℄;
}

Puede observarse omo este bu le presenta dos dependen ias entre itera iones: en la
primera instru ión hay una dependen ia entre itera iones relativa a la variable x[i℄ y
x[i+1℄, y en la segunda instru ión la dependen ia está en el uso de la variable y[i℄ e
y[i+1℄. Además, también hay una dependen ia de datos entre la primera y la segunda
instru ión respe to al valor de x[i+1℄.
Al ser las itera iones dependientes entre sí, el bu le no se puede desenrollar, pues siempre
tendríamos deten iones entre las instru iones dependientes.
30 CAPÍTULO 1. PARALELISMO A NIVEL DE INSTRUCCIÓN

Supongamos que tenemos tres arrays A, B y C que son distintos, y supongamos también
el siguiente bu le:

for (i=0; i<100; i=i+1)


{
A[i+1℄ = A[i℄ + C[i℄; /* S1 */
B[i+1℄ = B[i℄ + A[i+1℄; /* S2 */
}

En este ódigo hay dos dependen ias diferentes:

1. La instru ión S2 usa el valor A[i+1℄, al ulado por la instru ión S1 en la misma
itera ión.

2. La instru ión S1 usa un valor al ulado por la instru ión S1 en una itera ión anterior.
En la itera ión i se al ula A[i+1℄ que es leído en la itera ión i+1. Lo mismo o urre
on la instru ión S2 y B[i℄.

Estas dos dependen ias son diferentes y tienen efe tos diferentes. La dependen ia de la
instru ión S1 respe to a una itera ión anterior de la propia instru ión S1, es una dependen ia
entre itera iones que obliga a eje utar de forma se uen ial las diversas itera iones de esta
instru ión.

La dependen ia de S2 respe to a S1 es en una misma itera ión, y no entre itera iones. Así,
si ésta fuera la úni a dependen ia del bu le, se podrían eje utar múltiples itera iones de este
bu le en paralelo on tan sólo mantener el orden relativo entre los pares de instru iones on
la dependen ia.

Se pueden representar grá amente las dependen ias entre instru iones, representando
las instru iones mediante nodos y las dependen ias mediante un ar o entre la instru ión
que produ e el resultado y la instru ión que lo utiliza. Cada ar o se etiqueta on la distan ia
entre itera iones que plantea la dependen ia. Para el ódigo que estamos analizando, este
grafo de dependen ias sería el mostrado en la gura 1.6.

1 1

0
S1 S2

Figura 1.6: Grafo de dependen ias para el ódigo estudiado.

En la gura tenemos las dos instru iones S1 y S2, las dos dependen ias entre itera iones
(a distan ia uno) para ada una de las instru iones, y la dependen ia de datos. Cuando
el grafo de dependen ias tiene un i lo on distan ia de la dependen ia mayor o
igual que uno enton es el bu le no es paralelizable.

Ejemplo 1.5 Consideremos este otro ejemplo, donde de nuevo los arrays A, B, C y D son
distintos.
1.4. AUMENTANDO EL PARALELISMO A NIVEL DE INSTRUCCIÓN 31

for (i=1; i<=100; i=i+1)


{
A[i℄ = A[i℄ + B[i℄; /* S1 */
B[i+1℄ = C[i℄ + D[i℄; /* S2 */
}

La instru ión S1 usa el valor asignado en la itera ión previa por la instru ión S2,
de forma que hay una dependen ia entre itera iones entre S2 y S1. Sin embargo, puede
observarse que esa dependen ia es entre distintas instru iones y no de la misma instru -
ión entre varias itera iones. Esto puede verse laramente en el grafo de dependen ias
de la gura 1.7.

0
1
S1 S2

Figura 1.7: Grafo de dependen ias para el ódigo del ejemplo 1.5.

En el grafo de dependen ias puede observarse que el úni o i lo en el grafo es de distan ia


ero y por tanto el bu le sería paralelizable. Hay una dependen ia entre itera iones
(aunque no es ir ular), on lo que la itera ión i+1 no se puede eje utar hasta que
nali e la itera ión i.
Aunque no hay dependen ias ir ulares en el bu le anterior, el bu le debe ser transforma-
do para ha erlo paralelizable respetando el orden par ial que mar an las dependen ias
entre instru iones. Para ello hay que tener en uenta dos detalles importantes:

1. No hay dependen ia de la instru ión S1 a S2. Si la hubiera tendríamos un i lo en


las dependen ias y el bu le no podría paralelizarse. Sin embargo, omo no tenemos
esta dependen ia podemos inter ambiar las senten ias S1 y S2.
2. En la primera itera ión del bu le, la senten ia S1 depende del valor B[1℄, que es
al ulado antes de entrar en el bu le.

Estas dos observa iones nos permiten sustituir el bu le anterior por la siguiente se uen ia
de ódigo:

A[1℄ = A[1℄ + B[1℄;


for (i=1; i<=99; i=i+1)
{
B[i+1℄ = C[i℄ + D[i℄;
A[i+1℄ = A[i+1℄ + B[i+1℄;
}
B[101℄ = C[100℄ + D[100℄;

Ahora la dependen ia entre las dos instru iones ya no es entre distintas itera iones, on
lo que pueden solaparse varias itera iones del bu le para eje utarse de forma paralela,
siempre y uando las instru iones de ada itera ión mantengan su orden relativo.
32 CAPÍTULO 1. PARALELISMO A NIVEL DE INSTRUCCIÓN

1.4.1. Bus ar dependen ias


En ontrar las dependen ias en un programa es una parte importante de tres tareas:

1. Ha er una buena plani a ión del ódigo.

2. Determinar de qué bu les puede extraerse paralelismo.

3. Eliminar las dependen ias de nombres.

La omplejidad del análisis de dependen ias está en el uso de arrays, punteros o paso de
parámetros por referen ia, que permiten mu hos lenguajes de alto nivel. Cuando sólo se usan
variables, el estudio de referen ias es bastante sen illo, pues sólo depende de los nombres de
las variables. Sin embargo, uando se utilizan alias ( omo es el aso de los punteros y del paso
de parámetros por referen ia), surgen ompli a iones e in ertidumbre en el análisis.

El ompilador puede usar varios métodos para en ontrar las dependen ias, y on ello, si
es posible, eliminarlas. Algunos de esos métodos se basan en el he ho de que los índi es de
los arrays son anes. Un índi e de un array de una dimensión es afín si se pueden es ribir de
la forma a × i + b, donde a y b son onstantes e i es la variable índi e del bu le. El índi e de
un array de varias dimensiones es afín si lo son los índi es de ada dimensión. Los a esos a
arrays dispersos, que típi amente tienen la forma x[y[i℄℄, es uno de los prin ipales ejemplos
de a esos no anes.

Determinar si hay una dependen ia entre dos referen ias al mismo array en un bu le es por
tanto equivalente a determinar si las dos fun iones anes pueden tener el mismo valor para
diferentes índi es dentro de los límites del bu le. Por ejemplo, supongamos que tenemos en el
ódigo de un bu le for, una instru ión de alma enamiento en un array y otra instru ión que
lee de ese mismo array. Supongamos también que el índi e de la instru ión de alma enamiento
puede expresarse en la forma a × i + b, y el índi e de la instru ión de le tura del array puede
expresarse en la forma c × i + d, donde i es el índi e del bu le for que varía desde m hasta n.
En ese aso existe una dependen ia si se dan las siguientes ondi iones:

1. Existe dos índi es de las itera iones, j y k que están dentro de los límites del bu le for,
es de ir m ≤ j ≤ n, m ≤ k ≤ n.

2. La instru ión de alma enamiento guarda un resultado en una posi ión que más adelante
utiliza la instru ión de le tura, es de ir a × j + b = c × k + d.

En general, no va a ser posible determinar si hay una dependen ia en tiempo de om-


pila ión. Así por ejemplo, los valores de a, b, c, y d podrían ser des ono idos durante la
ompila ión (podrían ser valores en otros arrays, resultados de otros ál ulos, o entradas de
te lado) ha iendo imposible saber si hay o no dependen ia. Sin embargo, la mayoría de los
programas ontienen bu les on índi es sen illos donde a, b, c, y d serían onstantes. En estos
asos, es posible omprobar en tiempo de ompila ión si existen estas dependen ias.

Como un ejemplo, un test sen illo y su iente para omprobar la ausen ia de dependen ias
es el máximo omún divisor (GCD). Se basa en la observa ión de que si hay una dependen ia
entre itera iones, enton es se umple que (d − b) mod GCD(c, a) = 0. Hay que señalar que
1.4. AUMENTANDO EL PARALELISMO A NIVEL DE INSTRUCCIÓN 33

para poder usar el test GCD se debe normalizar el bu le, es de ir, la variable índi e del bu le
debe empezar en uno e in rementarse de uno en uno.

Ejemplo 1.6 Vamos a usar el test GCD para determinar si existen dependen ias entre
itera iones del siguiente bu le:

for (i=1; i<=100; i=i+1)


x[2i+3℄ = x[2i℄ * 50;

Dado este ódigo, los valores para las onstantes de los índi es son: a = 2, b = 3, c = 2
y d = 0. En este aso el máximo omún divisor de a y c es GCD(a, c) = 2. Mientras,
d − b = −3, on lo que (d − b) mod GCD(c, a) = −3 mod 2 6= 0, y por tanto no hay
dependen ia.

Hay que señalar que ésta es una ondi ión ne esaria para garantizar dependen ia pero no
es su iente, pues puede que el test se umpla y, sin embargo, que no haya dependen ia entre
itera iones. Esto puede su eder, por ejemplo, si no se tienen en uenta los límites del bu le.

Por otra parte, el ompilador, además de dete tar si hay dependen ias, debe dete tar de
qué tipo son esas dependen ias para tratar de eliminarlas uando sea posible. De esta forma
se pueden re ono er las dependen ias de nombres y eliminarlas en tiempo de ompila ión
mediante renombramiento.

Ejemplo 1.7 El siguiente bu le tiene múltiples tipos de dependen ias. Vamos a estudiar las
dependen ias verdaderas, las de salida, las antidependen ias, y eliminar las dependen ias
de salida y antidependen ias mediante renombramiento.

for (i=1; i<=100; i=i+1)


{
Y[i℄ = X[i℄ / ; /* S1 */
X[i℄ = X[i℄ + ; /* S2 */
Z[i℄ = Y[i℄ + ; /* S3 */
Y[i℄ = - Y[i℄; /* S4 */
}

En este ódigo podemos en ontrar las siguientes dependen ias:

1. Hay dependen ias verdaderas desde S1 a S3 y desde S1 a S4, debido a Y[i℄. Estas
dependen ias no son entre distintas itera iones, on lo que no evitan que el bu le
pueda paralelizarse. Sin embargo, estas dependen ias obligan a que S3 y S4 deban
esperar a que termine S1.
2. Hay una antidependen ia desde S1 a S2 debido a X[i℄.
3. Hay una antidependen ia desde S3 a S4 debido a Y[i℄.
4. Hay una dependen ia de salida desde S1 a S4 debido a Y[i℄.

La siguiente versión del mismo bu le elimina estas falsas dependen ias:


34 CAPÍTULO 1. PARALELISMO A NIVEL DE INSTRUCCIÓN

for (i=1; i<=100; i=i+1)


{
/* Se ha renombrado Y a T para evitar la dependen ia de salida */
T[i℄ = X[i℄ / ;
/* Se ha renombrado X a X1 para evitar la antidependen ia */
X1[i℄ = X[i℄ + ;
/* Se ha renombrado Y a T para evitar la antidependen ia */
Z[i℄ = T[i℄ + ;
Y[i℄ = - T[i℄;
}

Después del bu le la variable X se ha renombrado a X1. En el ódigo que siga al bu le el


ompilador puede simplemente sustituir el nombre X por X1.

1.5. Resumen
A lo largo de este apítulo hemos visto la importan ia que tiene aumentar el paralelismo a
nivel de instru ión para on ello mejorar las presta iones que al anza un sistema. Mejorando
el paralelismo a nivel de instru ión se redu en las dependen ias y por tanto las deten iones
que se provo an durante la eje u ión en el au e segmentado, on lo que disminuye el número
medio de i los por instru ión.

Hemos revisado los distintos tipos de dependen ias y ómo se pueden evitar, uando ésto
es posible. Se ha expli ado que no todas las dependen ias provo an riesgos en la segmenta-
ión, pues eso depende de la distan ia entre las instru iones que tienen la dependen ia y
la organiza ión del au e donde se vaya a eje utar el ódigo. También se han revisado los
distintos tipos de riesgos que pueden o urrir y su orresponden ia on los distintos tipos de
dependen ias entre instru iones.

En la última parte de este apítulo se ha estudiado ómo aumentar el paralelismo a nivel


de instru ión mediante la eje u ión en paralelo de las distintas instru iones que forman
un bu le. Para ello se ha visto ómo dete tar si un bu le puede ser paralelizable y ómo
solu ionarlo uando ésto sea posible.

1.6. Ejer i ios


1. Indi a todas las dependen ias de datos, antidependen ias y dependen ias de salida que
hay en el siguiente ódigo:

LD F0, 0(R1) ; S1
ADDD F4, F0, F2 ; S2
ADDD F6, F0, F4 ; S3
LD F2, 0(R3) ; S4
SUBI R3, R3, #4 ; S5

Vous aimerez peut-être aussi