Parallel Series: Video – 01 Bases

claqueta

En este primer video de las Parallel Series veremos qué es la programación paralela y el cambio de paradigma que va a suponer en el desarrollo de software.

En la primera parte veremos un poco de historia y conoceremos los motivos que nos han llevado hasta aquí, mientras que en la segunda nos centraremos en aclarar algunos conceptos base, necesarios para el correcto desarrollo de aplicaciones que utilicen la Task Parallel Library.

Como todos los videos de esta serie se trata de un vídeo de corta duración (mi intención es que todos duren 15 minutos aproximadamente), para que pueda ser visto en cualquier momento y además facilite la portabilidad a dispositivos móviles. Hoy en día hay que aprovechar cualquier momento para formarse! :-)

Enlaces relacionados:

Un poco de historia

Aclarando conceptos base

Volver al índice de contenidos

Parallel Series: Aclarando conceptos base

Cuando hablamos de programación paralela conviene tener bastante claros algunos conceptos a nivel de sistema operativo. En este apartado trataremos de aclarar estos términos, ya que más adelante los usaremos frecuentemente.

Procesos (Processes)

Toda aplicación ejecutándose en el sistema operativo existe dentro del contexto de un proceso, aunque no todos los procesos se corresponden con aplicaciones visibles. Basta abrir el administrador de tareas para comprobar que la lista de procesos es bastante mayor a la de aplicaciones. Eso es así porque pueden corresponderse a servicios, aplicaciones no visibles o porque algunas aplicaciones -como algunos navegadores- están diseñadas para crear varios procesos.

Processes

Un proceso proporciona los recursos necesarios para ejecutar un programa. Contiene un espacio de memoria virtual, código ejecutable, un contexto de seguridad, un identificador de proceso único, variables de entorno, y al menos un thread de ejecución.

Process

Cada proceso se inicia con un único thread, a menudo llamado thread principal. Pero puede crear threads adicionales, que pueden ser utilizados para encargarse de diferentes tareas.

Hacer llamadas entre procesos resulta complejo y muy costoso en términos de rendimiento debido a que deben usarse mecanismos especiales como pipes, sockets o llamadas RPC (Remote procedure call).

Dominios de aplicación .NET (AppDomains)

Al ser .NET una plataforma que ejecuta código administrado, los procesos que se crean al ejecutar éstas aplicaciones son un poco diferentes, ya que cuando se diseñó .NET una de las máximas preocupaciones fue la de tratar de mejorar el manejo de los procesos clásico o no administrados. Por ello se creó el concepto de dominio de aplicación, que podría definirse como un proceso lógico dentro del proceso del sistema operativo.

AppDomain

La gran diferencia es que dentro de un proceso podemos crear distintos dominios de aplicación y cargar en cada uno de ellos varios ensamblados, y aprovechar que las llamadas entre distintos dominios de aplicación y los ensamblados que contienen son mucho más rápidas que entre procesos. Si uno de estos ensamblado debe ser compartido entre dos dominios de aplicaciones éste se copia en cada uno de los dominios.

De este modo, al usar los dominios de aplicación se obtiene la ventaja de aislar el código de un proceso a otro, pero sin pagar el sobrecoste dedicado a realizar llamadas entre procesos.

Hilos (Threads)

Un thread es la entidad dentro de un proceso encargada de ejecutar el código. Todos los threads que contiene un proceso comparten los recursos y memoria virtual de éste, y mantienen controladores de excepciones, una prioridad de programación, almacenamiento local, y un identificador de thread único.

Los threads son independientes a los dominios de aplicación, de forma que podemos pensar en ellos como elementos transversales que pueden saltar de un uno a otro a lo largo del tiempo. No existe ninguna correspondencia entre el número de threads y de dominios de aplicación.

Por defecto, todos los procesos se crean con un thread por defecto llamado thread principal, aunque en las aplicaciones .NET se crear al menos dos, ya que es necesario al menos un segundo thread para administrar el recolector de basura. No obstante cada proceso puede crear un número casi ilimitado de ellos, aunque en última instancia el sistema operativo siempre tiene la potestad de priorizar a la baja estos hilos o incluso congelarlos.

Thread

Realizar cambios de contexto entre threads es muchísimo más rápido que los cambios de contexto de proceso. De hecho en los sistemas operativos que utilizan multitarea preemptiva (la gran mayoría hoy en día) el sistema operativo va cediendo una pequeña fracción de tiempo a cada uno de los threads de cada uno de los procesos cargados para que ejecuten una porción de su código ejecutable, dando la sensación de que varias aplicaciones se ejecutan al mismo tiempo.

Este tipo de multitarea tiene la ventaja frente a sus predecesores de que si un proceso deja de responder, el sistema no se colapsa y puede seguir respondiendo sin verse afectado por la caída del mismo. Esto en la práctica ha significado la casi desaparición de las llamadas BSOD (Blue Screen Of Death).

Multihilo (Multithreading)

A la capacidad que tienen los procesos de crear distintos threads ejecutándose simultáneamente es a lo que llamamos Multithreading. Y nos ha permitido simular la multitarea en los ordenadores personales de la última década y media. Esto es así porque aunque físicamente sólo hay un microprocesador, en términos del sistema operativo éste cede un periodo de tiempo a cada thread de cada uno de los procesos cargados en el sistema, y al repetirse una y otra vez produce la sensación de que todas las aplicaciones se ejecutan al mismo tiempo, pero nada más lejos de la realidad. Al menos hasta hace poco.

Multithreading

Paralelismo (Parallelism)

Con la aparición de los primeros microprocesadores con varios núcleos, al fin se pudo ejecutar código en paralelo y obtener la tan deseada multitarea real, ya que distintos threads pueden ejecutarse en distintos cores al mismo tiempo. De modo que a más cores, más threads pueden ejecutarse y por consiguiente más código.

Parallelism

Hace apenas cuatro o cinco años de la aparición de los primeros dual core, sólo un poco más tarde aparecieron los quad core, y hoy en día es bastante habitual ver estaciones de trabajo con 8 y hasta 16 cores. En cuanto al futuro, nadie sabe al ritmo que evolucionará esta tecnología, pero los chicos de Intel hace más de dos años ya filtraron imágenes de un Windows Server 2008 con 256 cores. Incluso los súper ligeros procesadores para teléfonos y tablets basados en ARM están empezando a lanzar modelos de dos y cuatro cores.

image

Volviendo al ejemplo de los monos, resulta muy tentador pensar que si aprovechamos toda la potencia de los nuevos núcleos podemos obtener ganancias de rendimiento espectaculares y escribir los 200 tomos en el tiempo que escribimos uno de ellos.

Evidentemente esta afirmación es un poco exagerada, ya que siempre va a haber un arduo trabajo de sincronización entre los diferentes monos… perdón threads. Con todo, la ganancia es espectacular, llegando fácilmente a multiplicar x5 o x6 en un entorno con 8 cores. Algo nada despreciable en según qué procesos. De modo que viendo el número de cores hacia dónde nos movemos, a mi juicio se hace imperativo conocer -si no dominar- la TPL.

Antes de terminar, un consejo

Como se ha visto, sólo puede existir paralelismo real en una estación con varios cores. De otro modo el código funcionará sin errores pero solo utilizando el único core de la máquina. Así que un error bastante común entre los desarrolladores es utilizar máquinas virtuales para desarrollar, y olvidarnos que la mayoría no permiten especificar varios cores. De modo que es bastante probable que alguna vez nos encontremos refunfuñando porque un código bien escrito no obtiene ninguna ganancia cuando lo ejecutemos dentro de una maquina virtual.

A continuación…

En el próximo post veremos cómo extender LINQ con Paralel LINQ, y de este modo dotar a nuestras consultas de paralelismo sin apenas impacto en el código actual.

Volver al índice de contenidos

Parallel Series: Un poco de historia

Un poco de historia

La programación paralela no es nada nuevo. Ya estaba presente allá en mis tiempos de estudiante hace más de 20 años, y hoy en día, desde la aparición del .Net Framework 4.0 está más viva que nunca gracias a la Task Parallel Library o TPL.

No obstante, decir que la TPL sólo sirve para realizar tareas asíncronas es como decir que un smartphone sólo sirve para llamar por teléfono. Es más, muchísimo más. Y es precisamente, de la mano de ésta librería que vamos a introducirnos en el apasionante mundo de la programación paralela. Una disciplina que tradicionalmente siempre ha estado asociada a los perfiles técnicos más elevados, y reservada para ocasiones especiales. Sin embargo, a partir de ahora y gracias a la TPL va a ser accesible a todo tipo de desarrolladores, y se va a convertir en algo muy importante, algo que todo buen desarrollador deberá añadir a su lista de activos. De hecho, va a ser una parte esencial en el futuro inmediato del desarrollo de aplicaciones para Windows 8 y posteriores.

Pero ¿qué realmente es la programación paralela? Podemos pensar en ella como en la posibilidad de dividir una tarea larga y pesada en varias tareas más cortas, y ejecutar éstas al mismo tiempo, de modo que tarde mucho menos que la tarea original.

Enciclopedias y monos

Vamos a suponer que tenemos que copiar los 200 tomos de la gran enciclopedia galáctica de Términus. Lógicamente no es lo mismo copiarlos uno detrás de otro, que contratar a 200 monos mutantes entrenados para copiar, y sentarlos en 200 escritorios con sus 200 bolígrafos a copiar los 200 libros. Es evidente que la segunda opción es mucho más rápida.

Pero ¿qué sucede si sólo tenemos 100 escritorios y bolígrafos? Pues que los monos van a tener que hacer cola y esperar su turno, de modo que cuando uno de los monos termine o se canse de escribir, deberá ceder su turno al mono que espera, provocando por el camino algunas colas y enfados por parte de los monos, que son buenos trabajadores pero un poco particulares.

Con todo, siempre será más rápido que la primera opción, pero la primera conclusión es que a más recursos (escritorios y bolígrafos) más rápido terminaremos la tarea. Y de paso menos vamos a tener que preocuparnos de gestionar los turnos y las esperas de los monos, con todo lo que conlleva. Porque en muchas ocasiones cuando trabajamos con monos o con threads el tiempo de sincronización es primordial, y puede marcar la diferencia entre el éxito y el fracaso.

image

Leyes muertas y física cuántica

Sin embargo, hasta ahora nos ha ido muy bien con la programación tradicional ¿porque parece que ahora es cuestión de vida o muerte aprender este nuevo paradigma? Es decir, habitualmente hasta ahora no habían demasiadas ocasiones en las que una aplicación debía recurrir a la asincronía o al paralelismo (que como veremos más adelante no es exactamente lo mismo). Por qué ahora sí?

La respuesta es sencilla, parece que la buena vida se termina. Si ha habido una constante en IT en los últimos 45 años, esa es la que describe la ley de Moore: En 1965 Gordon Moore, uno de los fundadores de Intel predijo que cada 2 años (18 meses al principio) se doblaría el número de componentes de un circuito integrado. Y se ha cumplido a rajatabla hasta hoy, pero en los últimos años se están alcanzando ciertos límites que hacen que dicha ley no pueda seguir cumpliéndose.

image

Simplificando un poco podríamos decir que existen un par de problemas: El escalado de frecuencia de los microprocesadores y el calor generado por los mismos. El primero de ellos hace referencia a la dificultad de seguir incrementando la velocidad de los microprocesadores, debido principalmente a que la tecnología utilizada para diseñarlos está actualmente cerca de los 32 nanómetros y el límite físico antes de que la materia experimente cambios, se calcula que está entre los 22 y los 18 nanómetros. Esta previsto alcanzar este límite aproximadamente en sólo dos o tres años, hacia 2014. A la vuelta de la esquina.

Una vez alcanzado ese nivel de miniaturización, en palabras del científico Stephen Hawking: “La materia presenta efectos cuánticos que harían necesaria una tecnología diferente para seguir realizando cálculos a ese nivel”.

El segundo de los problemas va ligado al primero, y es que en los últimos años el calor generado por los microprocesadores se ha ido incrementado exponencialmente, y en términos de densidad de potencia ya es igual al calor generado por la tobera de un cohete. Lo peor de todo ello es que incrementar la frecuencia sólo entre un 5 y 10 por ciento cada año, tiene un coste de casi doblar la temperatura.

ProblemasMicros_Mz_Calor

Con esto no quiero decir que no puedan fabricarse ordenadores más rápidos en un futuro. Quiero decir que si estas predicciones son acertadas, no podrán fabricarse microprocesadores más rápidos con la tecnología actual. Tal vez sea posible si se descubre cómo construir ordenadores que utilicen tecnología óptica, nano-ingeniería para crear transistores basados en nanotubos que aprovechen el llamado efecto túnel, o cualquier otro concepto aún por descubrir. Pero por el momento no podemos contar con ello.

Deus ex machina

Si por algo se ha caracterizado el ser humano es por su gran habilidad en resolver problemas (dejando aparte su nada desdeñable habilidad para provocarlos), de modo que ya hace unos años que se ha empezado a desarrollar y fabricar una de las soluciones a este problema. De hecho hoy en día se ha convertido en algo casi cotidiano: Se trata de fabricar procesadores con varios núcleos, que se repartan el trabajo -como los monos- consiguiendo así aumentar la velocidad. No por el hecho de ser cada vez más rápidos, si no por existir cada vez más recursos trabajando al mismo tiempo. Algo parecido -salvando las distancias- al cerebro humano, que en comparación con un ordenador es infinitamente más lento, pero su capacidad de procesamiento en paralelo gracias a sus millones de conexiones entre neuronas, no tiene rival con ningún otro elemento conocido en la naturaleza ni creado por el hombre.

A continuación…

En el próximo post aclararemos algunos conceptos básicos, pero muy necesarios cuando desarrollamos aplicaciones que hagan uso de la programación asíncrona.

Volver al índice de contenidos

Parallel Series: Índice de contenidos

Sobre esta serie

Este índice de contenidos y la serie en general van a estar en proceso continuo de cambio. Aunque tengo muy clara la estructura principal de las Parallel Series, también tengo muy claro su continua evolución. Y es que a día de hoy basta con dar un vistazo a la versión developer preview de Visual Studio 11 para comprobar la gran apuesta de Microsoft por esta tecnología, con los comandos async y await. Todavía no he terminado ni la mitad de los posts que tengo previstos para la versión 4.0 y ya se vislumbran muchísimas novedades en el futuro. Cool! :-)

Índice de contenidos de las Parellel Series

Artículos relacionados

Channel9ParallelSeries2

Acerca de la navegación

A pie de página de cada post de las Parallel Series se incluirá un enlace para volver a éste índice, y de esta forma navegar por los posts de forma más o menos cómoda.

Parallel Series: El Alfa

Prólogo

Cada versión del .NET framework nos sorprende con una serie de novedades, y para cada uno de nosotros hay -al menos- una que nos roba el corazón. A mi me sucedió con la aparición de Generics con el framework 2.0, los métodos extensores y LINQ en las versiones 3.0 y 3.5 y la Task Parallel Library en la versión 4.0.

Pensándolo detenidamente tampoco no es tan extraño, al fin y al cabo siempre me ha gustado la programación asíncrona (algo que si alguien le llega a contar a alguno de mis primeros maestros de tecnología digital, se habría muerto de la risa). Sin embargo, con los años éste que escribe ha llegado -más por tozudez que por talento natural- a conocer un poco los entresijos de la programación asíncrona. Una disciplina en la que tan importante es saber lo que hay que hacer, como lo que no hay que hacer.

Así pues, cuando llegó a mis manos la primera preview de Visual Studio 2010, una de las primeras cosas que hice fue mirar que demonios era eso de la Task Parallel Library. Primero porque ya hacía un tiempo que había escuchado acerca de la muerte anunciada de la ley de Moore. Y segundo porque cualquier cosa que hiciese más llevadero el trabajo de realizar y depurar aplicaciones multihilo, bienvenido iba a ser.

tpl

Desde entonces hasta ahora he tenido la suerte de poder dedicar un poco de tiempo a esta maravilla, de modo que me he propuesto crear una serie bastante larga de posts y vídeos sobre el tema. Más que nada porque a mi juicio hay poca documentación (al menos en Español) y algo así no puede quedar relegado al olvido. Y es que en multitud de ocasiones que cuando le explico a alguien el porqué es importante y en que consiste la TPL, acostumbra a decir: “Que guapo! Pues no tenía ni idea…”. Y eso, me mata.

Nacen las Parallel Series

En los próximos posts voy a ir definiendo el índice de contenidos de la serie, aunque a medida que crezca la serie es más que probable que vaya siendo modificado y ampliado. También veremos algo de historia para ponernos en contexto, aclararemos conceptos base que van a ser necesarios más adelante, e iremos desgranando los apartados principales de la Task Parallel Library.

La idea es empezar desde abajo e ir subiendo de nivel, hasta llegar a los aspectos más complejos, como los problemas de concurrencia o la depuración de este tipo de aplicaciones. En cada apartado prometo poner al menos un ejemplo y si puedo más, porque los humanos -y los developers heredamos de esta clase base- aprendemos mucho mejor los conceptos teóricos si van acompañados de la práctica.

Nos vemos muy pronto ;-)

Channel9ParallelSeries1

Volver al índice de contenidos