Вы находитесь на странице: 1из 8

Tutorial MPI en debian linux

La instalación de un cluster para procesamiento paralelo supone la utilización


de recursos de cpu y memoria distribuido en hardware conectado en red. Para que
sean visibles los beneficios de usar esta arquitectura es necesario utilizar un cluster
con varios nodos, al menos 3. Si no es posible usar al menos tres PCs físicos se
pueden crear máquinas virtuales sobre un PC con procesador de varios núcleos.

Pueden utilizar virtualbox o QEmu para crear las máquinas virtuales,


asignando una cantidad de memoria y un núcleo exclusivo a cada máquina virtual si
no cuenta con al menos 3 PCs.

Para este tipo de cluster es recomendable utilizar hardware homogéneo, sin


interfaz gráfica. Es necesario mantener la misma versión de mpi en todos los nodos.

Software requerido

● openmpi
● openssh
● nfs
● herramientas de desarrollo.
● un editor de texto sin formato

Debian/Ubuntu mantienen 2 versiones de MPI en su repositorio:

1. openmpi-bin
2. mpich

Configuración de la red

Antes de instalar el software MPI, empezaremos por configurar varios aspectos


de la red.

Configuración de las direcciones IP

Configure las direcciones ip en cada nodo, configure direcciones fijas o reserve


las direcciones por medio de un servidor dhcp.

El archivo de configuración de las interfaces es ​/etc/network/interfaces


El archivo se ve como sigue para configuración dinámica:

# The loopback network interface


auto lo
iface lo inet loopback
# Configuración dinámica de eth0
allow-hotplug eth0
iface eth0 inet manual

El archivo se ve como sigue para configuración fija:

# dirección fija de eth1


auto eth1
iface eth1 inet static
address 192.168.0.100
netmask 255.255.255.0
gateway 192.168.0.1

Para más información consulte el manual con el comando:

man interfaces

El servicio dhcp puede ser implementado en el nodo master. No es requerido si


se configuran los nodos con direcciones fijas.

Configuración /etc/hosts

El archivo ​/etc/hosts es una tabla que mantiene una relación de direcciones ip


a nombre, la primera columna contiene las direcciones ip, la segunda el nombre
(hostname); otras columnas corresponde a los aliases y son opcionales. El
separador de campos es cualquier carácter o secuencia que represente espacios en
blanco. La utilidad de este archivo es permitirnos utilizar nombres en lugar de
direcciones ip al momento de direccionar la comunicación entre nodos. Más
información en la línea de comando con la orden:

man hosts

En el nodo master, liste todos los nodos esclavos con sus direcciones y
nombres. En los nodos esclavos introduzca al menos el nodo master.

Para mejor consistencia en los nombres cree un archivo hosts y copielo a


todos los nodos.
A continuación se muestra como se ve el archivo ​/etc/hosts

# ip address hostname aliases


# ------------------------------------
127.0.0.1 localhost this
#
192.168.1.100 maestro master
192.168.1.100 esclavo_1 cliente_1 slave1
192.168.1.101 esclavo_2
192.168.1.108 esclavo_3
192.168.1.105 esclavo_4

Crear un usuario para el cluster

Aunque puede operar su clúster con su cuenta de usuario existente, lo


recomendable es crear una nueva para mantener nuestras configuraciones simples.

Cree un nuevo usuario ​mpiuser en todas las máquinas para mantener las
cosas simples.

Desde el usuario root ejecute la siguiente línea de comando para crear el


usuario:

adduser mpiuser

Introduzca la contraseña cuando sea solicitada y responda las demás


solicitudes.

Instalación y configuración SSH

Los nodos van a estar hablando en la red a través de SSH y compartir archivos
a través de NFS.

Se requiere la configuración del ​servidor ssh en los nodos esclavos y el ​cliente


ssh en el nodo master. Es posible instalar el servidor y el cliente de manera
independiente o instalar ambos y configurar cada cual según requerimiento.

Para instalar el servidor:

apt-get install openssh-server

Para instalar el cliente:

apt-get install openssh-client

Para instalar ambos:

apt-get install ssh

En el nodo master ingrese con el usuario mpiuser creado anteriormente.


su mpiuser

Ingrese la contraseña del usuario mpiuser cuando sea solicitada.

En la sesión de mpiuser genere una llave con la siguiente línea de comando:

ssh-keygen -t dsa

Esto generará un par de claves: pública y privada en los archivos


/home/mpiuser/.ssh/id_dsa.pub​ y ​/home/mpiuser/.ssh/id_dsa​ respectivamente.

Con la intención es evitar la solicitud de password cada vez que se quiera


comunicar con los otros nodos a través de ssh se copia la llave pública en los
esclavos del cluster (ssh server).

utilice el método que prefiera de los siguientes:

ssh-copy-id esclavo_1

scp /home/mpiuser/.ssh/id_dsa.pub mpiuser@esclavo_1:.ssh/authorized_keys

Para verificar la conexión, utilice la siguiente línea de comando:

ssh esclavo_1

Repetir para cada esclavo.

En caso de falla verificar:

/home/mpiuser/.ssh tenga permisos 700 (rwx------)

/home/mpiuser/.ssh/authorized_keys tenga permisos 600 (rw-------)

Utilice el comando chmod para modificar de ser necesario.

Instalación y configuración de NFS

En el nodo maestro se comparte un directorio con NFS para que los clientes
accedan a los datos.

Para instalar NFS ejecutamos desde el root:

apt-get install nfs-kernel-server

Ahora en la sesión de mpiuser, creamos un directorio para compartir:

mkdir data

Para compartirlo, editamos el archivo ​/etc/exports y agregamos la siguiente


línea:
/home/mpiuser/data *(rw,sync,no_root_squash,no_subtree_check)

a continuación ejecutar:

exportfs -a

Para mayor información verifique el manual en línea de comando.

man exports

En los nodos esclavos (cliente nfs) se instala el software necesario:

apt-get install nfs-common

Se crea el directorio de datos con el mismo nombre que el creado en el master

mkdir data

Se monta el directorio compartido en el directorio de datos para tener la misma


ruta a los archivos de aplicación.

sudo mount -t nfs maestro:/home/mpiuser/data ~/data

maestro debe estar listado en el archivo /etc/hosts del esclavo y ~ corresponde


al ​homedir ​del usuario actual (ver variable de entorno $HOME)

Para hacerlo permanente se monta el directorio modificando el archivo


/etc/fstab, agregando la línea:

maestro:/home/mpiuser/data /home/mpiuser/data nfs

fstab es una tabla donde se configura los sistemas de archivos a montar en el


inicio del sistema. mayor información en la línea de comandos:

man fstab

Instalación Open MPI

Seleccione una implementación e instale en cada nodo siguiendo el


procedimiento a continuación:

Instalación openmpi

Como usuario root instalar con el siguiente comando:

apt-get install openmpi-bin libopenmpi-dev

Acepte las sugerencias de apt.


Instalación mpich

Como usuario root instalar con el siguiente comando:

apt-get install mpich

Acepte las sugerencias de apt.

En adelante asumiremos openmpi como nuestro cluster.

Configuración de openmpi

Para que Open MPI sepa qué máquinas deben ejecutar sus programas, puede
crear un archivo para almacenarlo en el nodo maestro. Utilizaremos el archivo
/home/mpiuser/.mpi_hosts​ y podría contener lo siguiente:

# The hostfile for Open MPI


# filename:~/.mpi_hosts
# The master node, 'slots=2' is used because it is a dual-processor machine.

localhost slots=2

# The following slave nodes are single processor machines:

esclavo_1
esclavo_2
esclavo_3

En la configuración el número de slots corresponde al número de núcleos o


procesadores, los nombres ​esclavo_#​ corresponde a los nombres en /etc/hosts

Compilación de programas con openmpi

OpenMPI se puede utilizar con una variedad de lenguajes, dos de los más
populares son FORTRAN y 'C'. Si sus programas están escritos en 'C', entonces
puede usar mpicc en lugar de su compilador 'C' normal o puede pasar los
argumentos adicionales directamente a su compilador 'C'. Con mpicc los
argumentos que pasa son pasados a su compilador 'C' normal.

Si desea utilizar mpicc para compilar un archivo fuente 'C' llamado testmpi.c:

mpicc -o testmpi testmpi.c

Si desea ver qué se pasará a su compilador 'C' al compilar y vincular:

mpicc -showme -o testmpi testmpi.c


Ejecutar los programas MPI

Puede iniciar un programa en una sola máquina y ejecutarlo en varios


procesadores/núcleos. Esto es útil si tiene una máquina potente o está
depurando/probando un programa. Como alternativa, puede ejecutar el programa a
través del clúster y solicitar tantos procesos como desee ejecutar sobre él.

Para ejecutar ​miprograma​ en dos procesos en la máquina local:

$ mpirun -np 2 ./miprograma

Para ejecutar miprograma sobre cinco procesos en el clúster utilizando el


.mpi_hostfile creado anteriormente (Tenga en cuenta que miprograma debe estar en
la misma ruta en cada máquina):

mpirun -np 2 --hostfile .mpi_hosts ./miprograma

Código ejemplo
#include
#include
#include

int main(int argc, char *argv[])


{
const int MASTER = 0;
const int TAG_GENERAL = 1;

int numTasks;
int rank;
int source;
int dest;
int rc;
int count;
int dataWaitingFlag;

char inMsg;
char outMsg;

MPI_Status Stat;

// Initialize the MPI stack and pass 'argc' and 'argv' to each slave node
MPI_Init(&argc,&argv);

// Gets number of tasks/processes that this program is running on


MPI_Comm_size(MPI_COMM_WORLD, &numTasks);

// Gets the rank (process/task number) that this program is running on


MPI_Comm_rank(MPI_COMM_WORLD, &rank);

// If the master node


if (rank == MASTER) {

// Send out messages to all the sub-processes


for (dest = 1; dest < numTasks; dest++) {
outMsg = rand() % 256; // Generate random message to send to slave
nodes

// Send a message to the destination


rc = MPI_Send(&outMsg, 1, MPI_CHAR, dest, TAG_GENERAL, MPI_COMM_WORLD);
printf("Task %d: Sent message %d to task %d with tag %d\n",
rank, outMsg, dest, TAG_GENERAL);
}

// Else a slave node


else {
// Wait until a message is there to be received
do {
MPI_Iprobe(MASTER, 1, MPI_COMM_WORLD, &dataWaitingFlag,
MPI_STATUS_IGNORE);
printf("Waiting\n");
} while (!dataWaitingFlag);

// Get the message and put it in 'inMsg'


rc = MPI_Recv(&inMsg, 1, MPI_CHAR, MASTER, TAG_GENERAL, MPI_COMM_WORLD,
&Stat);

// Get how big the message is and put it in 'count'


rc = MPI_Get_count(&Stat, MPI_CHAR, &count);
printf("Task %d: Received %d char(s) (%d) from task %d with tag %d \n",
rank, count, inMsg, Stat.MPI_SOURCE, Stat.MPI_TAG);
}

MPI_Finalize();
}

Programación de aplicaciones MPI

... en construcción

Referencias

http://mpitutorial.com

https://www.open-mpi.org

Programación distribuida y paralela