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)
·
source( nú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:
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:
# 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))
No hay comentarios:
Publicar un comentario