ARQUITECTURA DE SISTEMAS PARALELOS. 3º INGENIERIA

Anuncio
ARQUITECTURA DE SISTEMAS PARALELOS.
3º INGENIERIA TECNICA EN INFORMATICA DE SISTEMAS. FEBRERO, 2004.
SOLUCIONES
C1. (2 puntos) El PowerPC 620 es un procesador de 64 bits con dos caches internos separados (datos e
instrucciones) de 32KB cada uno, asociativos por conjuntos (vías). El tamaño de línea es de 64 bytes. El
tamaño de página es de 4KB, y se desea que el acceso a cache se realice sólo con la parte de las
direcciones que se corresponde con el desplazamiento dentro de la página. Se pide:
• ¿Cuál es el grado de asociatividad (número de vías) de los caches internos?
• ¿Qué ventaja puede tener el hecho de que el acceso a cache se realice sólo con el desplazamiento
dentro de la página?
Respuesta:
Se desea que la búsqueda en cache pueda realizarse sólo con los bits que se corresponden con el
desplazamiento dentro de la página (12, pues 212=4KB). Puesto que el tamaño de línea es 64 bytes (26),
quedan 12-6=6 bits de índice, lo que nos da un total de 26=64 conjuntos, formados por n vías, cada una
con 64 bytes. Habrá un total de 32KB/(64*64) ó 215/212=23=8 vías.
Un razonamiento más sencillo es que si se quiere acceder a cache sólo con log2(tamaño_página) entonces
cada vía debe ser del tamaño de una página, luego el número de vías será 32KB/4KB=8. Pero, cuidado,
esto NO quiere decir que en cada vía hay una página guardada.
La ventaja es obvia: permite comenzar la búsqueda en cache sin necesidad de transformar primero la
dirección virtual en dirección física. Es decir, mientras se accede a la TLB/Tabla de Páginas con la parte
alta de la dirección virtual para encontrar el marco de memoria física, simultáneamente accedemos a
cache. Cuando tengamos la dirección física completa (salvo fallo de página), sólo quedará comparar las
etiquetas.
C2. (1 punto) Para recibir datos de un periférico (con una tasa media de 100 bytes por segundo) se
pueden usar dos métodos:
• Hacer un muestreo (polling) cada milisegundo, muestreo que ocupa la CPU por un total de 1µs
(microseg.)
• Usar interrupciones, con un tiempo de respuesta (desde que se activa la señal de interrupción al
llegar un byte hasta que se entra en la rutina de servicio) de 1µs.
El tiempo de leer un byte se supone despreciable. ¿Qué método es preferible desde el punto de vista del
uso de CPU?¿Cuál debe ser el periodo de muestreo para que el método preferible sea otro?
Respuesta:
El periférico envía 1 byte cada 10ms. Puesto que el muestreo (polling) se realiza cada ms, gastamos 1µs
cada ms (haya dato o no), mientras que con interrupciones (que sólo se activan cada vez que llega un
byte) gastamos 1µs cada 10ms, diez veces menos. Por tanto es preferible en este caso usar interrupciones.
Incluso si se reduce la frecuencia de muestreo a 1 cada 10ms, el caso óptimo, como mucho igualamos a
las interrupciones debido al hecho de que el costo del muestreo es el mismo que el de la rutina de
servicio. Sin embargo, téngase en cuenta que según otros parámetros el razonamiento puede ser distinto.
Por ejemplo, con interrupciones el tiempo de respuesta es casi inmediato, mientras que el muestreo puede
no coincidir con el momento justo de la llegada del dato (se usan buffers), por lo que desde el punto de
vista de cada dato aislado las interrupciones seguirían siendo más rápidas.
En resumen, sólo cuando el tiempo de respuesta a interrupciones sea mayor que el de muestreo y el
periodo de muestreo se ajuste suficientemente al tráfico de datos será preferible usar muestreo desde el
punto de vista de uso de la CPU.
C3. (1 punto) Explique brevemente cuál es la diferencia fundamental entre una topología de switches
centralizados y una de swicthes distribuidos. Ponga ejemplos de ambos tipos. ¿Cuál será el ancho de
banda de bisección de una red hipercubo de 16 nodos con todos los enlaces de fibra óptica de
1000Mbits/seg? ¿Cuánto valdrá la latencia de transporte entre dos computadores físicamente conectados
si la distancia entre ellos es de 100m y el tamaño medio del mensaje es 125 bytes?
Respuesta:
Ancho de banda de bisección = 8 * 1000Mbits/seg = 8000Mbits/seg
Latencia_transporte = Tiempo_vuelo + Tiempo_transmisión = Distancia/Velocidad + Tamaño/Ancho de
banda = 100m / (2/3 * 300000Km/s) + 125bytes / 1000Mbits/seg = 0,1 * 106 / (2/3 *300000) µs + 125*8 /
1000 µs = 0,5µs + 1µs = 1,5µs
PROBLEMAS:
P1. (3 puntos) Escriba una función llamable desde C con el siguiente prototipo (modelo SMALL):
long funcion (long num, int x);
La función debe devolver el número num despreciando los x bits menos significativos. Se supone que
x<32. La función debe devolver 0 si num es demasiado pequeño.
Compare ahora un programa que llame a esta función desde main con otro idéntico pero que escriba el
código de la función como parte de la propia main. ¿Qué instrucciones se ejecutan de más en el caso de
llamar a la función? (Debe explícitamente incluir el paso de parámetros, la llamada y el retorno, etc.).
Respuesta: (Nota: esta es sólo una de las posibles soluciones. Ignoramos los casos especiales como x≤0).
; Un código C que serviría de prueba
;
#include <stdio.h>
;
extern long funcion(long num,int x);
;
long num=-3009;int x=2;
;
main() {
;
num=funcion(num,x);
;
printf("%ld", num); // la respuesta aquí debe ser -3008.
;
}
.MODEL small
.CODE
PUBLIC _funcion
_funcion
proc
near
push
bp
mov
bp,sp
mov
cx,word ptr [bp+8]
;x
mov
dx,word ptr [bp+6]
;parte alta de num
mov
ax,word ptr [bp+4]
;parte baja de num
mov
bl,0
;bandera bl=0, positivo
test
dx,8000h
;no afecta al valor de dx
jz
positivo
not
dx
; si negativo, compl. a 2 de 32 bits
not
ax
add
ax,1
adc
dx,0
mov
bl,1
;bandera bl=1, negativo
positivo:
shr
dx,1
rcr
ax,1
loop
positivo
;desplaza a la derecha x veces
mov
cx,word ptr [bp+8]
deshacer:
shl
ax,1
;deshace los shifts anteriores
rcl
dx,1
;si no, la magnitud del número es diferente
loop
deshacer
cmp
bl,1
;si era negativo, vuelvo a dejarlo como estaba
jne
fin
not
dx
not
ax
add
ax,1
adc
dx,0
fin:
mov
sp,bp
pop
bp
ret
_funcion
endp
end
Otra posible solución sería crear una máscara con todos los bits a 1 salvo los x menos significativos y
hacer la operación lógica and con num.
Para la segunda parte del problema, las instrucciones ejecutadas de más por llamar a la función serían:
En la función principal (main):
3 pushes de 16 bits para el paso de parámetros
call
al menos un add sp, 6 para deshacer los parámetros
a lo que hay que añadir todas las líneas de la función ensamblador que no son estrictamente el "núcleo":
push
bp
mov
bp,sp
mov
cx,word ptr [bp+8]
mov
dx,word ptr [bp+6]
mov
ax,word ptr [bp+4]
..............................
fin:
mov
sp,bp
pop
bp
ret
Como comentario final, este "costo" puede no ser despreciable en caso de recursos limitados (memoria,
tiempo de ejecución, etc.).
P2. (3 puntos) El siguiente código en ensamblador recorre un vector v, que comienza en la posición 0,
calculando para cada v[i] el número de combinaciones que pueden darse con v[i] elementos tomados de
dos en dos. El número de combinaciones de n elementos tomados de k en k es: Cnk = n ⋅ (n − 1) ⋅K⋅ (n − k + 1)
k!
ADDI R4,R0,#2
ADDI R1,R0,#40
LOOP: LW R2,0(R1)
SUBI R3,R2,#1
MUL R2,R3,R2
DIV R2,R2,R4
SW 0(R1),R2
SUBI R1,R1,#4
BNEZ R1, LOOP
Las instrucciones MUL y DIV tienen los operandos en registros de propósito general como ocurre en el
WinDLX
Se pide:
a)
Realizar la secuencia de ejecución del programa suponiendo un DLX con todos los desvíos
de datos necesarios y con apuesta por salto no tomado. Indicar los bloqueos que se producen
y que desvíos se activan en cada caso. Calcular el tiempo necesario para su ejecución
suponiendo un reloj de 100Mhz.
b) Realizar la secuencia de ejeución del programa suponiendo un DLX sin ningún tipo de
desvío. Para optimizar la ejecución desenrollar el bucle 2 veces, reordenar y usar la técnica
del salto retrasado. Calcular el tiempo necesario para su ejecución y la aceleración respecto a
la máquina del apartado a suponiendo también un reloj de 100Mhz.
c) Generalizar los resultados obtenidos en el apartado a para programas que calculen Cn3,
Cn4,…, Cnk
Nota: Explicar y justificar cualquier decisión tomada
Solución:
a) DLX con todos los desvíos de datos necesarios y con apuesta por salto no tomado
ADDI R4,R0,#2
IF
ADDI R1,R0,#40
LOOP:
ID
IF
LW R2,0(R1)
EX
M
WB
ID
EX
M
WB
IF
ID
EX
M
WB
IF
ID
-
EX
M
IF
-
ID
EX
M
WB
IF
ID
EX
M
IF
ID
EX
M
WB
IF
ID
EX
M
WB
IF
-
ID
EX
M
WB
IF
IF
ID
EX
SUBI R3,R2,#1
MUL R2,R3,R2
DIV R2,R2,R4
SW 0(R1),R2
SUBI R1,R1,#4
WB
BNEZ R1, LOOP
LOOP:
WB
LW R2,0(R1)
M
Ta = (Ciclos_1 + 8*Ciclos_n + Ciclos_10) * Periodo de reloj = (12+8*10+13) * 10 ns = 1050 ns
En la última iteración hay que incluir las 4 etapas que restan por ejecutarse.
Al considerar salto no tomado, si hubiera instrucciones después del bucle, la última iteración tardaría un
ciclo menos ya que no habría que repetir la etapa IF.
b) Suponiendo que no hay ningún desvío de datos, desenrollando el bucle 2 veces y utilizando salto
retrasado
ADDI R4,R0,#2
ADDI R1,R0,#40
LOOP: LW R2,0(R1)
SUBI R3,R2,#1
MUL R2,R3,R2
DIV R2,R2,R4
SW 0(R1),R2
LW R5,-4(R1)
SUBI R6,R5,#1
MUL R5,R5,R4
DIV R5,R5,R4
SW -4(R1),R5
SUBI R1,R1,#8
BNEZ R1, LOOP
LOOP:
ADDI R1,R0,#40
ADDI R4,R0,#2
LW R2,0(R1)
LW R5,-4(R1)
SUBI R1,R1,#8
SUBI R3,R2,#1
SUBI R6,R5,#1
MUL R2,R3,R2
MUL R5,R6,R5
DIV R2,R2,R4
DIV R5,R5,R4
SW 8(R1),R2
DBNEZ R1, LOOP
SW 4(R1),R5
LW R2,0(R1)
IF
ID
IF
EX
ID
IF
ADDI R1,R0,#40
ADDI R4,R0,#2
LOOP: LW R2,0(R1)
LW R5,-4(R1)
SUBI R1,R1,#8
SUBI R3,R2,#1
SUBI R6,R5,#1
MUL R2,R3,R2
MUL R5,R6,R5
DIV R2,R2,R4
DIV R5,R5,R4
SW 8(R1),R2
DBNEZ R1, LOOP
SW 4(R1),R5
M
EX
-
WB
M
ID
IF
WB
EX
ID
IF
M
EX
ID
IF
WB
M
EX
ID
IF
WB
M
EX
ID
IF
WB
M
EX
-
WB
M
ID
IF
WB
EX
ID
IF
M
EX
-
WB
M
ID
IF
Tb = (Ciclos_1 + 3*Ciclos_n + Ciclos_5) * Periodo de reloj = (18+3*15+19) * 10ns = 820 ns
S = Ta/Tb = 1050/820 = 1,28 (mejora del 28%)
El primer bloqueo sólo va a ocurrir en la primera iteración.
WB
EX
ID
IF
M
EX
-
WB
M
ID
IF
WB
EX
ID
IF
EX
ID
IF
Una posible mejora (difícilmente obtenible por el compilador) sería la siguiente:
Aprovechando que la multiplicación y la división tienen la misma prioridad el código podría reordenarse
de la siguiente manera:
ADDI R1,R0,#40
ADDI R4,R0,#2
LOOP: LW R2,0(R1)
LW R5,-4(R1)
SUBI R1,R1,#8
SUBI R3,R2,#1
SUBI R6,R5,#1
DIV R2,R2,R4
DIV R5,R5,R4
MUL R2,R3,R2
MUL R5,R6,R5
SW 8(R1),R2
BNEZ R1, LOOP
SW 4(R1),R5
De esta manera conseguiríamos eliminar un bloqueo más en cada iteración.
c)
Generalizando los resultados del aparatado a para Cnk
ADDI R4,R0,#k!
ADDI R1,R0,#40
LOOP: LW R2,0(R1)
SUB R3,R2,#1
MUL R2,R3,R2
SUBI R3,R3,#1
MUL R2,R3,R2
… (k-2 veces)
SUBI R3,R3,#1
MUL R2,R3,R2
DIV R2,R2,R4
SW 0(R1),R2
SUBI R1,R1,#4
BNEZ R1, LOOP
Tc = (Ciclos_1 + 8*Ciclos_n + Ciclos_10) * Periodo de reloj = [(12 + (k-2)*2) + 8*(10+(k-2)*2) + (13 +
(k-2)*2)] * 10 ns = 200*k+650ns
Las nuevas instrucciones no producen bloqueos.
Descargar