¿Donde estás?

En mi página personal

Donde voy escribiendo sobre aquellas cosas que me interesan relacionadas con Informática, Inteligencia artificial, Seguridad informática y temáticas afines

Mis blogs

Mis blogs sobre Seguridad Informática y sobre Computación e Inteligencia Artificial

Ir a El laberinto de Falken

Ir a Divertimentos informáticos

 
Blog

¿Cómo sería hoy Internet sin la WWW?

Son muchos los que piensan que Internet es sinónimo de la web, sin embargo Intenet, como pila de protocolos de comunicaciones por conmutación de paquetes nació mucho antes. A finales de la década de los 60 se crea la red ARPANET, que es generalmente considerada el embrión de lo que a la postre será el Internet que hoy conocemos. Sin embargo, no es hasta el 6 de agosto de 1991 cuando Berners-Lee presenta oficialmente la propuesta formal de lo que es hoy la WWW (World Wide Web) o simplemente web.
La web, pues, no es más que una de las posibles aplicaciones que pueden darse a la red Internet, aunque como el tiempo se ha encargado de demostrar, es la principal hoy día.

Primer servidor web de la historia

Primer servidor web de la historia

Pero ¿y si Berners-Lee no hubiera inventado la web? ¿Cómo sería hoy Internet?
Por supuesto que usaríamos los protocolos como SMTP, POP3 o IMAP para el correo electrónico o FTP para el intercambio de archivos, pero ¿habría algo que sustituyera a la actual web?

También en el año 91, investigadores de la Universidad de Minesota publicaron la especificación para un protocolo para Internet llamado Gopher. Este protocolo facilitaba la organización de la información en forma de árbol, donde cada nodo era el equivalente a una página de texto. Además, se permite enlazar nodos mediante menús de forma similar a los enlaces de la web, aunque con más limitaciones. También se disponen de carpetas, la posibilidad de descargar archivos y hasta un servicio de búsqueda.
Tenemos, pues, algo que se asemeja bastante a la actual web y que durante algún tiempo se llegó a usar bastante (en relación al número de usuarios de Internet de aquellos días), así que no es aventurado pensar que Gopher (o la evolución de éste) ocuparía el lugar de la WWW. Sin embargo, la Universidad de Minesota pretendía cobrar por el uso, así que la web de Berners-Lee acabó extendiéndose al ser una tecnología totalmente gratuita y abierta.

Gopher

Gopher

Te estarás preguntando que ha sido de Gopher y si se sigue usando en la actualidad. Como podrás imaginar su uso es muy minoritario, pero aun quedan servidores que ofrecen servicios Gopher. Si quieres probar a conectarte a uno de estos servicios lo primero que necesitas es un cliente.
Para Windows puedes usar Gopher Client y para Linux puedes usar este. Otra opción es usar OverbiteFF, que se instala como plugin del navegador web (Firefox, Chrome e incluso para Android) y por lo tanto es multiplataforma.
Si no quieres instalar un cliente Gopher aun podrás probarlo usando GopherProxy o el proxy Floodgap.

¿Y ahora? He aquí algunos enlaces interesantes. Fíjate en que estas URLs comienzan con gopher:// en vez de con http://. Además se utiliza el puerto 70 en lugar del 80 para las conexiones. Los siguientes enlaces pueden usarse directamente sin necesidad de cliente Gopher ya que utilizan el proxy Floodgap.

gopher://gopher.floodgap.com/ Servidor Gopher de Floodgap
gopher://gopher.floodgap.com:70/7/v2/vs Buscador Gopher Veronica
gopher://gopher.rbfh.de:70/1/Code Códigos de la revista Linux Magazine hasta 2010.
gopher://gopher.quux.org:70/1/ Sitio de quux.org
gopher://gopher.quux.org:70/1/Software/Gopher/servers Listado de algunos servidores Gopher
gopher://gopher.floodgap.com:70/1/new Listado de algunos Sitios Gopher “modernos” (posteriores a 1999)
gopher://world.std.com/ The Online Book Initiative
gopher://christop.mooo.com/ Sitio de PunixOS. Un SO para la calculadora TI-92+

Desgraciadamente muchos sitios han desaparecido, pero mucha de la información que un día se publicó bajo el protocolo Gopher puede encontrarse en The Gopher Archive, que almacena información desde los años 80.
Algunos piensan que la estructuración de la información a la que obliga Gopher facilita el acceso a ésta, frente al caos de información que hay actualmente en la web. En todo caso, es una pena que poco a poco vaya desapareciendo todo el universo de Gopher (o Gopheresfera) como ya pasó con los servidores de news, ya que muere una parte fundamental de Internet y que está en su propio ADN.

 

¿Arquitectura Von Neumann?

Eckert y Mauchly

Eckert y Mauchly. Diseñadores, junto a Von Newman, de EDVAC

La arquitectura de computadores es una ciencia relativamente nueva y, a pesar de los increíbles avances que estamos obteniendo hoy día con las nuevas arquitecturas paralelas, GPUs, etc, este avance no es tan grande, arquitecturalmente hablando, como podríamos pensar. Los actuales ordenadores están basados fundamentalmente en la misma arquitectura desde que la computadora EDVAC fue diseñada por John Presper Eckert, John William Mauchly y John von Neumann. Esta computadora tenía una arquitectura diferente a su predecesora ENIAC. Tenía cinco partes bien diferenciadas: La unidad aritmético-lógica o ALU, la unidad de control, la memoria, un dispositivo de entrada/salida y el bus de datos que proporciona un medio de transporte de los datos entre las distintas partes. Es decir, exactamente la misma arquitectura que el ordenador que estás usando para leer este post. Esta arquitectura fue descrita en “First Draft of a Report on the EDVAC” (1945), escrito por Von Neumann basándose en los trabajos llevados a cabo en la EDVAC. En este documento, pues, están planteadas las bases de la moderna arquitectura de computadores, y se ha dado en llamar, de forma injusta a mi parecer, arquitectura de Von Neuman. En la práctica totalidad de la bibliografía se reconoce a Neumann como su creador.

Es evidente, sin quitar el mérito que le corresponda a Von Neumann, que tanto Eckert como Mauchly aportaron a dicha arquitectura, al menos, tanto como Neumann (y basándose en los trabajos previos de Eckert y Mauchly, hay quien podría pensar que más). Si hay que poner un nombre a la arquitectura que utilizan hoy nuestros ordenadores, creo que es justo reconocer a todos sus principales artífices. Un nombre como “Arquitectura Neumann-Eckert-Mauchly” o simplemente “Arquitectura EDVAC” sería más justo.

 

Los primeros videojuegos

Nolan Bushnell

Nolan Bushnell

No cabe duda de que el negocio del videojuego es uno de los que más capital mueven actualmente, de hecho, la microinformática nunca se habría popularizado sin los videojuegos. Pero, ¿quiénes fueron los precursores de esta industria? Sin duda, si hay un nombre propio a resaltar es el de Nolan Bushnell, considerado por muchos como el creador del primer videojuego de la historia, el archiconocido Pong. Pero nada más lejos de la realidad, el mismo Nolan había creado años antes un juego llamado Computer Space basado en un videjuego que había visto en un PDP-1 de la Universidad de Utah llamado Spacewar!. Por aquel entonces algunos ingenieros ya habían creado juegos para las máquinas de la época, como la versión del tres en raya para la máquina EDSAC. En cualquier caso, Nolan fue de los primeros en ver el potencial económico de aquellos juegos, así que con un capital de 500 dólares creó Atari en Junio de 1972. Al Alcorn fue el primer ingeniero contratado por Atari, y el creador de Pong. La máquina fue un éxito rotundo y en muy poco tiempo se estaban instalando cientos de miles de Pongs en bares y salas de recreativos de todo mundo. A partir de ahí Atari empezó a crear juegos legendarios, en los que los jóvenes echaban millones de monedas todos los días. Pero el verdadero paso importante para Atari fue la creación de la primera videoconsola de cartuchos intercambiables de éxito: la Atari VCS/2600. Antes, Atari había vendido con bastante éxito la que durante mucho tiempo fue considerada la primera consola para casa: Pong. Pero ¿fue realmente la primera consola para el hogar? Una sentencia de un tribunal terminó con la batalla entre Nolan y Ralph Baer, inventor de la consola Magnavox Odyssey.
Ralph Baer

Ralph Baer

Dicha consola fue anterior a la del fundador de Atari, y por lo tanto, Ralph terminó obstentando el gran honor de ser el primer creador de una consola de videojuegos para el hogar (además de embolsarse una no despreciable suma a costa de Atari). El primer juego que Ralph incorporó a la Odyssey se llamaba Tenis, y como puede observarse en la fotografía, el parecido con Pong parece algo más que casual.
Magnavox Odyssey Tennis

Magnavox Odyssey Tennis

Lo más curioso de la Odyssey es que era totalmente analógica, es decir, no tenía un microprocesador, sino que toda su lógica estaba hecha con transistores. Ni siquiera era capaz de almacenar puntuaciones, que debían anotarse en papel. Además su potencia gráfica era tan básica, que algunos juegos incorporaban un plástico transparente con el fondo del juego dibujado para colocarlo sobre el televisor (ver imagen del juego Tennis). Ralph Baer ha sido un prolífico ingeniero y ha conseguido algunas patentes y premios como la National Medal Of Technology en el 2005 y ha creado juegos de gran éxito como SIMON. Actualmente, ofrece sus servicios como consultor tecnológico según su propia página web.

 

El otro Quevedo

Leonardo Torres Quevedo

Leonardo Torres Quevedo

Hablar de los fundamentos históricos de la Informática es hablar de personajes como Babbage, Turing o incluso, si nos remontamos más atrás, Blaise Pascal. Desgraciadamente, pocas veces se nombra al ingeniero español Leonardo Torres Quevedo, y eso que su aportación a la informática está a la misma altura que la que hicieron los personajes nombrados. Sin duda, de haber nacido en Gran Bretaña o en Estados Unidos, hoy su nombre sería siempre puesto junto con los del resto de padres de la computación.

Torres Quevedo nace en Santa Cruz de Iguña (Cantabria) en el año 1852 y muere en Madrid en 1936, en plena guerra civil española. Estudió bachillerato en Bilbao y en 1868 se traslada a París para continuar estudios durante dos años más. A su regreso, en 1871 ingresa en la Escuela Oficial del Cuerpo de Ingenieros de Caminos de Madrid. Pero no es hasta sus 41 años, en 1893, cuando comienza a publicar sus primeros trabajos científicos.

Sus trabajos científicos e inventos destacan en el campo de la aeronáutica, el radiocontrol, las máquinas analógicas de cálculo y de la automática. Entre sus innumerables inventos podemos encontrar algunos que sentaron las bases de la informática moderna. Nos centraremos en los más importantes.

En 1903 presenta en la Academia de Ciencias de París el primer autómata telecontrolado mediante telegrafía sin hilos (ondas electromagnéticas). El invento es bautizado como Telekino. Tres años después es presentado en España, en presencia del Rey, donde hace una demostración teledirigiendo una embarcación en el agua a distancia. Nadie había hecho nada parecido anteriormente. Desgraciadamente, la falta de financiación dieron al traste con el desarrollo del invento.

Durante su prolífica vida, creó también máquinas capaces de realizar operaciones matemáticas. Estas máquinas algebraicas eran analógicas, de tipo mecánico. Desde mediados del sigo XIX ya había máquinas capaces de sumar y multiplicar, pero las de Torres Quevedo podían resolver ecuaciones de segundo grado y realizar operaciones logarítmicas. La más llamativa es el aritmómetro electromecánico. Estaba conectada a una máquina de escribir, a través de la que se introducían los números. La misma máquina de escribir, de forma automática, escribía el resultado. Pero lo más llamativo del aritmómetro era que podía realizar comparaciones entre números y operaciones lógicas, creando algo muy similar a lo que hoy entendemos como ordenador.

Pero de todos sus inventos, quizás el más espectacular fue “El ajedrecista”. Un ingenio electromecánico capaz de jugar al ajedrez gracias a un brazo mecánico. Esta máquina, y sus procedimientos algorítmicos, sienta los rudimentos de la inteligencia artificial.

Leonardo Torres Quevedo fue reconocido de forma internacional en los entornos científicos, de hecho, la noticia de su muerte fue mucho más difundida en el extranjero que en una España plenamente inmersa en la guerra civil.

 

Astrofotografía con webcam

Webcam labtec

Webcam labtec

Os presento un breve tutorial sobre cómo hacer astrofotografía con una webcam y un telescopio de modestas prestaciones. He utilizado la webcam más barata que he podido encontrar. Una labtec de 18 Euros. El problema principal de estas pequeñas webcams es que no permiten realizar largas exposiciones. La técnica consiste en tomar muchas fotografías del objeto y luego realizar la suma de las imágenes para conseguir mayor resolución. Es posible que refrigerando la cámara de alguna manera (por ejemplo, con una célula Peltier) se puedan conseguir mejores resultados.
La favorita de los aficionados es la webcam Philips SPC900 ya que permite ciertas modificaciones muy interesantes, aunque es difícil de encontrar.


Webcam abierta

Quitar tornillos y abrir

Lo primero que hay que hacer es abrir la cámara. En el caso de la labtec, sólo hay que quitar un par de pequeños tornillos de la parte trasera. De esta forma queda a la vista el objetivo de la webcam.


CCD de la webcam

Desenroscar objetivo para dejar la CCD a la vista.

Desenroscamos el objetivo hasta que quede suelto y lo retiramos, dejando a la vista la CCD. Guarda el objetivo por si algún día quieres volver a utilizar la webcam normalmente. Para ello sólo hay que volver a enroscar el objetivo.


Webcam con tubo de carrete

Poner el tubo cortado en el portaobjetivo.

Necesitaremos el envase de un carrete (cada vez más difícil de encontrar), es decir el tubito de plástico (habitualmente negro) en el que va metido el carrete fotográfico (en mi caso he usado uno blanco porque no tenía otro a mano, pero da igual, ya que el tubo queda completamente dentro del portaocular y no entra la luz). Con un cúter lo cortamos más o menos por la mitad, e introducimos la parte que no tiene fondo por el agujero de la carcasa frontal de la webcam. No tires la tapadera del tubo, ya que te sirve para tapar la CCD cuando no estás usando la cámara.


Webcam para astrofotografía

Cerrar webcam y ya está lista.

Cerramos la webcam, y ya está lista para funcionar.


Astrofotografía con webcam

La webcam encaja en el portaocular del telescopio.

El tubo entra perfectamente en el portaocular del telescopio (al menos en el mío que es de 1,25 pulgadas), así que lo introducimos igual que si fuera un ocular. Si queremos más aumentos le podemos poner una barlow sin problemas.


Astrofotografía con webcam

Conectamos webcam al ordenador

Nos resta conectarla al ordenardor y empezar a hacer pruebas. Es mejor empezar por la Luna, y seguir con los planetas mayores. La verdad es que no sé con cielo profundo qué calidad se puede conseguir, porque mi equipo es algo limitado (Meade ETX-70AT). Debajo he puesto un par de tomas de la luna. Son a foco primario (sin ocular). En la segunda he utilizado una barlow de 3X. La calidad de la imagen final depende mucho del procesado posterior de las imágenes. En este caso, las imágenes han sido generadas a partir de la suma de 100 tomas (fotogramas, ya que lo que se captura es un vídeo). Existen varios programas que podemos usar para este tipo de tomas, como K3CCD Tools o Astrostack. Para las de abajo he usado un programa llamado RegiStax.


Un par de pruebas con la luna (desde la ciudad, un seeing más que regular y sin seguimiento).
Equipo: Meade ETX-70AT. Foco primario. (en la segunda foto, lente Barlow 3X).



Fotografía de la Luna

Fotografía de la Luna a foco primario

Fotografía de la Luna

Fotografía de la Luna con barlow

 

Chuck Peddle

Chuck Peddle

Chuck Peddle


Si hablamos de microinformática, nos vienen a la cabeza personajes, sin duda importantes, como Gates o Jobs, pero la historia, y a veces la memoria, no siempre son justas. Hay personajes sin los que no sería posible entender la informática moderna y que quedan relegados a un segundo plano. Es el caso de Chuck Peddle. Uno de mis héroes personales y una de esas personas que nos sirven de modelo en nuestro día a día. Por ello quiero rendirle mi pequeño y humilde homenaje dedicándole este post.
Chuck Peddle podría haber pasado a la historia como el inventor de ordenador personal si algunos medios no se hubieran encargado de atribuir dicha hazaña a personajes más mediáticos o más de moda. Sea como fuere, Chuck creó el PET CBM más o menos en la misma época que Steve Wozniak su Apple I (de hecho el ordenador de Wozniak usaba el 6502 diseñado por Chuck).
Peddle trabajó en el diseño del microprocesador Motorola 6800. Este procesador era muy caro y Peddle pretendía crear un nuevo procesador más económico. Cuando Motorola desechó su propuesta, Peddle abandonó la compañía y se fue a otra mucho más pequeña llamada MOS Technology, dedicada a la fabricación de circuitos para calculadoras. Allí diseñó y creo el MOS 6502, que fue el microprocesador más exitoso en los primeros tiempos de la informática. Hoy en día se sigue usando incluso en productos comerciales como el Furby.
Cuando Jack Tramiel, presidente y fundador de Commodore compró Mos Technology, estaba a punto de forjarse una leyenda de la que Peddle fue en gran parte responsable. Commodore se situaba en la línea de salida de la carrera hacia el dominio de la informática personal.
Junto con el Apple I y el TSR-80, el PET de Commodore pertenecía a la primera hornada de lo que podemos llamar ordenador personal. Más tarde, ordenadores basados en la familia de microprocesadores MOS6502, como el VIC-20, el Commodore 64 o el Commodore 128 dominaron el mercado durante mucho tiempo.
Desgraciadamente, Peddle tuvo sus altibajos con Jack Tramiel y acabó abandonando Commodore ¡por dos veces! (de Commodore fue a trabajar a Apple, y luego volvió a Commodore). Cuando abandonó Commodore por segunda vez fundó Sirius Systems Technology (que más tarde cambiaría su nombre por Victor Technologies), donde creo el primer ordenador económico de 16 bits, aunque sin tanto éxito comercial como tuvo en Commodore.
La última noticia que tengo de Peddle es que CTO en una empresa llamada Celetron, dedicada al diseño de discos duros y fuentes de alimentación para ordenadores.

 

Tutorial para aprovechar los cores de tu microprocesador con OpenMP

Hoy día todos los ordenadores de sobremesa o los servidores tienen al menos dos cores o más, sin embargo, muchos programas aún no son capaces de hacer uso de ellos. Vamos a ver como usar los cores de tu microprocesador con OpenMP y mejorar así el rendimiento de tus aplicaciones.
Aunque hay varias técnicas a la hora de implementar sistemas multiprocesadores, vamos a quedarnos con las dos más comunes. Por un lado, tenemos los sistemas multiprocesadores con memoria compartida, por ejemplo, un PC con varios procesadores pero que comparten todo el rango de direccionamiento de la memoria y, por otra parte, tenemos los sistemas con memoria distribuida en los que cada microprocesador dispone de su propio rango de memoria y no pueden acceder, al menos directamente, a la memoria de otro microprocesador. Un ejemplo de este último esquema podría ser un cluster de ordenadores conectado mediante una red local en los que cada uno dispone de su propia memoria local.
Cada una de estas dos variantes tiene sus pros y sus contras, pero se hace evidente que el modelo de programación para uno y otro modelo ha de ser diferente. En el primero nos encontramos con variables y estructuras de datos compartidas entre los microprocesasores que pueden dar lugar a condiciones de carrera al manipular los datos. En el segundo modelo nos enfrentamos al problema de enviar y recibir información para cada nodo y a las latencias asociadas a la transmisión por la red local. En este artículo nos vamos a centrar en el primer modelo (de memoria compartida), y hablaremos del segundo modelo en un próximo post.
Una de las soluciones más sencillas para crear programas paralelos (aquellos que ejecutan porciones de su código de forma paralela y distribuida entre más de un procesador) es la librería de Intel OpenMP. Lo bueno de OpenMP es que ya está integrado en el compilador GCC y, por lo tanto, no necesitamos instalar ningún componente extra en nuestro sistema. Otra ventaja es que utiliza la etiqueta #pragma del preprocesador de GCC para definir las secciones paralelas, por lo que es fácil adaptar los programas existentes y además permite hacer los programas más portables, de forma que si un compilador no soporta OpenMP, podamos seguir compilando sin cambios.
Lógicamente, las secciones de nuestro código que más nos interesa paralelizar son los grandes bucles. Por ejemplo, si un bucle tiene n iteraciones y tenemos 2 microprocesadores, nos interesa que cada procesador ejecute n/2 iteraciones. Así, en un entorno ideal el bucle se ejecutaría en la mitad del tiempo que en un sistema con un sólo microprocesador. Veámoslo con un ejemplo:

int main() {         
    const int TAM=500;
    int i,j,k;
    
    float matrix1[TAM][TAM];
    float matrix2[TAM][TAM];
    float matrix3[TAM][TAM];
     
    /* asignamos valores a las las matrices */
    for (i=0; i<TAM; i++) {
        for (j=0; j<TAM; j++) {
            matrix1[i][j]=(float)i+j;
            matrix2[i][j]=(float)i-j;
            matrix3[i][j]=(float)0;
        }
    } 

    #pragma omp parallel for schedule (static) private (i, j, k)  
    for(i=0; i<TAM; i++) {  
      for(j=0; j<TAM; j++) {    
        for(k=0; k<TAM; k++) {  
          matrix3[i][j] += matrix1[i][k] * matrix2[k][j];
        }  
      }  
    }  
    
    return 0;
}

Este programa simplemente realiza un montón de multiplicaciones mientras recorre unas matrices de un tamaño considerable. En fin, un trabajo pesado de esos a los que sometemos a nuestros ordenadores. Vamos a compilarlo dos veces, una con OpenMP y otra sin él, para poder comparar. Para compilar con OpenMP sólo hemos de poner el flag -fopenmp en GCC. Es decir:

gcc -fopenmp pruebaomp.c -o conopm

Y ahora lo compilamos sin soporte OpenMP:

gcc pruebaomp.c -o sinopm

Como ves no hemos tenido que tocar una línea del código para hacer las dos versiones.
Antes de entrar a explicar cómo funciona, vamos a ver si realmente funciona, así que ejecutamos primero la versión sin OpenMP usando la orden time para ver cuánto tarda en ejecutarse (mi equipo es un dual core).

time ./sinopm 

real	0m1.221s
user	0m1.099s
sys	0m0.005s

Y ahora con OpenMP:

time ./conopm 

real	0m0.718s
user	0m1.403s
sys	0m0.008s

Nos fijamos en el tiempo real de ejecución (primera línea) y vemos que con OpenMP conseguimos un tiempo de 0,7 segundos, mientras que sin OpenMP el programa se ejecuta en 1,2 segundos. Con una simple directiva #pragma colocada estratégicamente hemos conseguido llevar casi a la mitad el tiempo de ejecución del programa. No llega a ser la mitad ya que OpenMP agrega cierto overhead en cada hilo de ejecución, pero no está nada mal para empezar.
Analicemos la directiva que hemos usado:

#pragma omp parallel for schedule (static) private (i, j, k)

Todas las directivas de OpenMP comienzan con #pragma omp seguido de una instrucción. La más usada de lejos es parallel for, ya que habitualmente lo que interesa paralelizar es la ejecución de bucles largos o con mucho uso del procesador, así que nos centraremos en ella. Como ya se ha dicho, esta directiva trata de crear tantos hilos como cores o procesadores tengamos disponibles, y asigna la ejecución de una parte del bucle a cada hilo (procesador).
Tras el parallell for vemos dos cláusulas. Por un lado schedule (static) y en seguida vemos la otra que es private (i, j, k).
Empecemos con la primera. schedule nos permite indicarle a OpenMP qué política queremos aplicar a la hora de asignar trabajo a cada hilo de ejecución. Hay varias políticas, pero las más comunes son static y dynamic. En la asignación estática OpenMP trata de repartir el trabajo de antemano entre los hilos. Por ejemplo, si el bucle hace 100 iteraciones, asignará 50 a cada uno antes de entrar en el bucle. Si la variable contadora del bucle es i, el hilo 1 realizará las iteraciones para i=0 hasta i=49 y el el hilo 2 de i=50 hasta i=100. Este método tiene la ventaja de que la asignación de trabajo a los hilos es directa, pero ¿qué ocurre si no todas las iteraciones tienen la misma carga de proceso? Observa el siguiente código:

int i=j=k=0;
#pragma omp parallel for schedule (static)
for (i=0; i<100; i++) {
    for (j=0; j<i; j++) {
        k=k*(i+j);
    }
}

Si analizamos este código llegamos a la conclusión de que las primeras iteraciones son mucho más ligeras en cuanto a carga de proceso que las últimas ya que el bucle interno realiza más trabajo cuanto mayor es la variable i. Esto quiere decir que si se asignan la primera mitad de iteraciones al primer hilo y la segunda mitad al segundo hilo, el primero terminará mucho antes y quedará ocioso hasta que termine el segundo (para obtener rendimiento nos interesa conseguir que todos los procesadores se usen el mayor tiempo posible).
En este escenario nos interesa más usar una planificación dinámica, en la que a cada iteración, OpenMP decide a qué hilo se la asigna. Esto hace que la carga se equilibre mejor, pero también conlleva una sobrecarga mayor ya que OpenMP tiene que tomar decisiones en cada vuelta del bucle.
La segunda cláusula que hemos usado, private (i, j, k), indica a OpenMP que cada hilo de ejecución va a tener su propia copia privada de las variables i, j y k. Es decir, si un hilo modifica la variable i, el otro seguirá manteniendo su propia copia con su valor original. Si queremos indicar explícitamente que una variable será compartida por todos los hilos, podemos hacerlo con shared(i, j, k). Hay que tener mucho cuidado cuando se diseñan algoritmos paralelos que comparten variables, ya que si no tenemos cuidado podemos obtener resultados imprevistos (una de las premisas de la programación paralela es que el algoritmo paralelo y el secuencia deben dar el mismo resultado, y si no tenemos cuidado con el orden al que accedemos a las variables esto podría no cumplirse).
Espero que estas pinceladas sobre OpenMP te animen a seguir investigando, ya que el tema da para escribir muchas páginas. Ten en cuenta que para no complicar demasiado la explicación se han hecho algunas simplificaciones a la hora de describir las políticas de planificación.
Otro día hablaremos del modelo de programación que se usa en multiprocesadores de memoria distribuida, como los clusters, y realizaremos un pequeño ejemplo para ilustrarlo.

 

Ejemplo de handler en Android

Mi primer contacto con Android, ya hace algún tiempo, fue para portar un juego que había hecho para la plataforma J2ME. Como Android y J2ME comparten lenguaje (Java) me las prometía muy felices pensando que el port sería casi directo. Me equivocaba.
Normalmente, el bucle principal de un juego suele correr en un thread “de fondo”. Si intentas actualizar la pantalla (en este caso un objeto Canvas) verás como Android te devuelve una bonita excepción como ésta:

android.view.ViewRoot$CalledFromWrongThreadException: 
Only the original thread that created a view hierarchy can touch its views.

Cuando lanzas un programa en Android, la ejecución se lleva a cabo en el llamado UIThread, que es el hilo principal de la aplicación y el que se encarga de actualizar la interfaz de usuario. ¿Por qué no actualizar la pantalla de juego desde el UIThread? Mi consejo: ni lo intentes. La lógica de un juego suele ser un trabajo bastante “pesado” y hará que tu aplicación se vuelva lenta y no responda bien cuando el usuario toque la pantalla. Además, a partir de la versión 4.0 de Android el propio sistema te impide hacerlo. La solución pasa, como ya se ha dicho, por usar un thread para la lógica del juego y repintado de la pantalla. Queda el pequeño detalle de repintar la pantalla desde este thread. Aquí los Handlers vienen en nuestra ayuda.

Los Handlers implementan un mecanismo de paso de mensajes entre threads de forma que nos permiten enviar mensajes desde nuestro hilo al UIThread. Para ello se utiliza el método sendMessage de la clase Handler para avisar al UIThread de que tiene que hacer el repintado de la pantalla. Os dejo un pequeño ejemplo, bastante sencillito, de cómo funciona.

En la clase principal definimos el handler e implementamos el thread.

public class EjemploHandler extends Activity {

	protected static final int MENSAJEID = 0x100;

	Thread threadVista = null;
	MiVista miVista=null;

	Handler vistaHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case EjemploHandler.MENSAJEID:
				// Invalidar vista para repintado
				miVista.invalidate();
				break;
			}
			super.handleMessage(msg);
		}
	};


	@Override
	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);

		// crear la vista
		this.miVista = new MiVista(this);
		this.setContentView(this.miVista);

		// Thread para actualizar la vista
		new Thread(new ActualizaVista()).start();
	}

	class ActualizaVista implements Runnable {

		public void run() {
			while (! Thread.currentThread().isInterrupted()) {
				// Enviar mensaje al handler para hacer invalidate
				Message message = new Message();
				message.what = EjemploHandler.MENSAJEID;
				EjemploHandler.this.vistaHandler.sendMessage(message);

				try {
					Thread.sleep(100); 
				} catch (InterruptedException e) {
					Thread.currentThread().interrupt();
				}
			}
		}
	}
}

Ahora sólo tenemos que usar nuestra clase descendiente de View como habitualmente.

public class MiVista extends View {

	int posx, posy, deltax, deltay;
	Paint fondo = new Paint();
	Paint bola = new Paint();

	public MiVista(Context context) {
		super(context);
		posx=10; posy=10; deltax=2; deltay=2;
		fondo.setColor(Color.GRAY);
		bola.setColor(Color.BLUE);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawRect(0, 0, canvas.getWidth(), 
						canvas.getHeight(), fondo);

		if (posx > this.getWidth() || posx < 0) {
			deltax=deltax*-1;
		}

		if (posy > this.getHeight() || posy < 0) {
			deltay=deltay*-1;
		}          

		posx=posx+deltax;
		posy=posy+deltay;

		canvas.drawCircle(posx, posy, 10, bola);
	}
}

Hay alternativa a los Handlers, como el uso de la clase AsyncTask, que nos permite realizar tareas de fondo con bastante control. Decir, antes de cerrar el post, que si quisiéramos hacer un juego medianamente complejo, es más interesante usar la clase SurfaceView en vez de la clásica vista con View como la del ejemplo anterior.