manual de configuracion de un cluster en debian
Post on 05-Dec-2014
318 Views
Preview:
DESCRIPTION
TRANSCRIPT
18 de diciembre de 2012
MANUAL DE CONFIGURACION
CLUSTER/MPI CON DEBIAN
Introducción
El contenido de este manual describe las acciones a realizar para la
configuración (creación) de un clúster de máquinas linux.
Este cluster permite la ejecución de programas paralelos; esto
significa que su codificación contiene instrucciones especiales para
ser ejecutados de forma paralela. Existen diferentes protocolos para
la creación de este tipo de entornos (pe. PVM o MPI). El cluster que
se describe utiliza el protocolo MPI a través de la implementación
LAM-MPI.
El cluster descrito consiste en un conjunto de máquinas con sistema
operativo linux a las que se les define un usuario (lam). El directorio
de trabajo de este usuario es un directorio remoto (montado usando
samba) que contiene los binarios necesarios para la activación del
nodo. No se supone que cada uno de los nodos sea una máquina
dedicada; de hecho cada máquina del cluster continuará realizando
las tareas asignadas (pe. servidor web, servidor de base de datos,
firewall, servidor de ficheros, etc.) además de pertenecer al cluster.
No es necesaria la ejecución de un daemon de sistema. Cuando el
cluster se activa, el nodo maestro se pone en contacto con cada uno
de los nodos clientes a través del usuario lam y ejecuta el daemon
lamd. Mientras está activo se pueden ejecutar los programas
paralelos dentro del entorno LAM. Cuando el clúster ya no es
necesario, se cierra el daemon lamd y no queda ningún proceso ni
usuario del cluster en ejecución.
Se procura que la seguridad de cada nodo no quede comprometida
por el hecho de pertenecer al cluster. Además, se busca que el propio
cluster sea seguro (no pueda ser usado o modificado por terceros).
Esto se consigue de la forma siguiente:
El acceso al usuario lam se realiza de forma segura a través de una
conexión SSH con clave RSA2 (clave asimétrica). Se garantiza que
nadie accederá a la cuenta del usuario lam a no ser que disponga de
la clave privada.
El sistema de ficheros compartido por el servidor utiliza usuario y
password para su acceso. Este usuario y password puede ser
vulnerado por terceros (aparece de forma plana en los ficheros de
configuración de cada nodo). Queda bajo la responsabilidad del
administrador del cluster garantizar que la gestión o configuración
del servidor de ficheros se realiza de forma segura.
La plantilla HTML usada para la redacción de este documento sigue
el formato de las LAM-FAQ. Gran parte de la información que aquí
se recopila se encuentra explicada en detalle en la documentación de
LAM o en las FAQ-LAM.
Comandos y Conceptos Básicos
1. ¿Qué es un Cluster?
Un Cluster de computadoras es un conjunto de computadoras
conectadas entre sí, que trabajan una tarea relacionada, de tal
forma que parecen una gran computadora. Cada procesador
de cada computadora se puede considerar un nodo del
Cluster.
Cuando se habla de programación en paralelo, se entiende
que los distintos procesos que se quieren ejecutar en paralelo
se distribuirán a través de los distintos nodos de un Cluster.
Entonces podemos tener computadoras con multiprocesador,
que tendrían varios nodos del Cluster.
Utilidad
La mayor utilidad de la paralización es la ganancia en
velocidad de la ejecución.
Hay que tener en cuenta que no todo problema/algoritmo
puede ser paralelizable. Y si lo es, no necesariamente hay una
ganancia en velocidad, puesto que debemos considerar el
tiempo de comunicación entre los procesos.
2. LAM
Es la definición que adquiere el usuario, donde el directorio
de este es un directorio remoto que contiene los binarios
necesarios para la activación del nodo.
3. MPI
Es un estándar de paso de mensajes.
Las siglas proceden del inglés “Message Passing Interface” o
Interfaz de Paso de Mensajes.
Se utiliza en la programación paralela en sistemas
distribuidos de computadores.
Puede utilizarse tanto en máquinas con o sin memoria
compartida, siendo estas últimas su objetivo prioritario.
4. LAM/MPI
Es un paquete software que se encarga de distribuir nuestros
programas en la máquina paralela e implementa la interfaz de
paso de mensajes.
Una vez instalado LAM/MPI puede crearse una máquina
paralela.
5. ¿Qué ventajas tiene el MPI?
El MPI permite distribuir sus nodos tanto en distintas
computadoras como en distintos procesadores en una misma
computadora. Permite también que se asignen varios
procesos a un mismo procesador, así pues si se tiene un
Cluster heterogéneo de computadoras, se puede, por ejemplo,
asignar más procesos (es decir, más tareas) a los procesadores
más rápidos.
Instrucciones básicas del MPI
Las instrucciones básicas del MPI cubren 3 aspectos:
Inicialización y terminación del MPI.
Todo programa MPI debe comenzar con la instrucción:
MPI Init(&argc, &argv);
Y debe terminar con:
MPI Finalize();
Identificación de quien soy y cuantos somos.
Con las siguientes instrucciones se puede obtener la
información básica de los nodos, es decir, cuántos son, y cual
soy.
int myrank; // Número de proceso.
int nprocs; // Número total de procesos.
MPI Comm rank(MPI COMM WORLD, &myrank);
MPI Comm size(MPI COMM WORLD, &nprocs);
Envío y recepción de mensajes entre los procesos.
Las instrucciones que soportan el esqueleto de todo pro-
grama MPI son:
Enviar mensaje:
MPI Send(buffer, contador, tipodato, destino,
tag, MPI COMM WORLD);
Recibir mensaje:
MPI Recv(buffer, maxcontador, tipodato,
origen, tag, MPI COMM WORLD,
&status);
6. MPICC
mpicc/mpiCC/mpif77, Son comandos que se utilizan para
compilar los binarios a ejecutar en el cluster. Se trata de
wrappers a los compiladores de sistema. Utilícese
exactamente igual (los mismos argumentos, etc.) que los
comandos originales, normalmente gcc.
7. MPICXX
mpicxx, Comando que se utiliza para compilar y enlazar
programas en C++ que hagan uso de MPI.
8. MPICC Y MPICXX
mpicc y mpicxx, Pueden utilizarse con las mismas opciones
que el compilador de C/C++ usual.
9. MPIRUN
mpirun, Ejecuta el programa de ejemplo hello en el clúster.
La opción C, indica que debe ejecutarse en todas las CPU's;
la opción N indica que solamente debe ejecutarse una
instancia en cada nodo.
10. LAMEXEC
lamexec, Comando similar a mpirun para lanzar programas
estándar unix (programas no MPI, pe. date). La opción C,
indica que debe ejecutarse en todas las CPU's; la opción N
indica que solamente debe ejecutarse una instancia en cada
nodo.
11. LAMCLEAN
lamclean, Este comando solamente debe utilizarse cuando un
programa del cluster acaba de forma incorrecta o inesperada
y mantiene recursos del cluster alocados. Mata todos los
programas que se están ejecutando en aquel momento en el
cluster.
12. MPITASK/LAMINFO/LAMNODES|TPING
Comandos informativos. mpitask lista el conjunto de tareas
que está ejecutando el cluster en este momento. Es el
equivalente al comando unix ps. laminfo proporciona
información del entorno LAM. Tiene multitud de opciones,
para más información consulte las páginas
de man. lamnodes lista el conjunto de nodos que forman el
cluster. Proporciona una información muy parecida al
contenido del fichero lam-bhost.def. tping comprueba que
todos los nodos están activados.
13. LAMBOOT
lamboot, Comando usado para arrancar el cluster. La
configuración del cluster debe la obtiene del fichero
$HOME/etc/lam-bhost.def. Utiliza las variables de entorno
LAMHOME para determinar donde se encuentra la
instalación de LAM y LAMRSH para indicar que la conexión
a los nodos se realize usando SSH.
14. RECON
recon, Comando para comprobar si el cluster está preparado
para ser arrancado. Utiliza las variables de entorno
LAMHOME para determinar donde se encuentra la
instalación de LAM y LAMRSH para indicar que la conexión
a los nodos se realize usando SSH.
15. LAMHALT
Comando utilizado para deshabilitar el cluster. En caso de
retorno de error o falta de respuesta utilice wipe -v
$HOME/etc/lam-bhost.def.
16. ITHOUT-FC
El componente ithout-fc se caracteriza por el uso como una
fuente CW por cable y redes DWDM. El cw se acoplada a
CC con un TEC incorporado, termistor, y un fotodiodo
monitor. El dispositivo está montado en un pasador, paquete
pinout mariposa compatible con el aislador óptico montado
en el TEC.
El ithout-fc incorpora un sistema de alta eficiencia de
acoplamiento para entregar cc, mW, ymW de potencia óptica
CW.
17. SSH-KEYGEN
SSH, se utiliza a menudo para iniciar sesión desde un sistema
a otro sin necesidad de contraseñas.
Ssh-keygen , se utiliza para generar, gestionar y convertir las
claves de autenticación de ssh. Con la ayuda de la
herramienta ssh-keygen, un usuario puede crear frase de
teclas para ambos SSH protocolo de la versión 1 y versión 2.
SSH-keygen genera RSA claves para el protocolo SSH
versión 1 y RSA o DSA claves para el uso de SSH versión 2
del protocolo.
¿Cómo funciona?
La herramienta ssh-keygen almacena la clave privada en $
HOME / .ssh / id_rsa y la clave pública en $ HOME / .ssh /
id_rsa.pub en el directorio home del usuario. Entonces, el
usuario debe copiar el id_rsa.pub a $ HOME / .ssh /
authorized_keys en su directorio de inicio en el equipo
remoto. También pide una contraseña. La frase de contraseña
puede estar vacío para indicar ninguna contraseña (claves de
host debe tener una contraseña vacía), o puede ser una cadena
de longitud arbitraria. En lugar de RSA, DSA también se
puede utilizar. Los pasos para crear claves de autorización
mediante el uso de la herramienta ssh-keygen son los
siguientes:
Archivos que utiliza ssh-keygen
La utilidad ssh-keygen tiene varios archivos para almacenar
las claves públicas y privadas. Los archivos utilizados por
SSH-Keygen utilidad son los siguientes:
$ HOME / .ssh / identity: El directorio $ HOME / .ssh /
archivo de identidad contiene la clave privada RSA cuando se
utiliza el protocolo SSH versión 1.
$ HOME / .ssh / identity.pub: El directorio $ HOME / .ssh /
identity.pub contiene la clave pública RSA para la
autenticación cuando se utiliza el protocolo SSH versión 1.
Un usuario debe copiar su contenido en el directorio $
HOME / .ssh / authorized_keys del sistema remoto donde un
usuario desea conectarse mediante la autenticación RSA.
$ HOME / .ssh / id_dsa: El directorio $ HOME / .ssh /
id_dsa contiene la versión 2 del protocolo de autenticación de
identidad DSA del usuario.
$ HOME / .ssh / id_dsa.pub: El directorio $ HOME / .ssh /
id_dsa.pub contiene la clave pública DSA para la
autenticación cuando se utiliza el protocolo SSH versión 2.
Un usuario debe copiar su contenido en el directorio $
HOME / .ssh / authorized_keys del sistema remoto donde un
usuario desea iniciar sesión con autenticación DSA.
$ HOME / .ssh / id_rsa: El directorio $ HOME / .ssh /
id_rsa contiene la versión 2 del protocolo de autenticación de
identidad de RSA del usuario. Este archivo no debe ser leído
por nadie más que el usuario.
$ HOME / .ssh / id_rsa.pub: El directorio $ HOME / .ssh /
id_rsa.pub archivo contiene la versión 2 del protocolo clave
pública RSA para la autenticación. El contenido de este
archivo debe ser añadido a $ HOME / .ssh / authorized_keys
en todos los equipos en los que un usuario desea iniciar
sesión con autenticación de clave pública.
CONFIGURACION DE LA RED
Todas las máquinas del cluster deben poder resolver por nombre el
resto de nodos. El esquema propuesto consiste en la existencia de un
servidor de nombres (DNS) donde todas las máquinas están
referenciadas y todas las máquinas tienen este servidor de nombres
asignado por defecto. La configuración de los servidores de nombres
no entra dentro del ámbito de este documento.
Para asignar el dominio y el servidor de nombres al nodo edite el
fichero /etc/resolv.conf y compruebe que contiene las siguientes
líneas:
domain domainname
search domainname
nameserver ip_nameserver
La implementación LAM-MPI actual gestiona la asignación de
puertos de forma dinámica (el primero que encuentra libre). En un
futuro está previsto que se pueda fijar los puertos usados por LAM-
MPI. Debe tenerse esto en cuenta si la máquina se encuentra detrás
de un firewall. En este caso las reglas a habilitar en el firewall son:
debe permitirse todo tipo de tráfico entre todas las máquinas
pertenecientes al cluster.
CREACION DEL USUARIO LAM EN CADA NODO
El usuario utilizado por el cluster es el usuario lam. Las
características de este usuario son las siguientes:
Nombre: lam
Home: /home/lam
Grupo: users (puede ser otro grupo)
Shell: bash
Password: A decidir por el administrador de la máquina. Local al nodo.
Descripción: usuario cluster LAM-MPI
En el fichero /etc/password debe constar una línea parecida a la
siguiente:
lam:x:500:100:usuario
cluster LAM MPI:/home/lam:/bin/bash
El directorio de trabajo ($HOME) de los nodos es un directorio
compartido. Antes de crear el usuario, comprobar que existe el grupo
donde será asignado (por defecto users). Para crear el usuario con las
características indicadas, ejecutar como root el siguiente comando:
useradd -c "usuario cluster LAM-MPI" -d /home/lam -g
users -n -s /bin/bash lam
Si se desea añadir una contraseña al usuario creado, ejecutar como
root el siguiente comando e indicar el password deseado (no es
necesario que sea conocido por el resto del cluster):
passwd lam
SISTEMA DE FICHEROS COMPARTIDOS. CLIENTES
El sistema de ficheros compartidos es de tipo samba con
autentificación. Es necesario tener instalado el cliente samba en cada
nodo del cluster. Para montar y desmontar manualmente un sistema
de ficheros de este tipo teclear:
mount -t smbfs –o username=foo,password=bar//
host_name/dir /mnt
...
umount /mnt
Nos interesa que el directorio de trabajo del usuario lam sea único en
todo el cluster para poder garantizar lo siguiente:
Ejecutables LAM-MPI únicos. La versión de los ejecutables
debe ser la misma para que el cluster funcione correctamente.
Simplificación en la distribución de programas a ejecutar.
Dentro de la carpeta compartida existe un directorio para
albergar los programas que ejecutará el cluster. Nos evitamos
el distribuir el programa antes de ejecutarlo.
Distribución automática de las claves públicas para SSH.
Cada nodo permite que el nodo master se conecte a él al
disponer de la clave pública. La posesión de esta clave no
significa que cualquier persona pueda acceder al usuario lam.
Solamente lo podrá hacer aquella que disponga de la clave
privada (el nodo master). La clave privada no se encontrará
en el sistema de ficheros compartido.
Para montar de forma automática un sistema de ficheros samba
usando autentificación debe añadirse la siguiente línea en el
fichero /etc/fstab:
//host_name/lam /home/lam smbfs
username=lam,passwd=lam,user,exec,fmask=644,dmask=755 0
0
Es responsabilidad del administrador del cluster garantizar la
accesibilidad e integridad de los ficheros compartidos (evitar que una
máquina no perteneciente al cluster monte el sistema de ficheros y
modifique su contenido).
SISTEMA DE FICHEROS COMPARTIDOS. SERVIDOR
Es necesario tener instalado el servidor samba. El objetivo es
explicar la configuración del sistema de ficheros compartido para el
cluster, no la instalación del servidor samba. Puedes encontrar más
información en www.samba.org. Los objetivos a cumplir son los
siguientes:
Disponer de un sistema de ficheros compartido instalado por
defecto en la mayoría de nodos.
Compartir el directorio /home/lam con los nodos del cluster.
Garantizar el acceso mediante usuario y contraseña.
Impedir que el contenido del directorio compartido sea
modificado por terceros.
Comprobar que el usuario lam existe en /etc/passwd. Añadir el
usuario lam en la lista de usuarios samba, usando la siguiente
instrucción (cuando solicite el password, introducir lam):
smbpasswd -a lam
Localizar el fichero smb.conf. Normalmente se encuentra
en /etc/samba/smb.conf. En caso de no encontrarlo en este path
usar la instrucción locate smb.conf para determinar la ruta del
fichero o buscarlo en /etc/smb.conf. Realizar las siguientes
modificaciones al fichero smb.conf:
[global]
workgroup = WORKGROUP
hosts allow = 192.9.199. 127.
encrypt passwords = yes
smb passwd file = /etc/samba/smbpasswd
[lam]
comment = lam
path = /home/lam
valid users = lam
public = no
writable = yes
printable = no
Una vez realizadas las modificaciones indicadas, ejecutar el
comando testparm -s para comprobar que la configuración final
del servidor samba es correcta y reiniciar el servicio.
CONFIGURACION DE CLUSTER/MPI CON DEBIAN
Podemos configurar un cluster de alto rendimiento en Debian
utilizando la interfaz de paso de mensajes LAM/MPI.
Los prerrequisitos de este manual es disponer de una instalación
básica de debian Etch, en nuestro caso hemos usado 2 máquinas
aisladas en una red propia que se usará tan solo para el cluster de alto
rendimiento, las hemos llamado: (192.168.1.23) nodo0,
(192.168.1.24). En cada una de las máquinas hemos creado un
usuario al que hemos llamado “cluster” con contraseña “123456”.
Instalación del build-essential
Una vez tengamos la instalación básica y comprobamos que tengan
connectividad entre ellas y lleguen a un gateway con salida internet
(para la instalación de paquetes con apt-get), procederemos a instalar
el paquete build-essential en cada una de las máquinas para compilar
LAM/MPI que nos descargaremos de la web oficial.
Así que en cada uno de los nodos ejecutaremos
>> apt-get install build-essential
Instalación de LAM/MPI
En nuestro caso no vamos a usar C++ y no necesitamos Fortran para
programar en el cluster, así que no necesitaremos el compilador
Fortran, eso sí le especificaremos la opción –without-fc en el
configure, compilamos también el paquete en cada una de las
máquinas:
>> tar -xzvf lam-7.1.4.tar.gz
>> cd lam-7.1.4
>> ./configure --without-fc && make && make install
Configuración de la Variable PATH
Una vez tenemos LAM/MPI instalado en todas las máquinas,
modificaremos el archivo .bashrc del usuario cluster, que
encontraremos en la home de este /home/cluster/.bashrc, al final del
archivo añadiremos las siguientes líneas:
PATH=/usr/local/lam/bin:$PATH
export PATH
PATH=/usr/local/lam/bin:$PATH
export PATH
Registramos los nodos
Modificaremos en el nodo0 el archivo /etc/hosts donde le
indicaremos donde están todos los nodos, y luego lo podemos copiar
a los otros nodos:
>> (gedit/nano) /etc/hosts
127.0.0.1 localhost
192.168.1.23 nodo0
192.168.1.24 nodo1
Instalación de ssh en debían
Para la instalación podemos hacerlo colocando el cd de instalación o
con conexión a internet
>> apt-get install ssh
Generar contraseña para el Maestro (nodo0)
Una vez podamos localizar todos los nodos, debemos conseguir que
el nodo0 pueda acceder usando ssh a todos los nodos sin necesidad
de password, para ello nos vamos al nodo principal y ejecutaremos
ssh-keygen:
>> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/cluster/.ssh/id_rsa):
[ENTER]
Enter passphrase (empty for no passphrase): [ENTER]
Enter same passphrase again: [ENTER]
Your identification has been saved in /home/cluster/.ssh/id_rsa.
Your public key has been saved in /home/cluster/.ssh/id_rsa.pub.
The key fingerprint is:
17:4f:9b:88:55:e2:dc:25:c3:74:01:c7:49:52:08:4f cluster@debian-
frontend
Copiamos la clave a todos los nodos
>> scp /home/cluster/.ssh/id_rsa.pub
cluster@192.168.1.24:/home/cluster/
Accedemos a cada uno de los nodos y guardamos la clave:
>> cd /home/cluster/
>> mkdir .ssh
>> cat id_rsa.pub >> /home/cluster/.ssh/authorized_keys
>> rm id_rsa.pub
Nos volvemos al nodo0, y comprobamos que podemos acceder a los
hosts ejecutando un comando que debería mostrar el shell en uso sin
necesidad de introducir ningún password:
> rsh nodo1 -n 'echo $SHELL'
>> /bin/bash
Creación del archivo boot_schema
Crearemos un archivo, al que yo he llamado boot_schema donde
indicaremos todos los nodos del cluster, y el número de CPUs, si
tenemos SMP le indicaremos dos CPU añadiendo cpu=2 despues del
nodo (por ejemplo debian-node4 cpu=2):
#Mis nodos del cluster
nodo0
nodo1
Arranque de Cluster
Momento de arrancar el cluster, para ello le pasaremos el archivo
boot_schema que creamos en el paso anterior, y si todo ha ido bien
veremos algo parecido a esto:
lamboot -v -ssi boot rsh boot_schema
LAM 7.1.4/MPI 2 C++/ROMIO - Indiana University
n-1<6023> ssi:boot:base:linear: booting n0 (nod0)
n-1<6023> ssi:boot:base:linear: booting n1 (nod1)
n-1<6023> ssi:boot:base:linear: finished
Probando en Cluster
EJERCICIO 1:
Tenemos a nuestra disposición una suite de tests para probar nuestra
instalación, pero que hay más bonito que empezar con un “Hola
Mundo” en C para abrir nuestro apetito, para ello crearemos un
archivo helloworld.c con el siguiente contenido, en un directorio al
que he llamado test dentro de nuestra home:
#include <stdio.h>
#include <mpi.h>
int main(int argc, char *argv[]) {
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
printf("Hello, world! I am %d of %d\n", rank,
size);
MPI_Finalize();
return 0;
}
Lo compilamos y pasamos el ejecutable a los otros nodos:
cd /home/cluster/test
mpicc helloworld.c -o helloworld
rsh debian-node1 -n 'mkdir /home/cluster/test'
scp hello 10.11.12.2:/home/cluster/test/
rsh debian-node2 -n 'mkdir /home/cluster/test'
scp hello 10.11.12.3:/home/cluster/test/
[...]
Hora de probar, deberíamos obtener un resultado como este (aunque
no necesariamente en el mismo orden):
mpirun C hello
Hello, world! I am 0 of 5
Hello, world! I am 2 of 5
Hello, world! I am 1 of 5
Hello, world! I am 4 of 5
Hello, world! I am 3 of 5
Tenemos también como hemos dicho una suite de tests que nos
permitiran comprobar el correcto funcionamiento de la instalación
MPI:
cd /home/cluster
tar -xzvf lamtests-7.1.4.tar.gz
cd lamtests-7.1.4/
./configure
make
make -k check 2>&1 | tee check.out
EJERCICIO 2:
hola.c programa MPI: activacion de procesos
#include <mpi.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int lnom;
char nombrepr[MPI_MAX_PROCESSOR_NAME];cat circu
int pid, npr;
int A = 2; // identificador y numero de proc.
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &npr);
MPI_Comm_rank(MPI_COMM_WORLD, &pid);
MPI_Get_processor_name(nombrepr, &lnom);
A = A + 1;
printf(" >> Proceso %2d de %2d activado en %s, A =
%d\n", pid, npr, nombrepr, A);
MPI_Finalize();
return 0;
}
EJERCICIO 3: circu.c - paralelizacion MPI de un bucle
#include <mpi.h>
#include <stdio.h>
#define DECBIN(n,i) ((n&(1<<i))?1:0)
void test (int pid, int z)
{
int v[16], i;
for (i=0; i<16; i++) v[i] = DECBIN(z,i);
if ((v[0] || v[1]) && (!v[1] || !v[3]) && (v[2] || v[3])
&& (!v[3] || !v[4]) && (v[4] || !v[5])
&& (v[5] || !v[6]) && (v[5] || v[6])
&& (v[6] || !v[15]) && (v[7] || !v[8])
&& (!v[7] || !v[13]) && (v[8] || v[9])
&& (v[8] || !v[9]) && (!v[9] || !v[10])
&& (v[9] || v[11]) && (v[10] || v[11])
&& (v[12] || v[13]) && (v[13] || !v[14])
&& (v[14] || v[15]))
{
printf(" %d) %d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d (%d)\n",
pid, v[15],v[14],v[13],
v[12],v[11],v[10],v[9],v[8],v[7],v[6],v[5],v[4],v[3],v[2],v[1
],v[0], z);
fflush(stdout);
}
}
int main (int argc, char *argv[])
{
int i, pid, npr;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &npr);
MPI_Comm_rank(MPI_COMM_WORLD, &pid);
for (i=pid; i<65536; i += npr) test(pid, i);
MPI_Finalize();
return 0;
}
EJERCICIO 4: envio.c - se envia un vector desde el procesador 0 al 1
#include <mpi.h>
#include <stdio.h>
#define N 10
int main (int argc, char **argv)
{
int pid, npr, origen, destino, ndat, tag;
int VA[N], i;
MPI_Status info;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &pid);
MPI_Comm_size(MPI_COMM_WORLD, &npr);
for (i=0; i<N; i++) VA[i] = 0;
if (pid == 0)
{
for (i=0; i<N; i++) VA[i] = i;
destino = 1; tag = 0;
MPI_Send(&VA[0], N, MPI_INT, destino, tag,
MPI_COMM_WORLD);
}
else if (pid == 1)
{
printf("\nvalor de VA en P1 antes de recibir datos\n\n");
for (i=0; i<N; i++) printf("%4d", VA[i]);
printf("\n\n");
origen = 0; tag = 0;
MPI_Recv(&VA[0], N, MPI_INT, origen, tag, MPI_COMM_WORLD,
&info);
MPI_Get_count (&info, MPI_INT, &ndat);
printf("Pr 1 recibe VA de Pr %d: tag %d, ndat %d \n\n",
info.MPI_SOURCE, info.MPI_TAG, ndat);
for (i=0; i<ndat; i++) printf("%4d", VA[i]);
printf("\n\n");
}
MPI_Finalize();
return 0;
}
EJERCICIO 5: dlock1.c - intercambio de dos variables #include <mpi.h>
#include <stdio.h>
int main (int argc, char **argv)
{
int pid, origen, destino, tag;
int A, B, C;
MPI_Status info;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &pid);
if (pid == 0)
{
A = 5;
printf("\n >> recibiendo datos de P1 \n");
origen = 1; tag = 1;
MPI_Recv(&B, 1, MPI_INT, origen, tag, MPI_COMM_WORLD,
&info);
printf("\n >> enviando datos a P1 \n");
destino = 1; tag = 0;
MPI_Send(&A, 1, MPI_INT, destino, tag, MPI_COMM_WORLD);
C = A + B;
printf("\n C es %d en proc 0 \n\n", C);
}
else if (pid == 1)
{
B = 6;
printf("\n >> recibiendo datos de P0 \n");
origen = 0; tag = 1;
MPI_Recv(&A, 1, MPI_INT, origen, tag, MPI_COMM_WORLD,
&info);
printf("\n >> enviando datos a P0 \n");
destino = 0; tag = 0;
MPI_Send(&B, 1, MPI_INT, destino, tag, MPI_COMM_WORLD);
C = A + B;
printf("\n C es %d en proc 1 \n\n", C);
}
MPI_Finalize();
return 0;
}
EJERCICIO 6: send-dead.c -prueba para ver el tamaino del buffer de la funcion send el programa
se bloquea al enviar un paquete mas grande #include <stdio.h>
#include "mpi.h"
#define N 100000
int main(int argc, char** argv)
{
int pid, kont; // Identificador
del proceso
int a[N], b[N], c[N], d[N];
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &pid);
for (kont=100; kont<=N; kont=kont+100)
{
if (pid == 0)
{
MPI_Send(&a[0], kont, MPI_INT, 1, 0, MPI_COMM_WORLD);
MPI_Recv(&b[0], kont, MPI_INT, 1, 0, MPI_COMM_WORLD,
&status);
printf("emisor %d \n", kont);
}
else
{
MPI_Send(&c[0], kont, MPI_INT, 0, 0, MPI_COMM_WORLD);
MPI_Recv(&d[0], kont, MPI_INT, 0, 0, MPI_COMM_WORLD,
&status);
printf(" receptor %d \n", kont);
}
}
MPI_Finalize();
return 0;
} /* main */
EJERCICIO 7: ssend.c - Ping-pong entre dos procesadores Comunicacion sincrona ssend
#include <stdio.h>
#include <mpi.h>
#include <math.h>
#include <unistd.h>
#define VUELTAS 4
double calculo()
{
double aux;
sleep(1);
aux = rand() % 100;
return(aux);
}
int main(int argc, char** argv)
{
double t0, t1, dat= 0.0, dat1, dat_rec;
int pid, i;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &pid);
if (pid == 0) t0 = MPI_Wtime();
for(i=0; i<VUELTAS; i++)
{
if (pid == 0)
{
MPI_Ssend(&dat, 1, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD);
dat1 = calculo();
MPI_Recv(&dat_rec, 1, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD,
&status);
dat = dat1 + dat_rec;
}
else
{
dat1 = calculo();
MPI_Recv(&dat_rec, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD,
&status);
dat = dat1 + dat_rec;
MPI_Ssend(&dat, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
}
}
if (pid == 0)
{
t1 = MPI_Wtime();
printf("\n Tiempo de ejecucion = %f s \n", t1-t0);
printf("\n Dat = %1.3f \n\n", dat);
}
MPI_Finalize();
return 0;
} /* main */
EJERCICIO 8: isend.c - Ping-pong entre dos procesadores Comunicacion inmediata isend
#include <stdio.h>
#include <mpi.h>
#include <unistd.h>
#define VUELTAS 4
double calculo()
{
double aux;
sleep(1);
aux = rand() % 100;
return(aux);
}
int main(int argc, char** argv)
{
double t0, t1, dat = 0.0, dat1, dat_rec;
int pid, i;
MPI_Status status;
MPI_Request request;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &pid);
if (pid == 0) t0 = MPI_Wtime();
for(i=0; i<VUELTAS; i++)
{
if (pid == 0)
{
MPI_Isend(&dat, 1, MPI_DOUBLE, 1, 0,
MPI_COMM_WORLD,&request);
dat1 = calculo();
MPI_Wait(&request, &status);
MPI_Recv(&dat_rec, 1, MPI_DOUBLE, 1, 0,
MPI_COMM_WORLD, &status);
dat = dat1 + dat_rec;
}
else
{
dat1 = calculo();
if (i!=0) MPI_Wait(&request, &status);
MPI_Recv(&dat_rec, 1, MPI_DOUBLE, 0, 0,
MPI_COMM_WORLD, &status);
dat = dat1 + dat_rec;
MPI_Isend(&dat, 1, MPI_DOUBLE, 0, 0,
MPI_COMM_WORLD,&request);
}
}
if (pid == 0)
{
t1 = MPI_Wtime();
printf("\n Tiempo de ejecucion = %f s \n",
t1-t0);
printf("\n Dat = %1.3f \n\n", dat);
}
MPI_Finalize();
return 0;
} /* main */
EJERCICIO 9: probe.c - ejemplo de uso de la funcion probe de MPI
#include <mpi.h>
#include <stdio.h>
int main (int argc, char **argv)
{
int pid, npr, origen, destino, ndat, tag;
int i, longitud, tam;
int *VA, *VB;
MPI_Status info;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &pid);
MPI_Comm_size(MPI_COMM_WORLD, &npr);
if (pid == 0)
{
srand(time(NULL));
longitud = rand() % 100;
VA = (int *) malloc (longitud*sizeof(int));
for (i=0; i<longitud; i++) VA[i] = i;
printf("\n valor de VA en P0 antes de enviar
los datos\n\n");
for (i=0; i<longitud; i++) printf("%4d",
VA[i]);
printf("\n\n");
destino = 1; tag = 0;
MPI_Send(VA, longitud, MPI_INT, destino, tag,
MPI_COMM_WORLD);
}
else if (pid == 1)
{
origen = 0; tag = 0;
MPI_Probe(origen, tag, MPI_COMM_WORLD, &info);
MPI_Get_count(&info, MPI_INT, &tam);
if(tam != MPI_UNDEFINED)
{
VB = (int *) malloc(tam*sizeof(int));
MPI_Recv(VB, tam, MPI_INT, origen, tag,
MPI_COMM_WORLD, &info);
}
printf("\n valor de VB en P1 tras recibir los
datos\n\n");
for (i=0; i<tam; i++) printf("%4d", VB[i]);
printf("\n\n");
}
MPI_Finalize();
return 0;
}
EJERCICIO 10: sumvecser.c - Calcula V(i) = V(i) * sumatorio(V(j)) Codigo serie;
#include <stdio.h>
int main(int argc, char **argv)
{
int N, i;
int *V, sum=0;
printf("\nLongitud del vector: ");
scanf("%d", &N); // Multiplo
del numero de procesos
V = (int *)malloc(sizeof(int) * N);
for(i=0; i<N; i++) V[i] = rand() % 100 - 50; //
inicializacion del vector
// Procesamiento del vector
for (i=0; i<N; i++) sum = sum + V[i];
for (i=0; i<N; i++) V[i] = V[i] * sum;
// Imprimir unos resultados
printf("\n sum = %d\n", sum);
printf("\n V[0] = %d, V[N/2] = %d, V[N-1] = %d\n\n\n",
V[0],V[N/2],V[N-1]);
return 0;
}
CONCLUSIONES
Dentro de la distribución de LAM existen ejemplos que se pueden
ejecutar para comprobar el funcionamiento del entorno. Si nos
interesa determinar el número de megaflops (millones de
operaciones en punto flotante por segundo) del cluster sin recurrir a
los benchmarks estándar (incluyen resolución de sistemas lineales,
resolución de EDP's, etc.) puedes hacerlo usando mflops.
El siguiente paso es dotar al cluster de herramientas que faciliten su
gestión. La herramienta ganglia permite la monitorización del cluster
(carga por cpu, memoria usada, usuarios conectados, etc.) a través de
web y con gráficos.
Si deseamos dar un uso intenso al cluster con múltiples tareas y de
forma constante nos hará falta un planificador de tareas que se
encargue de ejecutarlas a su tiempo, balancear la carga, determinar
los recursos necesarios para llevar a cabo una tarea, etc.
top related