Mostrando entradas con la etiqueta Laboratorio de Sistemas distribuidos y paralelos. Mostrar todas las entradas
Mostrando entradas con la etiqueta Laboratorio de Sistemas distribuidos y paralelos. Mostrar todas las entradas

miércoles, 16 de mayo de 2012

Semana 14

Aportación al proyecto hice una investigación de una buena herramienta para crear un grid, con Ganga y Python.




Y para la semana de laboratorio hice también una investigación teórica de Grid.

Grid

Grid Computing

Grid Computing se puede definir como la aplicación de los recursos de muchos ordenadores en una red a un único problema, por lo general una que requiere un gran número de ciclos de procesamiento o el acceso a grandes cantidades de datos.



La red de energía computacional es análoga a la red de energía eléctrica. Permite el acoplamiento de los recursos distribuidos geográficamente para ofrecer un acceso consistente y de bajo costo a los recursos, independientemente de su ubicación física o punto de acceso. Las redes de Internet o dedicados pueden ser utilizados para interconectar una amplia variedad de recursos electrónicos distribuidos (como supercomputadores, clusters de ordenadores, sistemas de almacenamiento, fuentes de datos) y los presentan como un recurso único y unificado.

En su esencia, Grid Computing permite a los dispositivos, independientemente de su funcionamiento a las características de ser prácticamente compartida, gestión y acceso a través de una empresa, industria o grupo de trabajo. Esta virtualización de los recursos pone todo el acceso necesario, los datos y potencia de procesamiento en las yemas de los dedos de los que necesitan para resolver rápidamente problemas complejos de negocios, realizar cálculo intensivo de investigación y análisis de datos, y operar en tiempo real.

Una empresa con un poco menos de 2.000 computadoras de escritorio pueden cosechar cerca de 1 teraflop (un billón de operaciones de punto flotante por segundo) de capacidad de computación. Aún mejor, la compañía puede capturar el poder de las computadoras que ya posee de que fuera de uso por la noche y el trabajo en menos de plena capacidad durante el día.

Universidades e instituciones de investigación han utilizado durante mucho tiempo la red de computación en la tecnología, pero recientemente también está haciendo avances rápidos en el mercado empresarial. IBM acaba de llegar a las normas de funcionamiento que va a generar muchas nuevas aplicaciones de negocios y hará que la proliferación de ancho.

Internet de Grid Computing

El Internet está evolucionando más allá del correo electrónico, contenido y comercio electrónico. Se está convirtiendo en una verdadera plataforma, que combina las cualidades de servicio de la computación empresarial con la capacidad de compartir recursos distribuidos a través de la web: aplicaciones, datos, almacenamiento, servidores, y todo en el medio.
Habilitación de dispositivos: Internet amplió la gama de cosas que los ordenadores personales puede hacer, aprovechando sus funciones de comunicación para poner servidores para trabajar el almacenamiento de archivos de copia de seguridad, servicio de páginas web personales y de bloquear el spam. Sin embargo, la computadora personal, asistente personal digital (PDA) u otros dispositivos conectados no tienen acceso transparente a todos los tipos de programas en todo tipo de plataformas. Las aplicaciones que acceden a que no están necesariamente integrados. La computación Grid mantiene la promesa de traer este tipo de poder y la capacidad de dispositivos habilitados para Internet. En un mundo inalámbrico, esta red podría permitir a los dispositivos más simples, tales como buscapersonas - para acceder a la potencia de los ordenadores a través de la red de una manera significativa.


La intensa colaboración: Hoy en día, la colaboración en línea proporciona uso compartido de documentos y permite a los debates. Este proceso va a cambiar con el grid computing, lo que facilitará la utilización conjunta de las solicitudes completas. A pesar de esto tiene gran uso de sofisticadas aplicaciones de colaboración, incluso las aplicaciones mundanas se beneficiarán. Por ejemplo: los patrones pueden ser detectados en el uso de recursos financieros, mejoras para el hogar, planificación de eventos y otras aplicaciones, y todas las aplicaciones relacionadas se beneficiarán de las opciones identificadas, y se tomen decisiones, las personas con necesidades similares. Muchos tipos de simulación, incluyendo prototipos, puede ser posible gracias a la computación grid. Esto animará a nuevas relaciones y nuevas comunidades.
Además de nuevas capacidades, hay un gran potencial para el ahorro de costes. Uso de los ciclos de repuesto (el tiempo de inactividad en el equipo), en paralelo con los ataques a los problemas, el acceso a través de dispositivos más sencillos y utilizar sólo las funciones de la aplicación que necesita debe hacer la mayoría de las aplicaciones de tecnología de la información más económico y asequible en el futuro.


Aplicaciones

Toda el área de la computación distribuida es una cama caliente de desarrollo significativo que se espera que genere avances sorprendentes en los próximos años. Y los primeros grandes aplicaciones ya están aquí.
United Technologies, el conglomerado de fabricación $ 28b, está equipando a más de 100.000 computadoras Wintel con su propio peer-to-peer software para hacer cálculos científicos y resuelve problemas complejos de modelado durante las horas libres. El proyecto es una ampliación de lo que la compañía de aviones Pratt & Whitney división de motores ha hecho para eliminar una supercomputadora Cray con 5.000 estaciones de trabajo Sun Unix, para llevar a cabo simulaciones de diseño de piezas de aviones. El resultado: el 85 por ciento de utilización para cada estación de trabajo.

Con 20.000 PCs en Pratt & Whitney, el proyecto P2P se espera reducir a la mitad el tiempo y el dinero que se necesita para desarrollar motores de turbina y otras partes de aviones, principalmente mediante la eliminación de varios millones de dólares prototipos. Anteriormente, se podría tomar $ 1 mil millones y cinco años entre el momento en un motor ha sido desarrollado y certificado.

Universidades y organizaciones de investigación han utilizado similares de procesamiento de igual enfoques para resolver problemas científicos complejos. El más famoso es un proyecto denominado SETI @ home, que utiliza los equipos de voluntarios en todo el mundo para buscar vida en otros planetas.

El Programa Intel filantrópica P2P ayuda a combatir enfermedades potencialmente mortales mediante la vinculación de millones de ordenadores en lo que se prevé que el recurso de computación más grande y rápido de la historia. Este "supercomputadora virtual" utiliza la tecnología P2P para hacer cantidades sin precedentes de poder de procesamiento disponibles para los investigadores médicos para acelerar el desarrollo de mejores tratamientos y medicamentos que podrían curar enfermedades.


miércoles, 9 de mayo de 2012

MPI con IPython


A menudo, un algoritmo paralelo requiere movimiento de datos entre motores. Una forma de conseguir esto es haciendo un tirón y luego un empujón con el cliente multimotor. Sin embargo, esta será lenta como todos los datos tienen que pasar por el controlador para el cliente y luego de vuelta a través del controlador, a su destino final.

Una manera mucho mejor de mover datos entre los motores es el uso de una biblioteca de paso de mensajes, como la interfaz de paso de mensajes (MPI). Arquitectura de cómputo paralelo IPython ha sido diseñado desde cero para integrarse con MPI.


Requisitos adicionales de instalación

  • El estandar MPI como OpenMPI o MPICH.
  • El mpi4py paquete.

Inicio de los motores con MPI


Para utilizar el código que llama a MPI, normalmente hay dos cosas que MPI requiere.

  • El proceso que se quiere llamar a MPI se debe iniciar con mpiexec o un sistema de proceso por lotes (como PBS), que cuenta con el apoyo de MPI.
  • Una vez iniciado el proceso, se debe llamar a MPI_Init ().

Hay un par de maneras para comenzar a los motores de ipython y conseguir que estas cosas pasen.

Arranque automático con mpiexec y ipcluster


El enfoque más sencillo es utilizar los lanzadores de MPI en ipcluster, que primero se iniciará un controlador y, a continuación un conjunto de motores que utilizan mpiexec:

$ ipcluster start -n 4 --engines=MPIEngineSetLauncher

Este enfoque es mejor que la interrupción de ipcluster se detendrá automáticamente y limpiará el controlador y los motores.

Empezar manualmente a usar mpiexec

Si desea arrancar los motores ipython utilizando el mpiexec, lo que hay que hacer es:

$ mpiexec -n 4 ipengine --mpi=mpi4py



Esto requiere tener un controlador en marcha y que los archivos FURL para los motores están en su lugar. También se ha construido en apoyo a PyTrilinos , que se puede utilizar (suponiendo que se instala) por el arranque de motores con:

$ mpiexec -n 4 ipengine --mpi=pytrilinos


Una vez que los motores están funcionando con el MPI, que están listos para ir. Ahora se puede llamar a cualquier código que utilice MPI en los motores de ipython. Y, todo esto se puede hacer de forma interactiva. Este es un muy sencillo ejemplo de la página oficial.

En primer lugar, permite definir una función simplemente que utiliza MPI para calcular la suma de una matriz distribuida. Y guarda el texto en un archivo llamado psum.py:


Referencias

iPy

jueves, 3 de mayo de 2012

Javascript paralelo

StratifiedJS extiende el lenguaje JavaScript con un pequeño número de construcciones de programación concurrente. Le permite expresar el flujo de control asíncrona en un estilo secuencial sencillo:



En ese código lo que se intenta recuperar las noticias de la BBC, al mismo tiempo trata de la CNN si no se recibió la noticia después de 1 segundo muestra la primera noticia que llega, y cancela cualquier solicitud que todavía podría estar en espera el tiempo de espera después de 1 minuto si no hay noticias recibidas, de forma automática la cancelación de las solicitudes pendientes.


StratifiedJS ejecuta el código en unidades lógicas que llamamos estratos. A diferencia de lo normal el código JS, los estratos se les permite "bloquear", es decir, el flujo de control se le permite detenerse en un punto determinado para ser recogidos más tarde en el mismo punto donde lo dejó. Un ejemplo sería la instrucción espera que bloquea por un período de tiempo dado.
Mientras que un estrato está bloqueado, puede ejecutar otros estratos. Los estratos son un poco como las discusiones, pero son mucho más determinista: un único estrato se está ejecutando en un momento dado y se ejecuta atómicamente hasta el punto en que o bien acabados o suspende. En ese punto el siguiente estrato pendiente se ejecuta hasta que termina o suspende, y así sucesivamente.
StratifiedJS contiene construcciones para la fundición de lógica asincrónica en forma de bloqueo (waitfor ()) y construcciones para la combinación de múltiples estratos (waitfor / y, waitfor / o desove) de una manera estructurada.

La función de StratifiedJS espera puede ser llamada con un argumento t el número de suspender el actual estrato de ~ t milisegundos:

La función de StratifiedJS espera puede ser llamada con un argumento t el número de suspender el actual estrato de ~ t milisegundos:
hold(1000);


Se debe tener en cuanta que sólo suspende el estrato que aparece en, que no bloquea todo el programa y no lo hace 'ocupado espera'. Otras capas simultáneas puede continuar para ejecutar durante este tiempo. Si está ejecutando SSJ en un navegador, la interfaz de usuario se quedará plenamente sensible durante los períodos de suspensión.


Referencia

http://onilabs.com/stratifiedjs

lunes, 30 de abril de 2012

Cena de filosofos

Para esta semana de Laboratorio implemente exitosamente y por fin, el problema de la cena de filosofos, este es el código:



Y muestra de su ejecución:



jueves, 19 de abril de 2012

PyFog

PyFog es una aplicación que usa superpy simple para crear una nube de palabras basado en un conjunto de documentos de entrada. Usted puede proporcionar listas de páginas web, archivos o feeds RSS y PyFog les arrastran al mismo tiempo, cuenta la frecuencia de cada palabra o grupo de palabras, y mostrar las estadísticas de las palabras más comunes.

Para utilizar Pyfog, sólo puede ejecutar el script fogGUI.py de la línea de comandos o haciendo clic en él. En Linux, esta secuencia de comandos debe estar ubicado en la ruta (en mi sistema que acaba en / usr / bin / fogGUI.py después de instalar superpy). En Windows, por lo general va en el directorio de secuencias de comandos (por ejemplo, en C: \ Python25 \ Scripts \ fogGUI.py).
Una vez que comience la secuencia de comandos fogGUI.py, se verá una ventana que muestra los parámetros PyFog:


Si rápido en un signo de interrogación junto a uno de los parámetros, aparecerá una ventana con información acerca de ese parámetro. Una vez que haya llenado los parámetros a su gusto (o puedes dejar los valores por defecto), haga clic en Aceptar para ejecutar PyFog. Si usted ha comenzado algunos servidores superpy en el equipo local y se especifica esto en la lista de servidores, PyFog entonces enviar los trabajos a los equipos remotos. De lo contrario, se iniciará una serie de servidores locales para aprovechar las múltiples procesadores en la máquina. En cualquier caso, se analizan las fuentes dadas a continuación, muestran la frecuencia con que se producen como se muestra a continuación.




El archivo por defecto RSS ejemplo proporcionado simplemente escanea los canales RSS de diversas fuentes de noticias. Esto nos da una idea interesante de lo que las palabras clave para las noticias de hoy son. Por supuesto, usted puede proporcionar cualquier entradas que te gusta. Usted podría intentar dar una lista de los 100 libros favoritos (o tal vez de los actuales 100 mejores libros en Amazon) y ver cuáles son las palabras clave que aparecen allí.

Al proporcionar un gran número de fuentes y la experimentación con la forma en PyFog tomas largas con diferentes ajustes para el parámetro localServers, puede tener una idea de lo bien que explota superpy múltiples procesadores en la máquina. En los procesos de desove superpy en máquinas remotas (con las secuencias de comandos o Spawn.py SpawnAsService.py provistos de superpy), se puede ver cuánto más rápido de un grupo de máquinas puede hacer en el análisis de conteo de palabras. Para una tarea como la que usted puede desear para analizar grandes fuentes tales como libros del Proyecto Gutenberg.

miércoles, 4 de abril de 2012

Distributed and parallel systems Extra Points

1. In which case is it straightforward to modify a recursive algorithm into a parallel one?
When the data are highly dependent, ie the result of the next iteration depends on the previous iteration

2. When is it impossible to turn an algorithm into a parallel one?
When there are inter-task dependencies

3. How will a process know when a thread that it previously forked finishes execution?
By using communication and synchronization between threads

4. Why do multi-threaded programs sometimes run slower than single-threaded versions?
The fact that the algoritms can be parallelized doesn't mean that they are optimal, sometimes the algoritmo is optimal only when there is a lot of data because when there is a little amount of data, it could take longer distributing tasks than running the code.

5. How does one ensure that one thread printing will not mess up another thread’s printouts?
By using locks that protect critical parts of code

Pypar

Instalarlo es sencillo necesitamos algunos paquetes

# Python paquetes
python2.5
python-dev
python-numpy
python-numpy-dev
python-imaging (PIL)


# MPI
lam4c2
lam4-dev
lam-runtime

#Descargar
http://code.google.com/p/pypar/downloads/list




Para verificar que todo se instalo correctamente tecleamos

mpirun -np 2 testpypar.py

Empezar

Importamos la librería en python:


Ahora nosotros podemos escribir algunas funciones propias de esa libreria por ejemplo
>>pypar.size()
Con eso podemos obtener el numero de procesos en paralelo, cuando usamos pypar en la linea de comandos esto debe de ser 1:


Los procesadores estan numerados desde el 0 hasta pypar.size() - 1, entonces con el comando pypar.rank(), podemos obtener el numero de procesador actual que esta corriendo:


Y para obtener el nombre del procesador del nodo actual se usa:
>>pypar.get_processor_name()
Y vemos que obtenemos el nombre de mi computadora:



Primer programa




La manera de correrlo es:

mpirun -np 4 demo.py

con esto le dices que se ejecutara en 4 procesadores y se mande una copia del programa a cada uno de ellos.


Este programa demo.py manda un mensaje de el procesador 0 y lo envía alrededor de un anillo

Cada procesador añadiendo un poco a ella hasta que llegue de vuelta en procesador 0.

Es escencial en los programas paralelos averiguar qué procesador esta ejecutando que cosa, esto se hace mediante la llamada:

myid pypar.rank = ()

El número total de procesadores se obtiene a partir

proc = pypar.size ()

Entonces uno puede tener diferentes códigos para diferentes procesadores de ramificación como en

si == 0 myid

Para enviar una estructura general de Python a un procesador de p, se escribe pypar.send (A, p) y para recibir algo de procesador de q, se escribe X = pypar.receive (q)

Esta es la base para la programación en paralelo usando Pypar, esperemos cuando este listo el cluster poder implementar esto en varios procesadores.


Referencias

Pypar

viernes, 23 de marzo de 2012

Embarazosamente paralelos

En los llamados problemas embarazosamente paralelos, un cálculo consiste en una serie de tareas que pueden ejecutar más o menos independiente, sin la comunicación. Estos problemas suelen ser fáciles de adaptar para la ejecución en paralelo. Un ejemplo es un estudio de parámetros, en la que el mismo cálculo debe llevarse a cabo utilizando una gama de parámetros de entrada diferentes. Los valores de los parámetros se leen de un archivo de entrada, y los resultados de los cálculos diferentes se escriben en un fichero de salida.


Trabajadores (W) parámetros de la petición de la tarea de entrada (I) y enviar los resultados a la tarea de salida (O). Tenga en cuenta las conexiones de muchos a uno: este programa no es determinista en el que las tareas de entrada y salida de recibir los datos de los trabajadores en el orden que los datos que se generan. Canales de respuesta, representadas como líneas discontinuas, se utilizan para comunicar los parámetros de la tarea de entrada para los trabajadores.
Si el tiempo de ejecución por problema es constante y cada procesador tiene la misma potencia de cálculo, a continuación, basta con problemas de partición disponibles en conjuntos de igual tamaño y asignar un conjunto tal que cada procesador.  Las tareas de entrada y salida son responsables de la lectura y escritura de los archivos de entrada y salida, respectivamente. Cada tarea de los trabajadores (por lo general una por procesador) varias veces pide valores de los parámetros de la tarea de entrada, calcula el uso de estos valores, y envía los resultados a la tarea de salida. Debido a los tiempos de ejecución varían, las tareas de entrada y salida no se puede esperar para recibir los mensajes de los distintos trabajadores en ningún orden en particular. En su lugar, una estructura de comunicación de muchos a uno se utiliza que les permite recibir mensajes de los diversos trabajadores en orden de llegada.

La tarea de entrada responde a una petición de los trabajadores mediante el envío de un parámetro con el trabajador. Por lo tanto, un trabajador que ha enviado una solicitud a la tarea de entrada, simplemente espera a que el parámetro para llegar a su canal de respuesta. En algunos casos, la eficiencia puede ser mejorada por prebúsqueda, es decir, que solicita el parámetro siguiente, antes de que sea necesario. El trabajador puede realizar el cálculo, mientras que su petición está siendo procesada por la tarea de entrada.

Debido a que este programa utiliza muchos-a-uno las estructuras de comunicación, el orden en que los cálculos se realizan no se determina necesariamente. Sin embargo, esto no determinismo sólo afecta a la asignación de los problemas a los trabajadores y la clasificación de los resultados en el archivo de salida no, los resultados reales calculadas.

Programar !! Python secuencial:

#!/usr/bin/python                                                                                                                                      
contador = 1
lista = []
resultados = []
f = open("entradas.txt")

#este rollo para sacar del archivo de entrada los numeritos                                                                                            
while True:
      linea = f.readline()
      if not linea: break
      print linea
      if contador % 2 != 0:
            lista.append(int(linea)) #amo python                                                                                                       

f.close()

print linea
f = open("salida.txt", "w")
for m in range(len(lista)):
      res = (lista[m])**2 #variable auxiliar que me ayuda a escribir en el array                                                                       
      resultados.append(res) #guardo en un arreglo, solo para debug                                                                                    
      cadena = str(res) + "\n" #lo que voy a poner en el archivo                                                                                       
      f.write(cadena) # escribo en el archivo                                                                                                          
f.close #lo cierro                                                                                                                                     

print lista
print resultados

Resultado :

Teminal


Archivo Salida.txt que se creo:

Python paralelo:
#!/usr/bin/python                                                                                                                                                                                                                                                               
import threading, time
import Queue

q = Queue.Queue()
o = Queue.Queue()
contador = 1

class cuadrado(threading.Thread):
      def __init__(self, num):
            threading.Thread.__init__(self)
            self.num = num
            self.res = 0

      def run(self):
            print "Calculando paralelamente los cuadrados"
            self.res = self.num ** 2
            o.put(self.res)



f = open("entradas.txt")

#este rollo para sacar del archivo de entrada los numeritos                                                                                                                                                                                                                     
while True:
      linea = f.readline()
      if not linea: break
      print linea
      if contador % 2 != 0:
            q.put(int(linea)) #ponemos en la cola                                                                                                                                                                                                                               
            print("Mando a llamar al hilo para que ejecute el cuadrado")
            h = cuadrado(int(linea))
            h.start()
            h.join()
f.close()


f = open("SALIDA.txt", "w")
print "Empiezo a escribir en el archivo"
for i in range(o.qsize()):
      cadena = str(o.get(i)) + "\n" #lo que voy a poner en el archivo                                                                                                                                                                                                           
      f.write(cadena) # escribo en el archivo                                                                                                                                                                                                                                   
f.close #lo cierro                                                                                                                                                                                                                                                              

Resultados:

Terminal



Archivo SALIDAS.txt







Más ejemplos

Algunos ejemplos de los problemas embarazosamente paralelos incluyen:


  • Consultas distribuidas de bases de datos relacionales utilizando el procesamiento distribuido conjunto
  • Servir archivos estáticos en un servidor web.
  • El conjunto de Mandelbrot y otros cálculos fractales, donde cada punto se puede calcular de forma independiente.
  • Representación de los gráficos por ordenador . En el trazado de rayos , cada píxel puede ser prestado de manera independiente. En la animación por ordenador , cada fotograma pueden ser prestados de manera independiente (véase la representación en paralelo )
  • Fuerza bruta búsquedas en la criptografía . Un notable ejemplo del mundo real es distributed.net .
  • BLAST búsquedas en bioinformática para las consultas de varios (pero no para consultas individuales de gran tamaño)
  • A gran escala de reconocimiento facial que consiste en la comparación de miles de entradas se enfrenta con el número igualmente grande de caras.
  • Las simulaciones por ordenador comparación de numerosos escenarios independientes, como los modelos climáticos.
  • Los algoritmos genéticos y otros de computación evolutiva metaheurísticas .
  • Ensemble cálculos de predicción numérica del tiempo .
  • Evento de simulación y reconstrucción de la física de partículas .
  • Tamizado paso de la criba cuadrática y el tamiz de número de campo .
  • Árbol de paso el crecimiento del bosque al azar técnica de aprendizaje automático.

Referencias

jueves, 22 de marzo de 2012

Java multitarea

Me ha parecido importante empezar a checar como sería hacer algunas cosas que puedo hacer  en Python, en Java, este post lo dedico a explicar como se crean y funcionan los hilos en Java, así como sincronizarlos, etcétera.

Los programas multihilo tienen dos o más partes que pueden ejecutarse de manera simultanea o concurrente. Cada parte del programa se llama hilo y cada hilo sigue un camino diferente. La programación multihilo es una manera especializada de multitarea.

Hay dos tipos de multitarea, a travez de procesos y atravez de hilos. Ambas son diferentes un proceso es un programa que se esta ejecutando, entonces la multitarea que se basa en procesos es la capacidad de las computadoras de ejecutar varios programas a la vez, el programa es la unidad más pequeña que el sistema de computo puede manejar.

La multitarea que se basa en hilos, el hilo es la unidad de código mas pequeño que se puede gestionar. Es decir un programa es capaz de ejecutar dos o más tareas en simultáneo. 

La multitarea que se basa en hilos tiene un menor costo de operación que las basadas en procesos. Los procesos requieren de más recursos  y necesitan espacio de direccionamieto propio. La comunicacion con procesos es costosa y limitada. Intercambiar contextos de procesos tambien es costoso. Mientras que los hilos son ligeros, comparten el mismo espacio de direccionamiento y el mismo proceso.

Los programas de Java usan entornos multitarea basados en procesos, pero esto no esta bajo control de Java. La multitarea de hilos si esta al control de Java. La multitarea que se basa en hilos permiten escribir programas eficientes que usan optimamente el CPU.

Clase Thread y la interfaz Runnable

El sistema multihilo de Java se crean en torno a la clase Thread, sus métodos y su interfaz Runnable. La clase Thread encapsula a un hilo de ejecución. Como no se puede hacer referencia directamente al estado de un hilo que se esta ejecutando es necesario usar la instancia a la clase Thread que representa a dicho hilo. Para hacer un hilo nuevo el programa debe extender a la clase Thread o implementar la interfaz Runnable.
La clase Thread define métodos que ayudan a manejar los hilos. Estos son algunos:
  • getName: Obtiene el nombre del hilo.
  • getPriority: Obtiene la prioridad del hilo.
  • isAlive: Determina si un hilo aún se esta ejecutando.
  • join: Espera a que termine un hilo.
  • run: Punto de entrada de un hilo.
  • sleep: Suspende a un hilo durante cierto tiempo.
  • start: Empieza al hilo llamando a run.
Hilo principal

Cuando los programas comienzan su ejecución, hay un hilo que se ejecuta automáticamenre, este es el hilo principal ya que es el único que se ejecuta al iniciar el programa. Este hilo es importante por dos razones:
  • A partir de este hilo será posible crear el resto de los hilos del programa.
  • Este es el último que finaliza su ejecución ya que debe de realizar ciertas acciones para terminar correctamente el programa.
Para controlar este hilo, hay que crear un objeto Thread, entonces se crea una referencia al mismo con el método currentThread(), que es un miembro public static de la clase Thread, su forma general es la siguiente:
static Thread currentThread()

Ese método devuelve una referencia al mismo hilo del que fué llamado. Una vez que se obtuvo la referencia al hilo principal es posible controlarlo como a cualquier otro hilo.

Ejemplo de Control de hilo principal

//controlamos el hilo principal                                                                                                                        

class hiloPrincipal{
    public static void main(String args[]){
        Thread t = Thread.currentThread();
        System.out.println("Hilo actual:" + t);
        //cambio del nombre del hilo                                                                                                                   
        t.setName("Hilo principal");
 System.out.println("Ahora se llama: " + t);
        try{
            for(int n = 5; n > 0; n--){
                System.out.println(n);
  Thread.sleep(1000);
            }

 }
        catch (InterruptedException e){
            System.out.println("Se interrumpio al hilo principal");
 }

    }

}

Con este programa obtenemos una referencia al hilo actual, llamando al método currentThread(), esta referencia la almacené en la variable local t. Llamamos al método setName() para poder cambiar el nombre interno del hilo.
El ciclo cuenta del 5 al 1 pausandose entre cada número 1 segundo, con el método sleep.

Creación de un hilo

Los hilos en Java se crean con el objeto del tipo Thread.java y hay dos maneras de hacer esto:
  • Implementando la interfaz Runnable.
  • Extendiendo la clase thread. 

Interfaz Runnable

La manera más facil de crear un hilo es creando una clase que implemente la interfaz Runnable, se puede construir un hilo desde cualquier objeto que implementa esta interfaz. La clase necesita implementar el método run(), que se declara asi:
public void run()
Dentro del método run(), se escribe el código que definirá un nuevo hilo.

Después de crear la clase, se crea el objeto de tipo Thread:
Thread(Runnable objeto Hilo, String nombreHilo)

El nuevo hilo que se creo no empezará su interfaz hasta que se llame al metodo start(), start() ejecuta una llamada al método run():
void start()

Ejemplo de creación de un hilo con Runnable:

//creacion de un segundo hilo                                                                                                                          
class HiloNuevo implements Runnable{
    Thread t;
    HiloNuevo(){
        t = new Thread(this, "HiloDemo");
        System.out.println("Hilo hijo: " + t);
        t.start(); //comienza el hilo                                                                                                                  
    }

    public void run(){
        try{
            for(int i = 5; i > 0; i--){
                System.out.println("Hilo hijo :" + i);
                Thread.sleep(500);
            }
        }catch(InterruptedException e){
            System.out.println("Salida del hilo hijo");
        }
    }
}
    class Hilo{
        public static void main(String args[]){
            new HiloNuevo();
            try{
                for(int i = 5; i > 0; i--){
                    System.out.println("Hilo principal: "+i);
                    Thread.sleep(1000);
                }
            }catch(InterruptedException e){
                System.out.println("Se interrumpe el hilo principal");
            }
            System.out.println("Salida del hilo principal");
        }

}

Resultado:



En este programa vemos que termina en último lugar el hilo principal, esto es porque lo altere para que así pasara, el hilo principal duerme más tiempo que el hilo hijo. En lo personal yo prefiero crear hilos implementando la interfaz Runnable me parece más fácil.

Creación de múltiples hilos

En los ejemplos anteriores solo había creado un hilo, sin embargo podemos crear tantos hijos como queramos. En el siguiente programa creo 3 hijos.

//creo 3 hijos                                                                                                                                                                                                                     

class HiloNuevo implements Runnable{
String nombre;
Thread t;

HiloNuevo(String nombreHilo){
nombre = nombreHilo;
t = new Thread(this, nombre);
System.out.println("Hilo nuevo "+ t);
t.start();
}

public void run(){
try{
for(int i=5; i>0;i--){
System.out.println(nombre +":" + i);
Thread.sleep(500);
}
}catch(InterruptedException e){
System.out.println("Interrupción del hilo" + nombre);
}
System.out.println("salida del hilo" + nombre);
}
}

class Hilos{
public static void main(String args[]){
new HiloNuevo("uno");
new HiloNuevo("dos");
new HiloNuevo("tres");
try{
//ESPERAMOS A QUE LOS OTROS HILOS TERMINEN                                                                                                                                                                             
Thread.sleep(10000);
}catch(InterruptedException e){
System.out.println("Interrupcion del hilo principal");
}
System.out.println("Salida del hilo principal");

}
}

Resultado:


Uso de isAlive() y join()

Como hemos visto en nuestros programas le decimos al hilo principal que duerma más tiempo que los demás para que no termine antes, pero esto no es muy conveniente ya que nosotros suponemos que en ese lapso de tiempo terminaran los demás, pero y si no es así?, para eso tenemos el método isAlive() que es un método definido por la clase Thread y su forma general es la siguiente:
final boolean isAlive().
Este método devuelve el valor True si el hilo al que se hace referencia aún se esta ejecutando, y devuelve false en caso contrario.
Ese método es útil en algunos casos, pero hay otro método más común join(), que se utiliza para esperar a que un hilo termine. Su forma general es:
final void join() throws InterruptedException
Ese método espera a que termine el hilo sobre el que se realizo la llamada. Su nombre viene de que el hilo llamante espera a que el hilo especificado se reuna con el. Otras formas de join permiten especificar el máximo tiempo de espera para que termine el hilo.

Ejemplo de isAlive y join()

//usamos jin para esperar a que terminen                                                                                                                                                                                                                                                                                                                                                                                                                              

class NuevoHilo implements Runnable{
    String nombre;
    Thread t;
    NuevoHilo(String nom){
        nombre = nom;
        t = new Thread(this, nombre);
        System.out.println("Nuevo hilo: "+ t);
        t.start();
    }
    //aqui entra el hilo                                                                                                                                                                                                                                                                                                                                                                                                                                              
    public void run(){
        try{
            for(int i=5; i>0; i--){
                System.out.println(nombre + ": " +i);
                Thread.sleep(1000);
            }
        }catch(InterruptedException e){
            System.out.println("Interrupcion del hilo " + nombre);
        }
        System.out.println("Sale el hilo "+ nombre);
    }
}
class DemoJoin{
    public static void main (String args[]){
        NuevoHilo ob1 = new NuevoHilo("uno");
        NuevoHilo ob2 = new NuevoHilo("dos");
        NuevoHilo ob3 = new NuevoHilo("tres");
        System.out.println("El hilo uno esta vivo " + ob1.t.isAlive());
        System.out.println("El hilo dos esta vivo " + ob2.t.isAlive());
        System.out.println("El hilo tres esta vivo " + ob3.t.isAlive());
        //espera a que los otros hilos terminen                                                                                                                                                                                                                                                                                                                                                                                                                       
        try{
            System.out.println("Espera a que finalizen los otros hilos");
            ob1.t.join();
            ob2.t.join();
            ob3.t.join();

        }catch(InterruptedException e){
        System.out.println("El hilo uno esta vivo " + ob1.t.isAlive());
        System.out.println("El hilo dos esta vivo " + ob2.t.isAlive());
        System.out.println("El hilo tres esta vivo " + ob3.t.isAlive());
        System.out.println("El hilo principal termina");
        }


}



}

Resultado



Prioridades de los hilos

El planificador de hilos usa las prioridades de los hilos para poder decidir cuando se va a permitir la ejecución de cada hilo. Los hilos que tienen prioridad más alta tienen mayor tiempo del CPU que los de prioridad baja. Un hilo de prioridad alta puede desalojar a uno de prioridad más baja. Por ejemplo, cuando un hilo de prioridad mas baja se esta ejecutando y otro  de prioridad más alta reanuda su ejecución, este segundo desalojará al de prioridad más baja.
Los hilos con la misma prioridad tienen el mismo acceso al CPU.
Para establecer la prioridad de un  hilo se utiliza setPriority(), que es miembro de la clase Thread,. Su forma general es:
final void setPriority(int nivel)
En donde nivel es la nueva prioridad del hilo. El valor del nivel debe de estar entre MIN_PRIORITY y MAX_PRIORITY. Actualmente estos valores son 1 y 10. Para establecer la prioridad por default que tienen los hilos de nuevo se usa NORM_PRIORITY, es  5.
Para obtener la prioridad de un hilo usamos getPriority() de Thread:
final int getPriority

Sincronización

En Java la sincronización parece sencilla ya que cada hilo tiene su propio monitor implícito asociado. Para entrar al monitor basta con llamar a un método modificado con la palabra clave synchronized. Mientras hay un hilo dentro de un método sincronizado, todos los demás hilos que tratan de llamar a ese método, o a otro método sincronizado sobre la misma instancia, tienen que esperar. Para salir del monitor simplemente hay que salir del método sincronizado.
La palabra clave synchronized, permite que un hilo acceda a un método sin interrupciones, aunque otros hilos quieran usarlo.

Comunicación entre hilos
  • wait() Indica al hilo que realiza la llamada que debe abandonar al monitor y quedar suspendido hasta que algún otro hilo llame al método notify()
  • notify() Activa a un hilo que previamente llamo a while en el mismo objeto.
  • notify all() Activa todos los hilos que llamaron previamente a wait() en el mismo objeto. Uno de esos hilos empezar a ejecutarse.
Los métodos se llaman asi:
final void wait()
final void notify()
final void notifyAll()

Productor consumidor en Java

class Q{
    int n;
    synchronized int get(){
        System.out.println("Consume: "+ n);
        return n;
    }
    synchronized void put(int n){
        this.n = n;
        System.out.println("Produce: "+ n);
    }
}

class Productor implements Runnable{
    Q q;
    Productor(Q q){
        this.q = q;
        new Thread(this, "Productor").start();
    }
    public void run(){
        int i = 0;
        while(true){
            q.put(i++);
        }
    }

}

class Consumidor implements Runnable{
    Q q;
    Consumidor(Q q){
        this.q = q;
        new Thread(this, "Consumidor").start();

    }

    public void run(){
        while(true){
            q.get();
        }
    }

}

class PC{
    public static void main(String args[]){
        Q q = new Q();
        new Productor(q);
        new Consumidor(q);
        System.out.println("control c para finalizar");

    }

}

En ese programa aunque se sincronizan los métodos put y get nada impide que el productor vaya más rápido que el consumidor, ni que el consumidor recolecte el mismo valor de la cola dos veces. Entonces la implementación correcta del productor consumidor es usando wait() y notify().
En el siguiente código muestro como hacerlo:

//productor consumidor simple                                                                                                                                                                                                                                                                                                                                                                                                                                         

class Q{
    int n;
    boolean valueSet = false;

    synchronized int get(){
        while(!valueSet)
            try{
                wait();
            }catch(InterruptedException e){
                System.out.println("captura de la excepcion");
            }
            System.out.println("Consume: " + n);
            valueSet = false;
            notify();
            return n;

    }
    synchronized void put(int n){
        while(valueSet)
            try{
                wait();
            }catch(InterruptedException e){
                System.out.println("Captura de la excepcion");
            }
        this.n = n;
        valueSet = true;
        System.out.println("Produce: "+ n);
        notify();
    }
}

class Productor implements Runnable{
    Q q;
    Productor(Q q){
        this.q = q;
        new Thread(this, "Productor").start();
    }
    public void run(){
        int i = 0;
        while(true){
            q.put(i++);
        }
    }

}

class Consumidor implements Runnable{
    Q q;
    Consumidor(Q q){
        this.q = q;
        new Thread(this, "Consumidor").start();

    }

    public void run(){
        while(true){
            q.get();
        }
    }

}

class PC{
    public static void main(String args[]){
        Q q = new Q();
        new Productor(q);
        new Consumidor(q);
        System.out.println("control c para finalizar");

    }

}

Resultado:


Finalmente, he aprendido a hacer programas multitarea en Java ahora podré aportar al equipo, si así se requiere programación en Java también  :) .

domingo, 11 de marzo de 2012

Cálculo del pi en paralelo

En esta semana quise complementar lo de algoritmos paralelos haciendo un algoritmo que calcula el número Pi primero en paralelo y después en secuencial.

Metodo de Montecarlo

Este algoritmo consiste en generar experimentos aleatorios independientes consistentes en generar N puntos x, y que pertenezcan de 0 a 1 y contabilizar C los números que caen dentro del cuadrante de un circulo de radio 1.


El área del circulo es igual a pi*radio **2, el área del cuadrante es pi/4, y la probabilidad es C/N = pi/4 osea pi = 4C/N.

La aproximación más precisa es cuando N tiende al infinito.
Este es el algoritmo secuencial que desarrolle:


Ejecución:



Paralelización

Este reparto consiste en la generacion de N experimentos en un conjunto de P procesadores. Cada procesador puede generar puntos y contar cuales C caen en el rango del círculo con 1 de radio.
Al iniciar solo el proceso principal conoce cuales son los valores de N, osea el número de pruebas que se quiere hacer, y cuantos procesadores se van a tener.
Después se envian a los procesos esclavos la N, para que empiezen a calcular.

Cada proceso realiza el trabajo que le corresponde


Y por último los procesos esclavos envían sus resultados al proceso maestro, para que el maestro calcule el numero de aciertos y lo multiplique por 4 (por la formula que acabamos de ver) y lo divida entre el total de experimentos N.

Mi programa en python emula este comportamiento con hilos, y queue de python para poder mandar cada suma al proceso maestro, este es el programa:


En donde señale que sean 5 procesadores, osea 5 hilos que realicen la tarea indicada.
Y la ejecución se ve así:



El algoritmo lo desarrolle tomando la lo propuesto en este pdf, donde proponen la realización de él más no códigos ni pseudocódigos.

miércoles, 8 de febrero de 2012

CORBA


¿Qué es CORBA?

CORBA es una tecnología muy potente que ayuda a construir sistemas distribuidas, sin embargo es un poco difícil por la gran variedad de funciones que tiene
Por esto mismo que es un poco difícil su aprendizaje mucha gente no usa CORBA en sus aplicaciones.


Hay algunos conceptos que debemos concer para empezar a usar CORBA
  • ORB, el núcleo: Es la parte principal que implementa las comunicaciones, los mapeos a los distintos lenguajes de programación.
  • IIOP/GIOP: Funciona como protocolo de comunicaciones entre los distintos objetos, el GIOP, que especifica el formato de las comunicaciones CORBA pero no específica transporte específico. Por eso esta IIOP, que es un GIOP sobre TCP/IP. Aquí nadamas se define el formato de los mensajes, y luego, cada ORB (implementación de CORBA) es responsable de convertir dichos mensajes en datos para la máquina en la que se está ejecutando,permitiendo así la interacción entre distintas implementaciones de CORBA ejecutándose en diferentes máquinas, con sistemas operativos diferentes, con representación de datos distinta.


  • El lenguaje IDL. Para hacer aplicaciones CORBA, uno de los primeros pasos es escribir los interfaces IDL de la aplicación. IDL es el lenguaje que permite definir una serie de interfaces para la comunicación entre dos o más aplicaciones. El IDL se escribe en un fichero, normalmente con la extensión IDL, en el cual se definen los interfaces y las funciones de esos interfaces.Un archivo.IDL podría ser el equivalente a un fichero de cabecera en C++, en el que se definen las clases (el equivalente a los interfaces CORBA) y las propiedades (variables de la clase) y métodos de esas clases. IDL no es un lenguaje para implementar interfaces CORBA, más bien es un lenguaje que define interfaces CORBA, por ello la semejanza con el fichero de cabecera de C++, donde,no se incluye ninguna implementación.
  • Cabos y esqueletos. Una vez que ya creamos el archivo.idl tenemos que usar el compilador IDL que genera los cabos y esqueletos necesarios para el uso e implementación de esas interfaces. Los cabos son el código generado para el cliente (la aplicación que va a hacer uso del objeto CORBA), mientras que los esqueletos son, el esqueleto de la implementación del objeto.
Hay compiladores IDL para distintos lenguajes de programación, con el fichero IDL, se pueden generar los cabos y esqueletos, y por tanto implementar cada una de las partes, en los lenguajes que soportan CORBA, y así ayuda a la transparencia del lenguaje de implementación de cada una de las partes que componen la aplicación.

Guía para python
Página principal
Lenguaje IDL