Bienvenida arrow Especiales arrow Grand Central, ¿pero éso qué es?
Grand Central, ¿pero éso qué es? PDF Imprimir E-Mail
Herramientas para facilitar la programación concurrente, por Borja Marcos   
Friday, 19 de June de 2009

grandcentralminilogoEl elemento más importante de Snow Leopard es una cosa llamada Grand Central. Este artículo pretende explicar de manera asequible qué es, para qué sirve, por qué es tan novedoso, y qué impacto va a tener sobre el usuario.

Es largo, pero  para entender de qué va la fiesta es imprescindible tener mínimamente claras unas cuantas ideas.

¿Parche o novedad?

En multitud de sitios, nadie sabe muy bien a santo de qué (o sí, pero es feo señalar con el dedo) se ha leído que la nueva versión de Mac OS X, Snow Leopard, es un simple parche para actualizar las presuntas "morcillas" que, aseguran,  habría cometido Apple con Leopard. ¿Será el nombre lo que ha hecho que gente con nulos conocimientos sobre la naturaleza, aparte de sobre Informática, ha confundido al personal?

Snow Leopard es de hecho la actualización más importante que se ha hecho a Mac OS X. Y no se llama Mac OS XI, estoy seguro, porque la X tiene su razón de ser desde el punto de vista del marketing. El que sea una "versión decimal" no significa que no sea importante, porque cada cual llama a las versiones como le viene en gana. Como muestra un botón: Los de Sun Microsystems de la noche a la mañana, convirtieron Solaris 2.7 en Solaris 7, porque Microsoft había llamado a su nueva abominación Windows NT 5. De ahí pasaron al 8, 9, 10, 11...

Si uno echa un vistazo a las características anunciadas de Snow Leopard, no parece ciertamente gran cosa. A lo largo de las distintas versiones de Mac OS X, Apple nos ha acostumbrado a hacer dos tipos de cambios: internos y visibles. Los cambios internos son más que obvios de una versión a otra dado que, salvo raras excepciones, se han traducido en mejoras de prestaciones, al menos por mi experiencia. Por supuesto, esto puede variar dependiendo del software que use cada uno, etc. Pero es indiscutible que en las versiones anteriores han hecho numerosos cambios muy visibles. Spotlight, Time Machine, etc, son quizás los ejemplos más llamativos.

¿Qué han hecho entonces? Pues añadir una característica fundamental, Grand Central, y asumo que reescribir y reorganizar buena parte del sistema operativo para aprovecharse de ello. El ejemplo más patente es quizás el nuevo Quicktime X.

Concurrencia y núcleos múltiples

Para entender qué es Grand Central, es imprescindible conocer cuál es el problema que pretende resolver. Daremos un repaso a esto a continuación. La explicación es bastante técnica, y muy larga, aunque intentaré que sea asequible a gente incluso sin conocimientos de programación.

Hay dos formas de mejorar el rendimiento de nuestros equipos: con procesadores más rápidos, o añadiendo más procesadores. El problema del procesador más rápido es que parece que nos hemos dado con un muro de cemento. En el año 1985 se hablaba de un límite en 100 MHz. Aquél límite se sorteó sin problemas, pero ahora parece que el muro anda cerca de los 3 GHz, un santo grial para los PowerPC G5, por los motivos que fuera, y una barrera que los Intel ahora mismo superan a duras penas. Por aquí parece que el camino está cerrado.

La alternativa, por tanto, es añadir más procesadores, lo que equivale a los efectos que nos interesa, a añadir núcleos. De hecho, usaré de forma indistinta el término "procesador" o "núcleo". Esto es algo que ha sido frecuente desde hace muchos años en sistemas grandes que atienden a miles de usuarios o que hacen cálculos especializados. Sin embargo, el éxito de la fórmula en una estación de trabajo es relativamente limitado. Y esto se debe a un motivo: la concurrencia.

Historia de la concurrencia

Haciendo un poco de historia, la concurrencia, también conocida como "multitarea", nació hacia los años 60, como respuesta a un problema: los sistemas de la época, dedicados al proceso por lotes, pasaban la mayor parte del tiempo esperando. Un proceso por lotes sencillo era algo como leer un inventario de una cinta, leer otra cinta con un listado de operaciones de almacén, y dar como resultado un nuevo inventario actualizado en otra cinta. 

Con el paso del tiempo, los procesadores fueron aumentando su rendimiento, y comenzaron a ser mucho más rápidos que los dispositivos de entrada y salida (cintas, lectores de tarjetas, etc) por lo que, como ya se ha mencionado, pasaban la mayor parte del tiempo esperando. Sin embargo, ese tiempo era carísimo. Un ordenador con un coste de muchísimos miles de dólares, un consumo eléctrico brutal, y una vida útil de un número determinado de horas, desperdiciaba dinero a manos llenas. Así nació la necesidad de intentar aprovechar esos tiempos de espera para realizar otras tareas. Había nacido lo que en sus tiempos se denominó tiempo compartido.

Utilizo el término "tiempo compartido", porque se trataba de ejecutar a la vez varios programas sin ningún tipo de colaboración o interacción entre ellos. En estas circunstancias, si el sistema operativo es capaz de hacerlo, no hay mayor problema. De hecho, una aplicación típica que ejecutamos en nuestro ordenador no necesita tener en cuenta el hecho de que hay otros programas corriendo. Safari, por poner un ejemplo, no está programado teniendo en cuenta que en otra ventana tendremos el Textedit. Eso es cosa del sistema operativo.

Tiempo después empezaron a emplearse estas técnicas para realizar programas concurrentes, en los cuales varias tareas que se ejecutaban a la vez sí colaboraban o competían por recursos compartidos, y entonces fue cuando se descubrió que la concurrencia no es en absoluto fácil de manejar: se había abierto la Matrioska de Pandora.

Problemas de la concurrencia

Programar no es fácil. Y con la concurrencia la cosa se pone mucho peor; uno debe prestar atención a muchos más detalles aún. Cuando varias tareas se ejecutan a la vez empleando el mismo recurso, debe tenerse en cuenta que, dependiendo de las velocidades a las que se ejecuten, el resultado puede ser diferente. Por tanto, no vale con probar el programa una vez, ver que funciona y santas pascuas.

Veamos un ejemplo: Tenemos una cuenta bancaria en la cual vamos a hacer dos ingresos. A la izquierda colocamos el saldo, y en otras dos columnas tenemos las operaciones que vamos haciendo. Hacer un ingreso es algo muy simple. Basta con tomar el valor del saldo, sumarle el valor del ingreso, y almacenar el nuevo valor del saldo. Ingresemos un euro:


VENTANILLA

leer saldo (10.000)
obtener nuevo valor: 10000 + 1
almacenar nuevo valor: (10.001)


Simple, ¿no? Esto es lo que hace un programa de ordenador. Vemos que, en general, consta de varias operaciones. Hace falta leer el saldo de donde lo tenemos almacenado, sumar la cantidad que vamos a ingresar, y acto seguido almacenar el nuevo saldo.

Veamos ahora qué pasa si hacemos el mismo ingreso desde dos ventanillas. Desde una de ellas vamos a ingresar 10.000 euros, y desde la otra, 1.


SALDO VENTANILLA1 VENTANILLA 2

10.001 leer saldo leer saldo
nuevo: 10.001 + 10.000
                         nuevo valor: 10001 + 1
almacenar nuevo: 20.001
20.000
almacenar nuevo: 10.002
10.002

¿Y qué pasó? En teoría el saldo tras los dos ingresos debería de ser de 20.002 euros. ¡Y faltan 10.000! Algún lector dirá que he hecho trampa, porque deliberadamente he descrito el proceso de manera que se pierda el ingreso de la ventanilla 2. Sin embargo, esto es algo que puede ocurrir, dado que no hay garantía alguna sobre la velocidad a la que se ejecutan distintas tareas. Las instrucciones se podrían intercalar de cualquier forma. En un banco que hiciera las cosas así, un porcentaje de los ingresos se perdería. Para un cliente sería una lotería tener el saldo correcto al final del día o ver evaporarse un ingreso importante.

Más de uno pensará: "pero esto es muy fácil de solucionar, basta con..." exacto. Basta con implantar una medida de control. Dos personas no entran al mismo retrete a la vez, y podemos impedir que las dos ventanillas manipulen la cuenta a la vez. Esto se conoce como exclusión mutua, y es la clave de la programación concurrente.

Una vez resuelto este problema, parece que ya podemos lanzarnos a hacer programación concurrente y poner todos nuestros núcleos a humear a gusto. Sin embargo, acabamos de abrir otra caja de Pandora. Y es que las cosas se complican.

De entrada, nos encontramos con una nueva complicación: el programador debe prestar atención en todo momento a la exclusión mutua, asegurándose de proteger todos y cada uno de los recursos a los cuales puede haber acceso compartido por varias tareas. Y los despistes ocurren, como con tantas otras cosas. Si a la hora de programar se deja algún recurso compartido sin proteger debidamente, habrá veces que el programa funcionará mal. No siempre, que es lo que dificulta enormemente la detección de estos problemas.

Pero aún hay más, algo bastante peor, y es que la exclusión mutua viene con sus problemas añadidos. La caja de Pandora resulta ser una de esas muñequitas rusas. Y se trata del problema del interbloqueo. ¿Qué pasa si dos tareas, que necesitan los recursos A y B, intentan hacer algo parecido a esto?

TAREA 1                TAREA 2
reservar A             reservar B
reservar B             reservar A

Pues que la tarea 1, tras reservar el recurso A, intenta reservar el B, que ha sido ocupado por la tarea 2. La tarea 2, que tiene el control del B, intenta tomar a su vez el control del A, pero resulta que no está libre. ¿El resultado? Cada una de las tareas está esperando a que la otra libere un recurso. Pero estos recursos nunca se liberarán. Este problema se conoce también como "abrazo mortal" (deadlock en inglés).

No vamos a entrar en detalles sobre el problema del interbloqueo, que aún da lugar a tesis doctorales. Parece mentira, pero existe una disciplina, la auténtica informática, en contraposición a la "informática de manual", que estudia los aspectos teóricos de este tipo de problemas, mucho más complejos de lo que parece a simple vista.

Entremos en los aspectos prácticos. ¿Qué significa todo esto? En resumen:

1- La programación se complica mucho. Hay que prestar atención a más detalles

2- Hay tareas que no son fáciles de descomponer en múltiples procesos. Otras que si, pero esto es muy variable.

3- No siempre es fácil conseguir maximizar el rendimiento. La exclusión mutua complica mucho este aspecto.

La consecuencia más evidente es el rendimiento: en general no se aprovecha igual  la potencia de, digamos, dos procesadores que van a X GHz que la de uno que fuera a 2X GHz. De ahí que al mirar en el monitor de CPU veamos que haciendo cosas como comprimir un vídeo, etc, no sube el uso de CPU al máximo. (Puede deberse también a la eficiencia del disco duro, pero esa es otra historia que no vamos a contar aquí).

¿Se puede facilitar la programación concurrente?

De donde llegamos al auténtico Santo Grial: ¿Es posible hacer que todo esto sea más fácil? Y de momento, la cosa no ha sido nada fácil debido a varios escollos. En primer lugar, existen lenguajes de programación diseñados teniendo en cuenta las necesidades de la programación concurrente. Desde lenguajes exóticos como Orca, o especializados como Erlang, hasta lenguajes de uso más común, como Java o Ada.

Pero por desgracia, la mayor parte de los desarrolladores trabaja en C, C++ o en Objective C, que tampoco son los lenguajes más apropiados del mundo para el desarrollo de aplicaciones (otro tema del que no hablaremos aquí). El caso es que es muy difícil que la comunidad de desarrolladores adopte un lenguaje más apropiado.

Por otra parte, hay otro escollo aún más serio: la dependencia de enormes bibliotecas de servicios como Cocoa. Esto limita la elección de los lenguajes de programación, y además plantea problemas para la adopción de la concurrencia. De nada sirve que un programador sea un auténtico as de la programación concurrente, si los servicios que emplea su programa no han sido diseñados teniendo en cuenta la concurrencia. Y la realidad es que la mayor parte del software que existe ahora mismo no está preparado.

Para poner la guinda, hay, por si fuera poco, un problema más, y es de educación. En los estudios superiores relacionados con la informática, de una u otra forma se estudia programación concurrente, pero en general queda en el recuerdo como una "asignatura teórica sin interés ni aplicación práctica" (parte de esa teoría inservible según muchos se enseña en las universidades). La práctica actual de la ingeniería de software, por si fuera poco, muy centrada en la programación orientada a objeto y una suerte de nuevo traje del emperador llamada UML no solamente es inadecuada sino incluso contraproducente, no solamente desde el punto de vista de la programación concurrente, sino también desde el de la seguridad. Pero esto es otro tema más sobre el que no procede extenderse aquí.

Y programar en un lenguaje que no está preparado para la concurrencia es aún peor, claro. Especialmente en C hay que invertir una buena cantidad de tiempo en definir convenciones y normas para evitar dispararse en el pie. 

Los lenguajes concurrentes, por otra parte, aunque facilitan algo las cosas siguen adoleciendo de un problema: el programador tiene que pensar en concurrencia, tiene que decidir qué elementos de su programa se convertirán en procesos concurrentes, y, como ya he mencionado un poco más arriba, lo que se está enseñando sobre ingeniería del software no sirve para nada. 

Y no, es computacionalmente posible (a no ser que se demuestre lo contrario) diseñar un "lenguaje de programación inteligente" que a partir de un programa convencional sea capaz de producir un programa concurrente. Hay procesadores capaces de hacer eso con un puñado de instrucciones, pero nada más.

Y aquí es donde entra Grand Central en escena. Por un lado conviene mantener los lenguajes de programación actuales para evitar el choque. Además está claro que, por muchas ayudas que ofrezca un lenguaje concurrente tradicional, la mayor parte de los programadores no están acostumbrados a la multitarea. Hace falta otra cosa. 

Y esto es lo que parece que ha hecho Apple, otra cosa. Hay dos motivos por los cuales no es posible para un programa de ordenador hacer una división mágica en varios procesos: los efectos colaterales (es decir, cambios en recursos que afectarían a otros procesos) y las dependencias temporales. 

La solución por la que han optado es diferente, y novedosa: proporcionar unas extensiones de lenguaje que permiten definir bloques bien delimitados que pueden ejecutarse con más libertad. Además de eso, han añadido la maquinaria para gestionarlos y controlar su procesamiento en los distintos procesadores/núcleos.  Y el resultado es lo que se conoce como Grand Central.

Con esto han sustituido un problema difícil (definir hilos, procesos, exclusiones mutuas, sincronizaciones, etc) por otro mucho más fácil, que es marcar bloques de código que pueden ejecutarse, digamos, "sueltos". Para un programador es mucho más fácil emplear este mecanismo que ponerse a gestionar distintas tareas y sus interacciones.

Bueno, pero... ¿para qué me servirá a mí?

Una de las aplicaciones que dicen que han reescrito para Snow Leopard es el Safari. La carga y el dibujo en pantalla de una página web, especialmente cuando ésta contiene elementos dinámicos, es un ejemplo del tipo de tarea que se beneficiará enormemente de esta posibilidad, empleando al máximo (dentro de lo posible) los recursos de procesador disponibles en el equipo.  Otro elemento clave es Quicktime X, que, según Apple, también ha sido reescrito, y entiendo que  empleando GC, por lo que muchas de las tareas de Quicktime, al margen de que emplee o no OpenCL, deberían ver su rendimiento muy mejorado.

En definitiva, con Snow Leopard y su Grand Central, las aplicaciones que se reescriban empleándolo deberán ver su rendimiento incrementado, y desde luego mejorará enormemente el aprovechamiento de los recursos disponibles. Será mucho más fácil encontrarse con los procesadores y/o núcleos trabajando al 100 % cuando se lleven a cabo tareas largas como conversiones de vídeo, en lugar de ver cómo en ocasiones se está empleando solamente la mitad de los recursos (o menos) en una tarea larga, cosa que resulta de lo más frustrante.

Desde el punto de vista de la seguridad, esto de los "bloques" de Grand Central tiene también muchísimo interés. Según han dejado caer en la última keynote, Safari además llevará a cabo tareas como la ejecución de "plugins" dentro de 
un entorno restringido (lo que se puede conocer como "caja de arena -sandbox- o una jaula) con el fin de mitigar los riesgos de seguridad que tales plugins representan a menudo. Si Grand Central incorpora medidas especiales de protección de recursos, cosa que creo que podría dar una pista sobre el motivo por el cual Snow Leopard ha dejado atrás el PowerPC G5, realmente el código basado en GC será más seguro, mucho más difícil de explotar.

Así que creo que el balance no está mal: mejores prestaciones aunque, por supuesto, la pelota estará en el tejado de los programadores de aplicaciones, que por supuesto deberán rediseñar partes de sus aplicaciones para beneficiarse de ello, pero creo que tienen incentivos más que notables para hacerlo.

Una noticia excelente, sin duda. Me parece el avance más importante que llega a un sistema operativo dirigido al gran público en más de 20 años, y desde luego sitúa a Mac OS X en una liga completamente diferente del resto.

Sobre el posible impacto negativo de un cambio tan radical, creo que no será para tanto. En primer lugar, porque no creo que esto sea algo en lo que empezaron a trabajar con el primer anuncio de Snow Leopard. Seguramente llevan un buen montón de tiempo con ello. Además, esto es un mecanismo de muy bajo nivel, y comprobar su corrección no es complicado. En caso de estar mal hecho, lo más probable es que el sistema fuera incapaz de arrancar siquiera. Si el sistema arranca y funciona, significa que esta maquinaria incrustada en lo más profundo del sistema funciona. Por supuesto podrá haber problemas con las aplicaciones que lo empleen, pero sospecho que tampoco serán tantos; la propia forma de definir los bloques, junto con la forma en la que imagino que lo han implementado, servirá como mecanismo de prevención.
 
 
Actualización 24/8/2009: Por fin he encontrado un artículo publicado en 1989 en la revista Dr. Dobb's Journal que muestra una idea remotamente similar, basada en una extensión de lenguaje, en este caso hecha en Forth, un lenguaje de programación apropiado para sistemas embebidos, y en el que está hecho, entre otras cosas, el Open Firmware que llevan los Macs PPC.
 
http://www.ddj.com/architect/184408085?pgno=5
 
"A Timed Event Network Scheduler in Forth".
 
El artículo es durillo, pero un vistazo en diagonal, los dibujos y el ejemplo de código deberían ser bastante ilustrativos.
 
 

Tags:
View blog reactions

 
< Anterior   Siguiente >

Colabora con Macuarium

  • Compra en nuestra apple store

    Apple Store

    Comprando desde nuestra Apple Store particular ayudas a mantener Macuarium.
    Ir a la tienda...
  • tarjeta macuarium

    Tarjeta Macuarium

    El principal medio que existe para colaborar en el mantenimiento de Macuarium.com
    Consiguela Ahora...
  • Vistete con macu

    Camisetas Macuarium

    Vistete a la moda, con nuestra selección de ropa y complementos de macuarium.
    Ir al probador...

Apadrina un servidor

Cantidad:
$