S2: Computadores y Rendimiento (I) - myTeachingURJC/Arq-computadores-01 GitHub Wiki

Sesión de Teoría 2: Computadores y Rendimiento (Parte I)

  • Tiempo: 2h (1h teoría + 1h ejercicios laboratorio)
  • Objetivos de la sesión:
    • Comprender el contexto de los computadores y sus abstracciones
    • Corrección de Ejercicios de Prácticas

Contenido

Introducción

Un aspecto muy importante de los procesadores es su rendimiento. No sólo queremos que funcionen bien, sino que funcionen a la máxima velocidad posible. Estudiaremos cuáles son los aspectos que influyen en el rendimiento de un procesador y cómo comparar diferentes computadores para determinar cuál es mejor. En esta primera parte nos centraremos en explicar ideas generales para tener intuición sobre todos los niveles y la complejidad que hay en los computadores. Y saber a grandes rasgos cómo mejorar el rendimiento

Las 8 Grandes Ideas en la Arquitectura de los Computadores

Esta es la recopilación de las 8 mejores ideas de los últimos 60 años del diseño de computadores. Se han obtenido de manera empírica, fruto de la experiencia del campo. Son ideas muy potentes, ya que han transcendido al computador en el que se utilizaron por primera vez. Son ideas que se han imitado y han sobrevivido

Estas ideas estarán presentes durante todo el curso

Diseñar Teniendo en cuenta la Ley de Moore

Hay algo que permanece constante en el diseño los computadores: la rápida evolución. La Ley de Moore es una regla empírica que afirma que los recursos de los circuitos integrados se duplican cada 18 - 24 meses. Esto significa que al cabo de 2 años, los chips tendrán el doble de transistores (o serán el doble de potentes)


(Fuente: Wikipedia)

Así, en los proyectos grandes, que duran varios años, desde la especificación inicial hasta que el prototipo del nuevo ordenador está terminado, los recursos de los chips se habrán duplicado o cuadriplicado. Los ingenieros deben anticiparse a eso, y tenerlo en cuenta. ¿Dónde estará la tecnología dentro de dos años?

Usar Abstracciones para simplificar el diseño

Para hacer que los diseños complejos sean abordables se usan abstracciones. Con ellas se establecen diferentes niveles de representación. Los detalles de bajo nivel se ocultan y se ofrece un modelo simplificado en los niveles superiores

Un ejemplo muy sencillo de abstracción es el bit. El bit es la unidad mínima de información, que representamos como 0 ó 1. Tal y como se implementan con la tecnología actual, los bits son voltajes en el nivel inferior, y se consigue conmutar un bit usando transistores. Un estado aparece cuando el transistor conduce y el otro cuando no conduce. Pero en el nivel superior trabajamos con los bits, y nos da igual si son debidos a transistores que conducen, a válvulas de vacío, a relés que se conectan/desconectan, etc. En el nivel superior se hace abstracción de todos estos detalles y nos quedamos con lo mínimo: un bit a 0 ó 1

Acelerar el caso más frecuente

Acelerar el caso más frecuente tiende a mejorar el rendimiento más que si aceleramos casos raros o poco frecuentes. Normalmente, además, el caso frecuente suele ser más simple que el raro y por tanto más fácil de mejorar. Es muy importante hacer mediciones para detectar el caso más frecuente, y poder así centrarse en su mejora

Rendimiento mediante Paralelismo

El rendimiento se incrementa realizando operaciones en paralelo

Rendimiento mediante segmentación

Un caso particular de paralelismo muy importante en la arquitectura de computadores es la segmentación. Imagínate una cadena de personas que se pasan cubos de agua para apagar un fuego. En un extremo una persona los llena y los pasa. En el otro extremo otra persona echa el agua al fuego y devuelve el cubo vacío. La cantidad de agua que se echa (rendimiento) es mucho mayor que si los individuos de la cadena llevasen cada uno un cubo desde la fuente hasta el fuego

Rendimiento mediante predicción

En algunos casos se consigue mayor velocidad media si se hace una suposición y se empieza a trabajar en ella que si simplemente se espera hasta tener la certeza. Es válido siempre y cuando el mecanismos para recuperarse de una predicción incorrecta no sea demasiado caro

Jerarquía de memorias

Como programadores queremos que la memoria sea rápida, grande y barata. Los arquitectos han conseguido tener estas tres características (que son excluyentes) mediante la jerarquía de memorias. En la cima de la jerarquía están los dispositivos de almacenamiento más rápidos, más pequeños y más caros. En la base los más lentos, grandes y baratos.

Gracia a la caché, los programadores tenemos la ilusión de que la memoria principal es casi tan rápida como la que está en la cima de la jerarquía y casi tan grande y barata como la que está en su base

Fiabilidad mediante redundancia

Las computadoras no sólo tiene que ser rápidas, sino que ¡tienen que ser fiables! Puesto que cualquier sistema físico puede fallar, podemos aumentar la fiabilidad añadiendo componentes redundantes. Si uno falla, actúa el otro

Mirando debajo de tu programa

Una aplicación típica, como un navegador, procesador de texto o una hoja de cálculo tiene millones de líneas de código y depende de unas bibliotecas donde están implementadas funciones fundamentales que dan soporte a esa aplicación

Sin embargo, el hardware de un ordenador (el procesador), sólo puede ejecutar unas instrucciones extremadamente simples: sumar registros, asignar valores, almacenar un registro en memoria... Pasar de una aplicación compleja a las instrucciones primitivas del procesador involucra varias capas de software que interpretan o traducen las operaciones de alto nivel a las instrucciones sencillas del ordenador. Es un gran ejemplo del potencial de la abstracción

Las capas de software se organizan de una forma jerárquica, con las aplicaciones en el anillo exterior y el software del sistema situado entre el Hardware y el software de aplicación

Hay dos tipos fundamentales del software del sistema: Sistema operativo y el compilador

Sistema Operativo

Es el interfaz entre el programa de usuario y el hardware. Entre sus funciones más importantes destacan:

  • Gestión de las operaciones de entrada y salida (E/S)
  • Asignación de almacenamiento y memoria
  • Reparto seguro de los recursos del sistema entre múltiples aplicaciones que se ejecutan de forma simultánea

Ejemplos de sistemas operativos: GNU/Linux, iOS, Windows, Android

Compiladores

Los compiladores traducen un programa escrito en un lenguaje de alto nivel, como C, C++, Java, Python, Javascript en instrucciones que el hardware puede ejecutar. Dada la sofisticación de los lenguajes actuales y la simplicidad de las instrucciones del hardware, esta traducción es compleja. Aquí veremos una panorámica general y en el tema 2 profundizaremos más

Del lenguaje de alto nivel al código máquina

El procesador ejecuta instrucciones que están almacenadas en la memoria en binario. Por ejemplo, para el RISC-V, esta instrucción de 32 bits realiza la suma de dos números situados en dos registros:

00000000101101010000001010110011

Para representar números binarios de muchos bits utilizamos una notación más compacta: el sistema hexadecimal. Cada dígito hexadecimal se corresponde con 4 bits. Así, el número binario anterior de 32 bits lo podemos representar en hexadecimal mediante 8 dígitos hexadecimales:

00B502B3

Originalmente, los programadores de los primeros computadores usaban directamente el código máquina en binario. Esto era muy tedioso y daba lugar a muchos errores por lo que se inventaron nuevas notaciones para hacerlo más fácil: se asignaron nombres a cada una de los números del código máquina, naciendo así el lenguaje ensamblador. Así, la instrucción anterior, se representa en "humano" de esta forma:

add x5, x10, x11

Los programadores escribían sus programas en lenguaje ensamblador en una hoja de papel, lo simulaban "mentalmente" y lo convertían manualmente a código máquina. Para hacer esa tarea más sencilla, se creó un programa para automatizar esta conversión de lenguaje ensamblador a código máquina: el programa ensamblador

Esto supuso un gran avance, aunque el lenguaje ensamblador seguía estando muy lejos de la notación humana usada, por ejemplo, por los científicos para simular fluidos o por los contables para hacer sus balances. Al programar en ensamblador, se está obligando a los humanos a pensar como los computadores. Y este proceso no es trivial y requiere esfuerzo

Por ello, otro gran avance fue la aparición de los lenguajes de alto nivel y de unos programas que traducen estos lenguajes cercanos a los humanos a lenguaje ensamblador: los compiladores

En esta figura vemos un ejemplo concreto. Un programador ha escrito la función expresion() en lenguaje Python para realizar el siguiente cálculo a partir de las 4 variables pasadas como parámetros: (a + b) - c + d +50. La función realiza el cálculo y devuelve el resultado

def expresion(a, b, c, d):
  return (a + b) - c + d + 50

Esta información se encuentra almacenada en un fichero, que llamamos fichero fuente. El compilador traduce del lenguaje Python al lenguaje ensamblador. El resultado sería un código como este, que en este ejemplo se está usando el RISC-V de 32 bits (que ya conocemos de las prácticas del laboratorio):

expresion: 
  add x5, x10, x11
  sub x6, x13, x12
  addi x6, x6, 50
  add x10, x5, x6
  jalr x0, x1, 0

Y finalmente el programa ensamblador lo convierte a código máquina para que el procesador lo pueda ejecutar

00000000101101010000001010110011
01000000110001101000001100110011
00000011001000110000001100010011
00000000011000101000010100110011
00000000000000001000000001100111

Es este código máquina el que se almacena en la memoria principal

Típicamente el código máquina lo representamos mediante números en hexadecimal para facilitar su lectura. Así, el programa anterior tendría esta pinta:

00B502B3
40C68333
03230313
00628533
00008067

Ventajas de los lenguajes de alto nivel

Los lenguajes de alto nivel nos ofrecen muchas ventajas:

  • Pensamiento más cercano al natural: Permiten que el programador piense de una forma más natural, más cercana al pensamiento humano. Y ya NO estamos obligados a pensar como los computadores. Se usan palabras humanas (en inglés) y notación algebraica. Los programas se parecen más a textos humanos que a crípticas tablas con símbolos

  • Adaptación de los lenguajes a aplicaciones específicas: Esta separación en alto nivel y código del procesador permite crear nuevos lenguajes cuya notación se adapte a una aplicación específica. Por ejemplo, el lenguaje Fortran se diseñó para hacer cálculos científicos, mientras que el Cobol está adaptado para el procesamiento de datos en la empresa. Al final todos se traducen a código máquina para que los ejecute el procesador gracias al compilador

  • Mejora de la productividad: Lleva menos tiempo desarrollar programas escritos en lenguajes de alto nivel que requieren menos líneas para expresar una idea. Es todo más conciso

  • Portabilidad: Los programas escritos en lenguajes de alto nivel son independientes del ordenador en el que se escribieron. Los compiladores lo traducen a la máquina concreta para que se ejecuten

Debido a todas estas ventajas, prácticamente ya no se programa en lenguaje ensamblador, salvo para aprender el funcionamiento de los procesadores, diseñar procesadores, programar compiladores o crear funciones muy específicas en sistemas críticos

Lecturas del libro de referencia

Te propongo que leas esta página del libro de referencia: "Computer Organization and Design. Hardware/Software interface. RISC-V"

  • Apartado 1.2: Eight Great Ideas in Computer Architecture (Pag 11-12)
  • Apartado 1.3: Below your program (Pag 13-16)

Hecha un vistazo al artículo en Wikipedia sobre La ley de Moore

Resolución de los Ejercicios de PRACTICAS

Resolución de los ejercicios de las sesiones de prácticas (L1 y L2). Recuerda que las soluciones están disponibles, por si las quieres ver por tu cuenta

Notas para el profesor

  • Título informal de la clase: "Citius, Altius, Fortius"
  • Lema de los juegos olímpicos: más rápido, más alto, más fuerte...
  • Además de entender cómo funciona un computador, los ingenieros estamos muy obsesionados con lograr que vaya cada vez más rápido... que ejecuten cada vez más instrucciones en menos tiempo...

Autores

Licencia

Créditos

Enlaces