3/7/15

Computación Paralela

(O cómo el funcionamiento de un procesador se parece a cocinar para mucha gente, o a una cadena de montaje)

En episodios divulgativos anteriores de este blog he intentado explicar por encima las motivaciones del trabajo de investigación que me ha llevado donde estoy. Primero, se habló de antenitas muy pequeñas hechas de grafeno, para luego intentar clarificar para qué nos podrían servir estas antenas muy pequeñas: para mejorar las redes que comunican diferentes núcleos de un procesador.

La gracia quizás ahora estaría en saber por qué demonios un procesador tiene diferentes núcleos o procesadores que se coordinan entre sí y que necesitan comunicarse. La respuesta corta es que esta es la manera que se tiene de poder seguir con el progreso que se ha ido sosteniendo durante los últimos 40 años y que básicamente busca aumentar el cabal de computación (el número de instrucciones simples que un procesador puede ejecutar en un tiempo determinado) sin disparar otras cosas como el consumo de energía.

La respuesta larga no tiene por qué ser mucho más interesante, pero allá va...


Se hace difícil imaginar cuántos millones y millones de euros se invierten anualmente en una carrera para hacer los procesadores más rápido y eficiente. Históricamente ha habido una carrera similar a la espacial, en la que diferentes países e instituciones han buscado tener siempre el superordenador capaz de ejecutar más instrucciones por segundo ejecutando aplicaciones científicas. Empresas como Google o Facebook tienen naves industriales monstruosas llenas de ordenadores en red que se encargan de procesar miles de millones de peticiones diarias que llegan a sus servidores, de gente que realiza búsquedas en Google, sube fotos a Facebook, etc. De forma similar, Apple o Dropbox necesitan un músculo brutal para servir todo lo que la gente y las empresas suben, modifican, bajan de la nube. A pequeña escala estamos la gente de a pie, que tiene un portátil o un móvil capaz de hacer cosas que alguien nunca hubiera imaginado hace unos cuantos años.


Si bien quizás últimamente la tendencia no esté tanto en hacer el ordenador más rápido porque sí, sino en hacerlo de la forma más eficiente posible (para que Google no necesite una central nuclear para abastecer sus servidores, por ejemplo), lo que los escenarios anteriores tienen en común es que basan gran parte de sus logros en el paradigma de la computación paralela. Y esto no es más que hacer que varios componentes hagan trabajos independientes a la vez para ganar tiempo.

Hace más de 40 años, hubo un buen hombre que trabajaba en el mundo de los semiconductores y que se aventuró a predecir que los avances científicos permitirían, cada año y medio aproximadamente, doblar el número de transistores que se pueden meter en la misma superficie. A grandes rasgos, esto acabó significando que los procesadores podrían funcionar más rápido, en el sentido siguiente. Imaginad que el procesador fuera una rueda que va a M vueltas por segundo y en cada vuelta de la rueda se ejecutaran N instrucciones (en total MN instrucciones por segundo). Este avance básicamente decía que los procesadores podrían dar más vueltas por segundo (por ejemplo 2M), de manera que se ejecutarían más instrucciones por unidad de tiempo (2MN).


En el gráfico anterior veréis que la evolución que los procesadores reales han ido teniendo a lo largo de los años ha sido la que predijo el bueno de Moore. En verde tenéis el número de transistores por procesador a lo largo de los años, que efectivamente ha ido doblándose sin parar. No en vano la Ley de Moore es de lo más fiable que ha habido últimamente y que de alguna manera marca la pauta de objetivos a cumplir para las empresas que se dedican a esto.

El lector es avispado y verá, no obstante, que la línea amarilla, que marca la velocidad (en vueltas por segundo) a la que estos procesadores funcionan, ha llegado a un punto que se ha estabilizado y no parece crecer. No se trata de que no pueda crecer; en realidad lo que pasa es que se llega un punto en que no puedes asumir lo que consume un procesador que va tan rápido en vueltas por segundo.

¿Qué hay que hacer entonces? El lector es listo y verá que hay dos maneras de aumentar el rendimiento, o bien aumentando las vueltas por segundo o bien aumentando lo que se hace cada vuelta. En este segundo aspecto es donde entra el tema de la computación paralela: si por el mismo precio de tener un empleado que trabaja el doble de rápido, puedes tener tres empleados yendo a velocidad normal, ¿qué elegirías? Probablemente lo segundo ya que, si el coste de coordinar los tres muchachos no es muy alto, tendrás más faena hecha en el mismo tiempo.

El quid de la cuestión está en que para que esto funcione, necesitas que el trabajo puede repartirse entre los tres y que las dependencias sean mínimas. Puedes hacer cosas simples, rápidas, enteras y de forma repetitiva (hacer bocatas); o puedes organizarte como si fuera una cadena de montaje, donde cada uno tenga una parte de la faena (uno se harta de hacer pa amb tomàquet, el segundo de ponerle el embutido y el tercero de envolverlos).

Así pensaron los que hacen los procesadores...

UN SÓLO NÚCLEO: PARALELISMO A NIVEL DE INSTRUCCIÓN
Un procesador lo que hace básicamente es ejecutar una lista de instrucciones. Sumas, restas, multiplicaciones, guardar cosas en memoria, leer cosas de memoria, etc... Para ejecutar cada una de estas instrucciones, necesitas varios pasos: traer la instrucción de memoria, leer la instrucción, leer los operandos, ejecutarlo todo, y guardar el resultado a memoria otra vez. Esto es así siempre.

La manera de funcionar primitiva sería sólo tener a un trabajador que hiciera los cinco pasos seguidos. Si tardas un segundo para cada cosa, ejecutas 1/5 instrucciones por segundo. La segunda manera sería tener cinco trabajadores haciendo los cinco pasos seguidos. Idealmente, sacarías 5/5 instrucciones por segundo. El problema está en que cada trabajador necesitará tener todo lo necesario para ejecutar una instrucción. Es como necesitar tres fábricas diferentes para fabricar tres coches a la vez, por si acaso los tres hacen el mismo paso a la vez... Por eso se pensó en el modelo de cadena de montaje, donde cada trabajador se especializa en uno de los pasos. Otra razón para usar la cadena de montaje es que es más fácil reaccionar cuando una instrucción depende del resultado de la anterior, y tienes que pararlo todo hasta que no esté acabada.



PARALELISMO A NIVEL DE DATOS/PETICIÓN/APLICACIÓN
Con el paralelismo a nivel de instrucción nos hemos ido a lo más fino de un procesador, a como podrías mejorar para fabricar miles de millones de tornillos en masa. Pero claro, cuando tu fabricas un coche, los tornillos te vienen ya todos hechos y muchas veces atornillados. Las mejoras hechas sobre los tornillos las damos por hechas, y nos tenemos que preocupar más a lo grande.

Digamos que cuando se introdujeron las mejoras para explotar el paralelismo de instrucción, no había problemas para aumentar la velocidad y las dos mejoras se combinaban para hacer procesadores pepinos. En ese entonces, con un solo procesador mejorado ya bastaba.

Ahora bien, en cuanto el problema de la energía ha impedido que las velocidades no puedan subir tan rápido como uno quisiera, los ingenieros tuvieron que apañárselas para aumentar el rendimiento. Y para ello necesitaban explotar más paralelismo. Y para ello, pensaron en hacer procesadores más simples, pero poner más de uno por chip y comunicarlos si hace falta. Esto encaja con lo de pensar más a lo grande: si el coste de coordinar los diferentes procesadores no es muy grande, la ganancia puede ser brutal. Y más si cada vez puedes poner más procesadores.

El problema, en principio, es que a nivel de instrucción el paralelismo estaba claro porque TODAS las instrucciones eran casi iguales y seguían los mismos pasos. Ahora, lo que necesitamos es que la aplicación que vamos a ejecutar tenga paralelismo, que podamos de alguna manera partir la aplicación en diferentes trozos semi-independientes y los podamos ejecutar en paralelo sin que tengan que pararse a menudo a esperar resultados unos de los otros.

Por suerte, las aplicaciones y todo aquello que se procesa ha ido aumentando de complejidad y de tamaño, y de ahí se puede sacar paralelismo:

Paralelismo de datos: Por ejemplo, las pantallas tienen más resolución, lo que significa más píxeles o puntitos que ir refrescando cada fracción de segundo, lo que implica tener que procesar imágenes más rápido. Esto sería paralelismo de datos: tienes que realizar la misma función sobre un conjunto de datos grande a la vez y en paralelo. No dependes de los demás, pero tiene que ser A LA VEZ.

Paralelismo de petición: lo de Google y Facebook vendría aquí. Cada vez que alguien les visita, lo que hace es enviar una petición (quiero ver tu página) a la cual tienen que responder. Son simples y totalmente independientes unas de las otras, lo que pasa es que no sabes cuando van a venir. Para ello, tener varios procesadores que se vayan encargando de ir repartiéndose las peticiones es ideal.

Paralelismo de aplicación: esto ya es más peliagudo y entra más en el terreno del ingeniero que diseña la aplicación. Él debe saber qué partes pueden dividirse en trozos independientes y ejecutarse a la vez en diferentes procesadores, y qué partes necesitan resultados de operaciones anteriores y hacen pararlo todo. Si eres Toyota y tienes una fábrica totalmente modular, tienes que saber organizar las diferentes tareas para sacar el mayor rendimiento posible. Un ejemplo bastante real podría ser un simulador meteorológico. Para actualizar el mapa (dar la predicción de los próximos 10 minutos) en un punto en concreto, coges todos los datos de los puntos adyacentes y calculas unas ecuaciones que te dan el dato actualizado. Si piensas en el mapa entero, eso implica calcular la ecuación en muchos puntos a la vez pero con datos distintos (lo de sus respectivos puntos adyacentes). Podrías calcular la ecuación de cada punto en paralelo, cada una de ellas en un procesador distinto. Ahí está.

CONCLUSIÓN
La conclusión está en que desde hace tiempo el paralelismo se ha explotado en los ordenadores para hacer más trabajo en menos tiempo, pero es ahora cuando de verdad se explota a niveles más altos y por necesidad. Es por eso que los procesadores cada vez tienen más núcleos de proceso que interaccionan entre sí, y así seguirá siendo durante un buen tiempo. Bien para mí, ya que una de los grandes pilares de mi tesis es la que dice que con antenitas, podremos comunicar mejor todos estos núcleos de proceso, cosa que reducirá el coste que tiene coordinarlos.

Pero ya veremos...

4 comentarios:

  1. Menys mal que en el teu coco tens uns bons procesadors molt ben comunicats per treballar tot aixó. Olé mi Chechu!!

    ResponderEliminar
  2. natural que necesitis ceremonies del té per recargar piles, je, je

    ResponderEliminar
  3. comparto opinión del progenitor "olé mi Chechu!"
    a seguir con las antenitas, sé que son el futuro ;) i tu també!!!

    ResponderEliminar
  4. Este comentario ha sido eliminado por el autor.

    ResponderEliminar