viernes, 27 de mayo de 2016

Arquitecturas Paralelas


Numa, Uma y SMP

Aunque el rendimiento de los procesadores no cesa de aumentar, muchas aplicaciones siguen necesitando mayores prestaciones . Esta potencia espectacular la proporcionan las máquinas de procesamiento paralelo . El crecimiento de este mercado ha sido considerable en los últimos años . Muchos fabricantes han lanzado productos con arquitecturas y nombres diversos, y hoy en día los consumidores de tecnología se enfrentan a mensajes y definiciones confusas y muchas veces contradictorias .
Con el fin de clarificar este oscuro mundo, vamos a clasificar las arquitecturas paralelas existentes, explicando las fortalezas y debilidades de cada una de ellas . Cabe mencionar que ninguna de las arquitecturas es netamente superior a las demás en todos los campos . La mejor elección dependerá de nuestras necesidades y de las aplicaciones que vayamos a ejecutar .
Fundamentalmente existen dos categorías: las arquitecturas UMA ( Acceso Uniforme a Memoria ) y NUMA ( Acceso No Uniforme a Memoria ) . En las arquitecturas UMA la memoria está consolidadada en un solo bloque y en las tecnologías NUMA la memoria está distribuida en varios puntos del sistema, por lo que el tiempo de acceso a memoria depende del lugar accedido . Cada categoría presenta varias implementaciones, pero antes de pasar a explicarlas haremos una clasificación general:
UMA:
? Sistemas de Multiprocesamiento Simétrico ( SMP )
NUMA:
? Red Distribuida
? SMP Paralelo
? ccNUMA
? Procesamiento Masivamente Paralelo ( MPP )
Arquitecturas UMA ( Acceso Uniforme a Memoria )
Sistemas de Multiprocesamiento Simétrico ( SMP ) :
Los sistemas de Multiprocesamiento Simétrico ( SMP ) son los arquitecturas paralelas más sencillas y más populares . Existen multitud de ejemplos comerciales como los HP 9000 Clase K, T y V, los Sun UE6000 y E10000, DEC 8400 o IMB RS/6000 J50 y R50 .
En estos sistemas un conjunto de procesadores reducido ( como máximo unas pocas decenas ) comparten todos los recursos ( memoria, I/O, discos, etc . ) y ejecutan conjuntamente las tareas . La gran sencillez de este modelo permite que una sola copia del sistema operativo gestione los recursos de forma totalmente transparente al usuario y a la aplicación . Hay algunas excepciones en que conviven complicadamente varios sistemas operativos en la misma máquina, como en el UE10000 .
Las ventajas de los sistemas SMP son la facilidad de programación ( el sistema operativo gestiona todos los recursos de forma transparente ) , la facilidad de crecimiento ( si se necesita más potencia se añaden nuevos procesadores ) y la facilidad de manejo, además de la eficiencia en la ejecución de operaciones colaborativas ( por el hecho de que todos compartan una única memoria ) . Las principales desventajas son su escalabilidad limitada a unas pocas decenas de procesadores y la disponibilidad ( como todos los recursos son únicos y compartidos al fallar cualquiera de éstos falla toda la máquina ) .
Los sistemas SMP son adecuados para la mayoría de las aplicaciones, especialmente aquellas que requieren alta eficiencia en el uso de memoria compartida, como los Sistemas de Soporte a la Decisión ( DSS ) y de Procesamiento de Transacciones On-Line ( OLTP ) . Hoy en día los sistemas SMP son capaces de satisfacer las necesidades de la inmensa mayoría de los usuarios .
Los sistemas SMP pueden llegar a tener una potencia asombrosa . Por ejemplo los nuevos servidores SMP V2500 de HP superan en potencia al mítico DeepBlue que ganó a Kasparov .
Arquitecturas NUMA
Redes Distribuidas:
La red distribuida ha sido introducida recientemente como solución comercial, aunque es una vieja idea que proviene de los tiempos en que nacieron las redes . En la emoción de aquellos años se pensó que sería posible coordinar una red de muchos ordenadores pequeños y baratos para resolver problemas más grandes .
La realidad es que las redes distribuidas sólo funcionan bien con aplicaciones que pueden ser particionadas, de modo que cada ordenador ejecute independientemente una parte . La cuestión es que esos problemas se encuentran básicamente en el ámbito técnico . En los problemas del ?mundo real? la necesidad de comunicación entre las ordenadores es tan grande que éstos pasan la mayoría del tiempo parados esperando respuestas . A esta ineficiencia se une la dificultad de administración de estos entornos .
Aunque las redes distribuidas tengan una aplicación muy limitada, el principio en el que se basan sigue teniendo validez: si necesitamos más potencia, conectamos varios sistemas . En los años siguientes se ha avanzado mucho en la capacidad de interconexión, hasta el punto de que en la tecnología ccNUMA se ha conseguido que varios sistemas conectados se comporten como uno sólo mucho más potente .
SMP Paralelo:
La arquitectura SMP Paralela sigue el sencillo principio antes expuesto: interconectar varios sistemas SMP ( nodos ) mediante una red de alta velocidad para que todos trabajen colaborativamente sobre una sola aplicación .
Con los sistemas SMP Paralelos se elimina la limitación en el número de procesadores de los sistemas SMP, consiguiendo tener varios cientos de procesadores en un solo sistema . Además muchas aplicaciones comerciales presentan versiones especiales para este tipo de arquitectura ( por ejemplo Informix XPS, Oracle OPS o Sybase MPP ) . Estas versiones reparten las tareas a realizar entre los nodos de tal modo que se minimice la interacción entre ellos, logrando rendimientos realmente altos . Además los nodos pueden programarse para asumir las tareas de otros en caso de fallo, aumentando de este modo la disponibilidad .
Las ventajas de estos sistemas son la mayor y más fácil escalabilidad ( para conseguir más potencia se añaden más nodos ) y la alta disponibilidad . Entre las desventajas se cuentan la necesidad de una copia del sistemas operativo por nodo y su menor eficiencia en el manejo de operaciones que requieran memoria compartida ( el acceso a la memoria de otro nodo es más lenta porque se hace a través de la red de interconexión ) .
Los sistemas SMP paralelos se han convertido en el estándar para los Sistemas de Soporte a la Decisión ( DSS ) de tamaño pequeño a grande y para Procesamiento de Transacciones ( OLTP ) pequeño a mediano ( hasta 1 Terabyte aproximadamente )
Algunos ejemplos de arquitecturas SMP Paralelas son el sistema de HP Enterprise Parallel Server ( EPS ) , el de IBM RS/6000 SP ( SP2 ) SMP-based o el NCR WorldMark 5100M .
La solución EPS de HP es tan flexible que admite la integración de hasta 16 nodos que pueden ser servidores HP de varios tipos ( incluso ccNUMA ) . De este modo satisface perfectamente tanto las necesidades de un programa de consolidación de servidores como de un incremento de la potencia disponible ( con 16 nodos ccNUMA tendríamos hasta 2048 CPUs ) .
ccNUMA:
El modelo SMP Paralelo ofrece muchas ventajas: fácil aumento de la potencia disponible, alta disponibilidad y gran flexibilidad . Su principal desventaja es la separación de la memoria en varios nodos, lo que reduce su eficiencia en aplicaciones que hagan un uso intensivo de memoria compartida .
Este problema se elimina con la tecnología ccNUMA . En ella también se tienen varios nodos SMP, pero se interconectan de tal modo que se comportan como si fueran uno solo . El sistema operativo gestiona complejas redes de interconexión que permiten que la memoria y demás recursos, físicamente separados, aparezcan como si no lo estuvieran . 

bibliografia:
http://www.computerworld.es/tendencias/arquitecturas-de-altas-prestaciones#
https://conceptosarquitecturadecomputadoras.wordpress.com/computacion-paralela/
http://informatica.uv.es/guia/asignatu/AAC/AA/apuntes/aa.pdf

sábado, 16 de abril de 2016

Paso de mensajes con Python (MPI)

MPI para python

MPI es un sistema estandarizado y portable de paso de mensajes, diseñado para funcionar en una amplia variedad de computadoras paralelas. El estándar define la sintaxis y semántica de un conjunto de funciones de librería que permiten a los usuarios escribir programas portables en los principales lenguajes utilizados por la comunidad científica (Fortran, C, C++). Desde su aparición, la especificación MPI se ha transformado en el estándar dominante en librerías de paso de mensajes para computadoras paralelas. En la actualidad se dispone de diversas implementaciones, algunas provistas por los fabricantes de computadoras de alta performance, hasta otras de reconocidos proyectos open source, tales como MPICH10 y LAM/MPI,11 muy utilizadas en los clúster de PC’s tipo Beowulf.
A pesar de los idiomas más apropiados para la computación paralela son C o Fortran, muchos investigadores prefieren lenguajes basados ​​en la matriz (como Python o Matlab) más de C y Fortran para su facilidad de uso. En particular, Python ha vuelto cada vez más popular. Por desgracia, Python no es muy adecuado para la computación de alto rendimiento y sus capacidades de las paralelas son todavía poco desarrollado. Sin embargo, por la misma razón que Python es un lenguaje excelente para el diseño de algoritmos y para resolver problemas que no requieren el máximo rendimiento, Python es una herramienta excelente en el desarrollo de código paralelo. En general, la programación en paralelo es mucho más difícil y compleja que en serie. Esto hace que la programación paralela en Python grande para la creación de prototipos y para pequeñas y medianas códigos. Incluso puede considerarse adecuado para la producción si la comunicación no es muy frecuente y el rendimiento no es la principal preocupación.
MPI para Python proporciona ataduras de la Message Passing Interface estándar (MPI) para el lenguaje de programación Python, permitiendo que cualquier programa de Python para aprovechar múltiples procesadores.

Funciones

Este módulo proporciona  la función spawn() (semilla), un front-end para diversas funciones específicas de la plataforma para el lanzamiento de otro programa en un sub-proceso. 

Ejemplo: 
Compute Pi - Master (or parent, or client) side:
#!/usr/bin/env python
from mpi4py import MPI
import numpy
import sys

comm = MPI.COMM_SELF.Spawn(sys.executable,
                           args=['cpi.py'],
                           maxprocs=5)

N = numpy.array(100, 'i')
comm.Bcast([N, MPI.INT], root=MPI.ROOT)
PI = numpy.array(0.0, 'd')
comm.Reduce(None, [PI, MPI.DOUBLE],
            op=MPI.SUM, root=MPI.ROOT)
print(PI)

comm.Disconnect()


Comm. Send buf , dest = 0 , tag = 0 
Realiza un envío básica. Este envío es una comunicación de punto a punto. Se envía información de exactamente un proceso para exactamente un otro proceso.
parámetros:
·         Comm ( Comm MPI ) - comunicador que pretende realizar la búsqueda
·         buf ( opción ) - datos que desea enviar
·         dest ( número entero ) - rango de destino
·         tag ( número entero ) - etiqueta del mensaje
Ejemplo:
import  numpy
from  mpi4py  import  MPI
a  =  numpy ([ 1 , 2 , 3 ])
if  MPI . COMM_WORLD . rank  ==  0 :
        MPI . COMM_WORLD . Send ( a ,  dest  =  1 )
else :
        MPI . COMM_WORLD . Recv ( a ,  source  =  0 )

 Comm. Recv buf , source = 0 , tag = 0 ,Status status= None 
punto a punto básico de recibir datos
parámetros:
·         Comm ( Comm MPI ) - comunicador que pretende realizar la búsqueda
·         buf ( opción ) - dirección inicial del búfer de recepción (escoja la ubicación recibo)
·         sourcenúmero entero ) - rango de fuente
·         tag ( número entero ) - etiqueta del mensaje
·         status ( Status ) - estado del objeto
Ejemplo:
from mpi4py import MPI
 
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
 
if rank == 0:
    data = {'a': 7, 'b': 3.14}
    comm.send(data, dest=1, tag=11)
elif rank == 1:
    data = comm.recv(source=0, tag=11)



Comm. Bcast buf , root = 0 
Difunde un mensaje desde el proceso con rango "raíz" a todos los otros procesos del grupo.
parámetros:
·         Comm ( comm MPI ) - comunicador a través del cual transmitir
·         buf ( opción ) - tampón
·         root ( int ) - rango de operación de raíz
Ejemplo:
import numpy
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
 
#intialize
rand_num = numpy.zeros(1)
 
if rank == 0:
        rand_num[0] = numpy.random.uniform(0)
 
comm.Bcast(rand_num, root = 0)
print "Process", rank, "has the number", rand_num



Comm. Reduce sendbuf , recvbuf , Op op = MPI.SUM , root = 0 
Reduce los valores en todos los procesos en un solo valor en la raíz proceso.
parámetros:
·         Comm ( Comm MPI ) - comunicador que pretende realizar la búsqueda
·         sendbuf ( choice ) - dirección del buffer de envío
·         recvbuf ( choice ) - dirección del búfer de recepción (sólo significativa en la raíz)
·         op ( handle ) - reducir la operación
·         root ( int ) - rango de operación de raíz

Ejemplo:
import numpy
from mpi4py import MPI
comm = MPI.COMM_WORLD
 
rank = comm.Get_rank()
rankF = numpy.array(float(rank))
total = numpy.zeros(1)
comm.Reduce(rankF,total, op=MPI.MAX)


Comm. Scatter sendbuf , recvbuf , root 
Envía datos desde un proceso a todos los otros procesos en un comunicador (Longitud de recvbuf debe dividir  la longitud de sendbuf. De lo contrario, utilice Scatterv )
parámetros:
·         sendbuf ( choise ) - dirección del buffer de envío (significativo sólo en la raíz)
·         recvbuf ( choise ) - dirección del búfer de recepción
·         root ( int ) - rango de proceso de envío
Example:
import numpy
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
LENGTH = 3
 
#create vector to divide
if rank == 0:
        #the size is determined so that length of recvbuf evenly divides the
        #length of sendbuf
        x = numpy.linspace(1,size*LENGTH,size*LENGTH)
else:
        #all processes must have a value for x
        x = None
 
#initialize as numpy array
x_local = numpy.zeros(LENGTH)
 
#all processes must have a value for x. But only the root process
#is relevant. Here, all other processes have x = None.
comm.Scatter(x, x_local, root=0)
 
#you should notice that only the root process has a value for x that
#is not "None"
print "process", rank, "x:", x
print "process", rank, "x_local:", x_local


Comm. Gatherv (choice sendbuf[, choice recvbuf,tuple_int sendcounts, tuple_int displacements,MPI_Datatype sendtype], root=0)
Reunir Vector, recopilar datos para un proceso de todos los otros procesos en un grupo proporcionar diferente cantidad de datos y los desplazamientos en los lados que reciben
parámetros:
·         Comm ( Comm MPI ) - comunicador a través del cual para dispersar
·         sendbuf ( choice ) - tampón
·         recvbuf ( choise ) - tampón en el que recibir la sendbuf
·         sendcounts ( tuple_int ) - número de elementos para recibir de cada proceso (un número entero para cada proceso)
·         displacements tuple_int ) - número de elementos de distancia desde el primer elemento en la matriz receptora en el que comenzar añadiendo la matriz segmentada
·         sendtype ( MPI_Datatype ) - MPI tipo de datos de la memoria intermedia se envía (elección de sendbuf)
·         root ( int ) - proceso de partida para dispersar

Example:
# for correct performance, run unbuffered with 3 processes:
# mpiexec -n 3 python26 scratch.py -u
import numpy
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
 
if rank == 0:
        x = numpy.linspace(0,100,11)
else:
        x = None
 
if rank == 2:
        xlocal = numpy.zeros(9)
else:
        xlocal = numpy.zeros(1)
 
if rank ==0:
        print "Scatter"
comm.Scatterv([x,(1,1,9),(0,1,2),MPI.DOUBLE],xlocal)
print ("process " + str(rank) + " has " +str(xlocal))
 
comm.Barrier()
if rank == 0:
        print "Gather"
        xGathered = numpy.zeros(11)
else:
        xGathered = None
comm.Gatherv(xlocal,[xGathered,(1,1,9),(0,1,2),MPI.DOUBLE])
print ("process " + str(rank) + " has " +str(xGathered))

Bibliografia de consulta