Sie sind auf Seite 1von 36

aic2tema5

Parallel Virtual Machine


ndice
5.1. Caractersticas de PVM 5.2 Arquitectura de PVM 5.2.1 Modelo de computacin 5.2.2 Modelo de implementacin 5.2.3 Arranque y configuracin de PVM 5.2.4 Construccin de la mquina virtual (interioridades). 5.3 Modelo de comunicacin. 5.3.1 Mensajes. 5.3.2 Tarea demonio. 5.3.3 Demonio demonio. 5.3.4 Etapas de un mensaje. 5.4 Programacin de aplicaciones en PVM 5.4.1 Interfaz de usuario de PVM 5.4.2 Funciones para el control de procesos 5.4.3 Funciones de informacin 5.4.4 Funciones de configuracin dinmica de la mquina virtual 5.4.5 Funciones de sealizacin 5.4.6 Funciones de control de buffers 5.4.7 Funciones de empaquetado/desempaquetado de datos. 5.4.8Funciones para envo y recepcin de mensajes. 5.4.9 Funciones para operaciones colectivas 5.5 Ejemplos 5.5.1 Padre-Hijo 5.5.2 Envo de mensajes 5.5.3 Uso de grupos 5.5.4 Informacin de la PVM 5.5.5 Producto escalar de dos vectores 5.5.6 Producto de dos matrices cuadradas

5.1 Caractersticas de PVM


SW de dominio pblico desarrollado por el Oak Ridge National Laboratory. Computacin basada en procesos. Modelo basado en paso de mensajes. Heterogeneidad a nivel de computadores, redes y aplicaciones.

Existe la posibilidad de asignar explcitamente tareas a computadores concretos. Los computadores de la mquina virtual pueden ser multiprocesadores de memoria distribuida o compartida. Escalabilidad. Inclusin/ eliminacin de forma dinmica. Se puede configurar en una aplicacin una submquina virtual dentro de la mquina virtual. Tolerancia a fallos. No proporciona tolerancia a fallos de forma implcita en una aplicacin. El programador es el responsable de disearla en el programa. Dominio pblico. Versin actual: 3.4.4 Bajo coste. SW gratuito. HW: cualquier computador con versiones Linux/PVM. Portabilidad.

Entornos donde se ha instalado PVM MODELO DE COMPUTADOR ORDENADORES PERSONALES SISTEMA OPERATIVO -------------------------------------------------------------------------------WinNT, Linux, Solaris, SCO, NetSBD, BSDI, FreeBSD, NetBSD -------------------------------------------------------------------------------OSF, NT-Alpha, HP-UX, AIX 3.x, AIX 4.x, IRIS 5.x, IRIS 6.x, SunOS, Solaris 2.x -------------------------------------------------------------------------------2

Pentium II, Pentium PRO, Pentium Duals y Quads, AMD, Apple Macintosh ESTACIONES DE TRABAJO Y SISTEMAS DE MEMORIA COMPARTIDA DEC Alpha, Pmax, Microvax, HP 9000, IBM RS6000, J30, SGI, SUN3, SUN4, SPARC, Ultra SPARC COMPUTADORES PARALELOS

Cray YMP T3D T3E, Cray2, Convex Exemplar, IBM SP2, 3090, NEC SX-3, Fujitsu, Amdahl, TMC CM5, Intel Paragon, Sequent, Symmetry, Balance

5.2 Arquitectura de PVM


Cada tarea puede enviar un mensaje a cualquier otra tarea PVM No existen lmites en el nmero y tamao de los mensajes. Factor condicionador ==> memoria disponible en cada computador. Envo asncrono sin bloqueo Devuelve el control a la tarea tan pronto como el buffer de envo est libre para ser utilizado de nuevo con independencia de que el destinatario haya realizado una llamada a la funcin de recepcin. Recepcin asncrona con/sin bloqueo. Una recepcin no-bloqueante devuelve el control a la tarea con independencia de la llegada de los datos. Existe un flag que permite determinar qu ha ocurrido en la recepcin. La recepcin bloqueante no devuelve el control a la tarea en tanto no se produzca la llegada de los datos al buffer de recepcin. Se garantiza el orden de los mensajes. Modificacin del orden mediante las funciones de filtrado. Difusin de mensajes en modo broadcast. Mismo mensaje a un grupo de tareas. Grupos dinmicos de tareas. Identificador de grupo. Formar parte de diferente grupos. Entrada y salida dinmica. Sincronizacin de barrera y envo de mensajes en modo broadcast. Envo de seales y eventos asncronos. Ej.: despertar a una tarea para recibir un mensaje, notificar situaciones anmalas. La recepcin de eventos slo se puede dar en: conclusin de una tarea, y eliminacin/inclusin de un computador en la mquina virtual.

5.2.1 Modelo de computacin


a. Paralelizacin de una aplicacin segn la similaridad de sus tareas: a. MPMD o paralelismo a nivel funcional: i. Cada tarea realiza una funcin diferente (entrada de datos, resolucin del problema, presentacin de resultados...) ii. Cmo se obtiene el paralelismo? 1. Ejecutando diferentes tareas de forma concurrente. 2. Estableciendo entre alguna de ellas una segmentacin o pipeline a nivel de datos. b. SPMD: i. Cada tarea ejecuta el mismo cdigo pero sobre un subconjunto diferente de datos. b. Paradigmas algortmicos de paralelizacin desde el punto de vista de la estructuracin de las tareas: a. Fases paralelas: i. Sucesin de un nmero indeterminado de fases para alcanzar la solucin. ii. Cada fase tiene dos etapas: clculo e interaccin.

b. Segmentacin (pipeline) i. Las tareas de la aplicacin se comportan como etapas de una segmentacin virtual a travs de la cual los datos circulan de forman continua.

EJEMPLO - Suma de nmeros (Segmentacin)

Cdigo bsico para el procesador PI recv(&accumulation, Pi-1); accumulation=accumulation+number; send(&accumulation, Pi+1); Excepto para el primer proceso P0: send(&number, P1); Y el ltimo proceso Pn-1, que es: recv(&number, Pn-2); accumulation=accumulation+number;

c.

Arborescente i. Adecuado para problemas en los que la carga de trabajo se desconoce a priori (algoritmos recursivos o de clasificacin...) ii. Difcil balancear adecuadamente la carga

d. Maestro-esclavo (host-node) i. Tarea maestra 1. Parte secuencial del algoritmo 2. Lanza e inicializa las tareas esclavas, recoge los resultados y realiza (si hay) funciones de sincronizacin Variantes ii. 1. Un hijo cuando concluye puede recibir ms carga del padre y continuar trabajando. 2. El padre puede tener que procesar la parte que le corresponda de la carga de trabajo.

e. Hbrido i. Generacin totalmente arbitraria de la estructura de las tareas en funcin de la carga de trabajo a procesar

5.2.2 Modelo de implementacin


Demonio (pvmd3): Instalado en todos los computadores de la mquina virtual. Acepta como parmetro opcional un fichero con la configuracin. Gestiona y ejecuta las aplicaciones PVM en la mquina virtual, administra los mecanismo de sincronizacin, comunicacin, conversin de datos y oculta la estructura de red al programador. Biblioteca de desarrollo (API): Contiene funciones para operar con las tareas, transmitir mensajes entre ellas y alterar las propiedades o configuracin de la mquina virtual. Toda aplicacin se debe enlazar con los ficheros de la biblioteca. Estos ficheros son tres: libpvm3.a, libgpvm3.a, libfpvm3.a. Consola de PVM. 5

Proporciona una interfaz simple entre el usuario y el demonio. Permite modificar de forma interactiva la mquina virtual que previamente ha sido definida por el demonio mediante el fichero de configuracin. Versin grfica de la consola: xpvm.

5.2.3 Arranque y configuracin de PVM


Hay cuatro formas de arrancar PVM en Linux: - Desde la consola (pvm) - Desde la consola grfica (xpvm) - Ejecutando de forma directa el demonio (pvmd3)
pvm [-n host_name] [host_file] xpvm [-n host_name] [host_file] pvmd3 [-n host_name] [host_file]& o n host_name permite especificar un nombre alternativo para la mquina en la que se arranca el demonio en caso de que estn instaladas varias tarjetas o interfaces de red. o host_file fichero de configuracin. - Desde un programa (funcin pvm_start_pvmd Antes de visualizar la consola se produce la lectura del fichero $HOME/.pvmrc

SINTAXIS

SIGNIFICADO

EJEMPLO

add host_1...host_n

Incorpora los computadores host_1 a host_n a la mquina virtual.

add tarzan

alias atajo comando

Define un atajo o alias para escribir un comando. Sin parmetros, lista los existentes. Muestra la configuracin de la mquina virtual

alias h help

conf

delete host_1...host_n

Elimina los computadores host_1 a host_n de la mquina virtual. Los procesos que se encuentren funcionando en esos computadores son eliminados. No se puede eliminar la mquina desde la que se est utilizando la consola. Muestra en pantalla argumento.

delete tarzan

echo argumento

echo hola mundo

halt

Mata (elimina) a todos los procesos y demonios PVM incluyendo la consola y detiene la mquina virtual. Es la forma recomendada para detener el sistema ya que asegura una salida ordenada.

help comando

Muestra todas las opciones disponibles para comando. Sin argumento lista todos los comandos que se pueden utilizar en la consola. Imprime el identificador (TID) de la tarea consola.
Visualiza un listado de los trabajos en ejecucin.

help halt

id

jobs

kill tid

Se utiliza para matar una tarea PVM mediante su identificador.

kill 40003

mstat host

Muestra el estado del computador host.

mstat tarzan

ps opciones

Lista todos los procesos que se ejecutan en la mquina virtual. Muestra su localizacin, su identificador y el de la tarea padre. Las opciones que posee son: -a: Informacin de todos los procesos. -hhost_tid: Informacin de los procesos del nodo que tenga como TID host_tid. -nhost_name: Informacin de los procesos que del nodo con el nombre host_name -x: Informacin de todos los procesos, incluida la consola.

ps ps ps ps

-a -h40003 -nlinda.uned.es -x

pstat tid

Imprime por pantalla el estado de la tarea cuyo identificador es tid. Cierra la consola dejando la mquina virtual funcionando.

pstat 40003

quit

reset

Mata todas las tareas PVM salvo las consolas que se encuentren en ejecucin, limpia los buffers de envo y recepcin de mensajes, inicializa las tablas internas de PVM y deja a los demonios en estado de espera. Visualiza las variables de entorno del sistema.

setenv

sig n_seal tid

Enva la seal n_seal a la tarea cuyo identificador es tid.

sig 15 40003

alias ? help alias ayuda help alias stop halt alias exit quit alias depurar trace echo Configuracin actual mquina virtual conf echo Versin de PVM version echo TID de la consola id add blancanieves add sabio Ejemplo de fichero .pvmrc

Hay dos formas de configurar PVM: Fichero de configuracin Contiene la lista de los computadores que forman la mquina virtual. Contiene los computadores que en el futuro pueden aadirse desde consola. Cada usuario puede tener su propio fichero de configuracin. Sintaxis: nombre_computador opcion_i=valor_i Manualmente desde Consola (add) No permite incluir opciones Salvo que se hayan especificado antes en el fichero de configuracin (&)
OPCIONES lo=nombre_usuario SIGNIFICADO Permite indicar un nombre de usuario (login) alternativo para realizar la conexin remota al computador. Por defecto, se utiliza el login empleado en la mquina en que se inici la ejecucin de PVM.

so=pw

Provoca que el demonio de la mquina en la que se inici la ejecucin de PVM solicite una contrasea para poder acceder a la mquina remota. Cuando se recurre a esta opcin no se puede arrancar la PVM desde la consola o como tarea de fondo ya que el demonio solicita la entrada de datos a travs del teclado. Al procesar el demonio esta opcin se obtendr por pantalla el mensaje: Password (tarzan.dia.uned.es:msanchez): teniendo que introducir la contrasea del usuario msanchez en el computador tarzan.dia.uned.es. Tras esto, el arranque de la mquina continuar normalmente. Por defecto, PVM utiliza el comando rsh para iniciar los demonios pvmd3 remotos. Esto slo funcionar si en la mquina remota aparece el nombre del computador local en el fichero .rhosts del usuario o en el fichero /etc/host.equiv del sistema y, adems, las RPC (Remote Procedure Calls) estn activadas. Sin embargo, cuando se especifica esta opcin el demonio maestro recurre a la funcin rexec() para la creacin de la tarea remota.

dx=ubicacion_del_demonio

Permite establecer al demonio en la mquina remota en una ubicacin diferente a la que se utiliza por defecto. Se puede indicar una ruta absoluta o relativa con respecto al directorio home del usuario en la mquina remota seguido del nombre del demonio (por defecto, pvmd3). Es la opcin adecuada para poder utilizar la instalacin personal de un usuario.

ep=ubicaciones_de_ejecutables

Conjunto de rutas separadas por el carcter : en las que se encuentran los ficheros que se van a utilizar. Si no se especifica esta opcin, la mquina virtual buscar las aplicaciones en la ruta $HOME/pvm3/bin/PVM_ARCH siendo PVM_ARCH el nombre de la arquitectura de la mquina considerada.

sp=valor_numerico

Permite especificar la potencia del computador en relacin con las dems mquinas que constituyen la mquina virtual. El valor numrico debe ser entero y estar en el rango [1 1000000]. El valor por defecto es 1000.

wd=directorio_de_trabajo

Permite indicar el directorio de trabajo en el que se van a ejecutar todas las tareas que sean lanzadas. Por defecto se ejecutan en el directorio $HOME.

ip=nombre_de_ordenador

Cuando existen varios interfaces o tarjetas de red, esta opcin permite seleccionar un nombre de entre los que maneja la mquina. Hay que utilizar un nombre y no una direccin IP ya que el valor se pasa al comando rsh y a la funcin rexec().

so=ms

Implica que en esta mquina el demonio debe ser arrancado de forma manual. Esta opcin es la adecuada si no se pueden utilizar rsh y rexec() pero existe comunicacin IP entre el maestro y el esclavo. El empleo de esta opcin provoca el establecimiento de un dilogo a travs de la consola con el maestro, el cual ir proporcionando por consola las instrucciones necesarias para arrancar de forma manual el demonio. El uso de esta opcin no es muy habitual.

# Ejemplo de fichero de configuracin blancanieves sabio so=pw mudito dx=/url/local/bin/pvmd3 lo=lengua lloron ep=/home/ejecutables:~/bin cascarrabias lo=tozudo # Computadores que pueden aadirse #posteriormente con el comando add

&ulises.dia.uned.es lo=laertes &telemaco.ucm.es so=pw &penelope.mat.uned.es wd=/home/pruebas/ Ejemplo de fichero de configuracin

# Ejemplo de fichero de configuracin con #opciones por defecto * lo=aqueo dx=/url/local/bin/pvmd3 patroclo aquiles # Redefinicin de una de las opciones por #defecto * lo=troyano hector paris Ejemplo de fichero de configuracin con opciones por defecto

5.2.4 Construccin de la mquina virtual


Arranque del demonio maestro: Es el que arranca en primer lugar (4 formas descritas). Arranca a los demonios esclavos segn el host_file. Este proceso de arranque se realiza por el proceso shadow pvmd o pvmd (proceso hijo del maestro realizada mediante la llamada al sistema fork()). Cada demonio arranca en el directorio /tmp dos ficheros: pvm1.uid (registro de errores). pvmd.uid (n ip y puerto de escucha). uid: identificador numrico del usuario que ejecuta el demonio. Creacin de los demonios esclavos: Manualmente (opcin so=ms del host_file). No se puede usar para la inclusin dinmica. Suele usarse si los servicios RPC estn deshabilitados pero existe conectividad entre las mquinas mediante TCP/IP. Mediante el comando rsh(): Tienen que estar activos los servicios RPC (demonio rshd). Sin necesidad de contraseas: /etc/hosts.equiv: contiene todos los nombres de los computadores que componen la mquina virtual. $HOME/.rhosts: contiene todos los nombres de los computadores que componen la mquina virtual. Mediante la funcin rexec(): Se encuentra compilada como parte del cdigo de pvmd3. Reclama al usuario el empleo de una contrasea en tiempo de ejecucin. La tabla del host. Contiene informacin de los computadores que forman la PVM. Entrada host descriptor: hay una por cada uno de los computadores que foman la mquina virtual. Permite acceder a la informacin de configuracin del computador y de los buffers de mensajes. Cada demonio tiene una copia de la host table. Por qu se puede producir la actualizacin? Al aadir un nuevo esclavo a la mquina virtual. El maestro se encarga de actualizar la host table y enviar la taba actualizada mediante broadcasting a todos los esclavos. Eliminacin de un esclavo desde el maestro. El maestro enva un mensaje a todos los esclavos indicando la mquina que ha causado la baja. Un demonio sea dado de baja de forma local, sea cancelado por el envo de una seal UNIX, sea abortado... El esclavo mata a todas las tareas que dependan de l mediante el envo de la seal SIGTERM y remite un mensaje a los restantes demonios para que lo eliminen de sus copias de la host table. Eliminacin autnoma por parte de un esclavo de una entrada cuando observe que una mquina es inalcanzable (tiempo de confirmacin). 9

Identificador de una tarea (TID) Cada tarea, grupo de tareas y demonios poseen un TID nico. Campos: S (Server bit), G (Group bit), H (Host field), L (Local field). H: almacena el host descriptor. Es posible disponer de hasta (212 1)= 4095 computadores en una mquina virtual. L: identifica a una tarea dentro de cada uno de los computadores de la mq. virtual. Pueden coexistir hasta (218 1)= 262143 en cada computador. G H L

31

30

29

18

17

SIGNIFICADO

1...4095

1...262143

Identificador de una tarea.

1...4095

1...262143

Direccin multicast.

Identificador del demonio local a la tarea.

1...4095

Identificador de un demonio.

Identificador del shadow daemon en la mquina maestra.

Nmero negativo

Nmero negativo

Condicin de error.

10

5.3 Modelo de comunicacin


Tipos de comunicacin que coexisten en la PVM: Indirecta entre dos tareas (opcin por defecto): Entre un demonio y una tarea (TCP) Entre demonios (UDP) Directa entre dos tareas (TCP) Hay que compilar PVM con la opcin.

5.3.1 Mensajes
Partes del mensaje: Cuerpo: informacin til (datos del problema) que se intercambian las tareas. Cabecera: informacin de control. Cdigo: n entero que define el tipo de mensaje (filtrado). Codificacin: indica la clase de empaquetamiento. Wait context ID (waitc): lo genera el demonio cuando recibe una peticin de servicio por parte de una tarea local. Este nmero se enva al demonio destino y se devuelve con la respuesta. El waitc sirve para que el demonio local cuando reciba la conformidad del demonio destino pueda recuperar el contexto en que se encontraba y saber qu tarea fue la originaria. Checksum: para control de errores. No se

usa.

5.3.2 Tarea-demonio:
Se realiza a travs de sockets TCP. Se puede selecionar en la compilacin que los sockets sean Unix en lugar de TCP (ms rpido). Servicio seguro (mensajes de confirmacin). Comunicacin a nivel local ==> coste de creacin y cierre relativamente bajo. Formato de las cabeceras de los paquetes: SOM (Start Of Message). SOM=1: primer mensaje. EOM (End Of Message). EOM=1: ltimo mensaje. SOM=EOM=0 ==> fragmento intermedio.

11

5.3.3 Demonio-demonio:
Protocolo UDP. Bajo nmero de conexiones. Coste de creacin de sockets UDP ms bajo que los de TCP. Empleo de timers del nivel UDP para detectar problemas en las comunicaciones o los demonios. Cabecera del paquete: SOM y EOM: determinan los paquetes que delimitan el comienzo y final de un mensaje. DAT: indica que el paquete contiene datos vlidos y debe ser entregado a la tarea. ACK: indica que el nmero del paquete del que se confirma su recepcin es vlido. PVM enva un paquete de ACK (ACK=1, DAT=0) por cada fragmento de datos recibido (ACK=0, DAT=1). Ambos bits activos: piggybacking. FIN: provoca el cierre ordenado del proceso de comunicacin entre los demonios.

5.3.4 Etapas de un mensaje


M: mensaje Mn: partes en que se descompone M. CT: cabecera tarea. CTD: cabecera tarea demonio. CDD: cabecera demonio-demonio. ACK: cabeceras con ACK=1, DAT=0

12

5.4 Programacin de aplicaciones en PVM


Aplicacin paralela basada en PVM: Lenguaje de programacin: C, C++ y FORTRAN. API de PVM. Composicin de la aplicacin paralela: Un nico programa: Lanzado desde la consola. Se generan varias copias con el comando spawn. Programa maestro y esclavo: El programa maestro crea tareas que ejecutan el cdigo de los esclavos. Un nico programa: Se desdobla en varias tareas. Cada tarea ejecuta un cdigo segn la lgica del programa. Restriccin al lanzamiento de una tarea desde la consola: la tarea no debe contener una entrada interactiva. Salida estndar: Aplicacin invocada desde la lnea de comandos: los resultados se escriben en pantalla. Aplicacin lanzada desde la consola: la salida ir al fichero /tmp/pmd1.uid del demonio maestro.

5.4.1 Interfaz de usuario de PVM


http://www.netlib.org/pvm2/book/pvm-book.html Control de procesos: creacin y destruccin de tareas. Informacin: permiten obtener informacin sobre el estado de la mquina virtual. Configuracin dinmica de la mquina virtual: permiten la adaptacin del sistema ante determinadas situaciones, como por ejemplo, un fallo de computadores o un aumento de la carga computacional. Sealizacin: permiten dotar a la mquina virtual de la funcionalidad necesaria para poder construir aplicaciones paralelas tolerantes a fallos. Control de buffers: limpiar buffer de envo, crear un buffer, establecer un buffer activo... Empaquetamiento /desempaquetamiento de datos. Envo y recepcin de mensajes. Operaciones colectivas.

13

5.4.2 Funciones para el control de procesos


OPCIONES int info=pvm_start_pvmd(int arg, char **argv, int block) int info=pvm_addhosts(char *infos) int info=pvm_delhosts(char *infos) **hosts, int nhost, int SIGNIFICADO

Arranca el demonio PVMD.


Aade hosts a la mquina virtual PVM. Elimina hosts de la mquina virtual PVM. Arranca nuevos procesos bajo PVM.

**hosts,

int

nhost,

int

int numt=pvm_spawn(char *task, char **argv, int flag, char *where, int ntask, int *tids) task: nombre del programa PVM que va a ejecutarse. La ruta por defecto en que se buscan los programas es $HOME/pvm3/bin/$PVM_ARCH. argv: puntero a un vector de argumentos que se pasa a la tarea que va a ser creada, siendo el elemento 0 el nombre y ubicacin del proceso y el ltimo null. flag: valor entero que se emplea para especificar las opciones de creacin del proceso.

where: cuando procede, es una cadena de caracteres que indica dnde crear el proceso. ntask: n de copias del proceso que hay que crear. tids: array con los TIDs de las tareas creadas con xito. Si hay errores, los cdigos de error se sitan en las ltimas (ntask-numt) posiciones. Termina tarea PVM

int info=pvm_kill(int tid)

Ejemplos de uso de la funcin pvm_spawn. numt=pvm_spawn(argv[0], (char**)0, PvmTaskDefault, (char*)0, n, tids); numt=pvm_spawn(argv[0], (char**)0, PvmTaskDefault,``, n , tids); char argumentos[] = {12, 60, (char*)0} numt=pvm_spawn(esclavo, argumentos, 0, 0, 16, tids) numt=pvm_spawn(esclavo,0,PvmTaskHost,ulises.dia.uned.es, 1, &tids[0]); numt=pvm_spawn(esclavo, 0, PvmTaskArch,SUN4, 1, tids); numt=pvm_spawn(esclavo, 0, PvmTaskHost, linda, 256, tids); int info=pvm_kill (int tid). Solicita la terminacin del proceso que la recibe. No debe usarse para la terminacin de la tarea que la invoca (pvm_exit() y exit()). info<0==> error int info=pvm_start_pvmd (int argc, char **argv, int block). 14

argc: n de argumentos en argv. argv: array de parmetros que se pasan al demonio. Nombre de un host_file. block: block<>0: la rutina ha de esperar hasta que todos los comutadores indicados en el host_file se incorporen. block=0: permite continuar la ejecucin del programa. info: devuelve 0 si la rutina se ejecuta con xito.

5.4.3 Funciones de informacin int tid = pvm_mytid(); int tid = pvm_parent(); Devuelve el TID del padre o el valor PvmNoParent si el proceso no fue creado con la funcin pvm_spawn(). int info = pvm_config( int *nhost, int *narch, struct pvmhostinfo **hostp); nhost: n de computadores que forman la mquina virtual. narch: n de diferentes formatos de datos que se estn utilizando. hostp: puntero a un array de estructuras del tipo pvm hostinfo que proporciona la siguiente informacin sobre
cada computador: int hi_tid: DTID del demonio.

char *hi_name: array de caracteres con el nombre del computador. char *hi_arch: array de caracteres con el nombre de la arquitectura. int hi_speed: velocidad relativa del computador.
struct pvmhostinfo *computadores; int i, nhost, narch; info = pvm_config( &nhost, &narch, &computadores ); printf ("Nmero de nodos que componen la PVM: %d\n", nhost); printf ("Tipos de arquitecturas que componen la PVM: %d\n", narch); for (i = 0; i < nhost; i++) { printf("Nombre: %s\n", computadores[i].hi_name); printf("DTID: %x\n", computadores[i].hi_tid); printf("Arquitectura: %s\n", computadores[i].hi_arch); } Ejemplo

int info = pvm_tasks (int which, int *ntask, struct pvmtaskinfo **taskp); Proporciona informacin sobre las tareas PVM que se estn ejecutando en la mquina virtual. which 0: solicita informacin de todas las tareas. DTID: solicita informacin de las tareas asociadas a ese demonio. TID genrico para una tarea concreta. ntask: n de tareas de las que se devuelve informacin. taskp: puntero a un array de tamao ntask de estructuras del tipo pvmtaskinfo. int ti_tid: TID de la tarea. int ti_ptid: TID de la tarea padre. int ti_host: TID del demonio bajo el que se ejecuta la tarea. int ti_flag: indicador del estado de la tarea. char *ti_a_out: cadena de caracteres con el nombre de la tarea.

struct pvmtaskinfo *taskp; int i, ntask; info = pvm_tasks( 0, &ntask, &taskp );

15

printf("Total tareas en PVM: %d\n", ntask); for (i = 0; i < ntask; i++) { printf("TID tarea: %x\n", taskp[i].ti_tid); printf("TID tarea padre: %x\n", taskp[i].ti_ptid); printf("TID demonio: %x\n", taskp[i].ti_host); printf("Nombre de la tarea: %s\n", taskp[i].ti_a_out); } Ejemplo

int info = pvm_perror (char *msg); Imprime informacin sobre el error producido en la ltima llamada a una funcin de PVM. msg: mensaje adicional que se concatena a la informacin generada por la rutina. int status = pvm_pstat (in tid) Proporciona informacin sobre el estado de la tarea de identificador tid.

int mstat = pvm_mstat (char *host) Proporciona infromacin sobre el estado del computador host.

int oldval = pvm_setopt (int what, int val) Rutina de propsito general para el cambio de ciertas opciones que determinan el funcionamiento de la mquina virtual. Algunas opciones: impresin automtica de errores, nivel de depuracin, enrutamiento de los mensajes... int val = pvm_getopt (int what) Rutina de propsito general que permite obtener informacin sobre la configuracin de la mquina virtual.

5.4.4 Funciones de configuracin dinmica de la mquina virtual


int info = pvm_addhosts (char **hosts, int nhost, int *infos) Rutina para la inclusin de nhost nuevos computadores en la mquina virtual. hosts: array de cadenas de caracteres con el nombre de los computadores a incluir en la mquina virtual. nhost: n de computadores a aadir. infos: array con los cdigos de estado de cada uno de los computadores indicados en el array hosts. info: info=nhost: todos los computadores se han aadido. 1<=info<nhost: se ha producido algn fallo. ==> anlisis de infos. info<1: no se ha aadido ningn computador.

16

int info = pvm_delhosts (char **hosts, int nhost, int *infos) Rutina para la eliminacin de nhost computadores de la mquina virtual.

5.4.5 Funciones de sealizacin


int info = pvm_sendsig (int tid, int signum); Rutina para el envo de una seal signum a la tarea PVM asociada al tid. Si se enva con xito la sel info=0. inf info = pvm_notify (int what, int msgtag, int cnt, int *tids); Funcin que enva un mensaje a la tarea que lo invoca cuando suceden determinados eventos en un conjunto especfico de tareas. what: establece el evento al que hay que prestar atencin.

msgtag: etiqueta del mensaje que se enva a la tarea que ha invocado la rutina. cnt: especifica la long. del array cuando se usan las opciones PvmTaskExit y PvmHostDelete. Cuando se usa la opcin PvmHostAdd, se indica las veces que hay que avisar. tids: lista de los TIDs de las tareas y demonios que hay que observar. El array est vaco si se usa la opcin PvmHostAdd

info = pvm_notify( PvmTaskExit, 100, contador, array_tids ); % Establecimiento de la notificacin. pvm_notify( PvmTaskExit, 9999, contador, arraytids ); . . . . . . . . . . . . % Cancelacin de la notificacin. pvm_notify( PvmTaskExit | PvmNotifyCancel, 9999, contador, arraytids ); Ejemplo

5.4.6 Funciones de control de buffer


Pasos para el envo de un mensaje de una tarea PVM: Inicializacin de un buffer de envo Empaquetamiento del mensaje en el buffer Envo del mensaje Pasos para la recepcin de un mensaje por una tarea: Recepcin mensaje (modo bloqueante o no bloqueante). Desempaquetamiento de los datos. Inicialmente para cada tarea PVM se crea un buffer activo de envo y otro de recepcin. El programador puede crear ms buffer pero slo puede haber uno activo en cada instante. int bufid = pvm_initsend (int encoding); Limpia el buffer de envo activo. bufid: identificador del buffer activo. 17

encoding: indica el mtodo de codificacin. PvmDataDefault: formato XDR (adecuado para entornos heterogneos). PvmDataRaw: sin codificacin (slo posible si los computadores tienen formatos de datos compatibles si no dar error en el desempaquetado). PvmDataInPlace: en el buffer se almacenan nicamente punteros a los datos y sus tamaos, manteniendo los datos almacenados en el espacio de datos del usuario. Los datos han de estar en posiciones contiguas de memoria y no deben ser modificados entre el empaquetado y envo.

int bufid = pvm_mkbuf (int encoding) Crea un buffer de envo vaco. int info = pvm_freebuf (int bufid) Se emplea para liberar la memoria asignada al buffer bufid cuando no vaya a ser utilizado ms. int bufid = pvm_getsbuf () Devuelve en bufid el identificador del buffer activo de envo. int bufid = pvm_getrbuf () Devuelve en bufid el identificador del buffer activo de recepcin. int oldbuf = pvm_setsbuf (int bufid) Establece como buffer activo de envo el identificado por bufid. oldbuf: valor del buffer de envo activo antes de invocar la rutina. int oldbuf = pvm_strbuf (int bufid). Establece como buffer activo de recepcin el identificado por bufid. oldbuf: valor del buffer de recepcin activo antes de invocar la rutina.

5.4.7 Funciones de empaquetado y desempaquetado de datos


Argumentos de las rutinas de empaquetado: Puntero al primer elemento del arreglo a empaquetar. nitem: total de elementos a empaquetar. stride: establece la distancia entre dos elementos consecutivos a empaquetar. stride = 2 de cada dos elementos se empaqueta 1. Formato genrico de las funciones ms importantes: int info = pvm_pkXXX (YYY *datos, int nitem, int stride) int info = pvm_upkXXX (YYY *datos, int nitem, int stride) XXX: tipo de datos de PVM que se va a enviar. YYY: tipo de datos C del array a empaquetar. int info = pvm_pkstr (char *cadena) int info = pvm_upkstr (char *cadena)

18

5.4.8 Funciones para el envo y recepcin de mensajes


a) Datos a enviar son de distinto tipo: Necesariamente tienen que ser empaquetados antes de ser colocados en un buffer de envo de PVM. pvm_send (): envo no bloqueante. pvm_recv (): recepcin bloqueante. Crea un nuevo buffer de recepcin activo para el mensaje que llega. pvm_nrecv (): recepcin no bloqueante.

b) Datos a enviar son del mismo tipo: Se emplea pvm_psend() y pvm_precv(). Estas rutinas conllevan el empaquetamiento/envo o desempaquetamiento/recepcin.

19

c) Modos de empaquetamiento de datos de PVM:

d) Descripcin de las rutinas: int info = pvm_send (int tid, int msgtag) info = pvm_initsend (PvmDataDefault); info = pvm_pkint( array, 10, 1); info = pvm_send( tid, -1) int info = pvm_psend (int tid, int msgtag, void *buf, int len, int type); Valores del argumento type:

20

int info = pmv_mcast (int *tids, int ntask, int mstag) Rutina no-bloqueante que enva el mensaje previamente empaquetado en el buffer activo a un grupo de ntask tareas identificado por el array tids). msgtag ha de ser mayor o igual que 0. info = pvm_initsend( PvmDataRaw); info = pvm_pkint( array, 10, 1); etiqueta = 5; info = pvm_mcast( tids, ntask, etiqueta);

? int bufid = pvm_recv (int tid, int msgtag); bufid: identificador del buffer de recepcin activo que ha sido creado y que contiene el mensaje recibido. Si se ha producido un error en la recepcin devuelve un valor inferior a 0. tid = pvm_parent(); bufid = pvm_recv( tid, -1); info = pvm_upkint( tids, 10, 1); info = pvm_upkint( tamanio_problema, 1, 1); info = upkfloat( array_entrada, 100, 1); int bufid = pvm_nrecv( int tid, int msgtag); tid = pvm_parent (); bufid = pvm_nrecv( tid, -1); if (bufid){ info = pvm_upkint (tids, 10, 1); info = pvm_upkint (tam_prob, 1, 1); info = pvm_upkfloat (array, 100, 1); } else /*Realizar otras operaciones */ ? int bufid = pvm_trecv (int tid, int msgtag, struct timeval *timeout) Permite fijar un tiempo mximo de espera para la recepcin del mensaje. int bufid = pvm_probe (int tid, int msgtag); Rutina no-bloqueante que slo devuelve un identificador del buffer en el bufid como notificacin de que el mensaje ha llegado. Si el mensaje no ha llegado a la tarea receptora la rutina devuelve 0. tid = pvm_parent (); etiqueta = 4; recibido = pvm_probe( tid, etiqueta); if (recibido) bufid = pvm_recv(tid, etiqueta); else 21

/*Realizar otras operacione*/ ? int info = pvm_bufinfo (int bufid, int *bytes, int *mstag, int *tid) Permite obtener informacin del mensaje almacenado en el buffer bufid. bytes: long. del cuerpo del mensaje en bytes. msgtag: etiqueta del mensaje. tid: identificador de la tarea origen del mensaje. bufid= pvm_recv (-1, -1); info = pvm_bufinfo( bufid, &long, &tipo, &tid)

int info = pvm_precv (int tid, int msgtag, void *buf, int len, int type, int *rtid, int *rtag, int *rlen) tid: identificador tarea origen (comodn 1) msgtag: etiqueta buf: puntero al array en que almacenamos el mensaje recibido. len: tamao del array (mltiplo del tamao del tipo de datos). type: tipo de los datos del array.

o rtid: identificador de la tarea que ha enviado el mensaje. o rtag: etiqueta del mensaje recibido. o rlen: long. del mensaje recibido. o info: xito info=0, fracaso info<0

5.4.9 Funciones para operaciones colectivas


PVM Group Server (pvmgs): se activa al invocarse la primera funcin colectiva. Biblioteca de grupos: libgpvm3.a Agrupamiento dinmico: permite que existan varios grupos de tareas simultneamente y que una tarea forme parte de varios grupos a la vez. Las llamadas a funciones colectivas pueden producir resultados imprevistos dependiendo de si una tarea abandona o entra en el grupo. int inum = pvm_joingroup (char *group) inum: instancia (n de orden de la tarea en el grupo. Si n es el n de tareas dentro del grupo, 0<=inum<=n-1. Las tareas que se desunen del grupo y se vuelven a unir pueden que no obtengan el n de instancia que tenan. PVM intenta rellenar huecos con los n de instancia de los miembros del grupo que lo han abandonado. Cdigos de error que pueden ser devueltos en inum:

22

int info = pvm_lvgroup (char *group) Cdigos de error que pueden ser devueltos por info:

int tid = pvm_gettid (char *group, int inum) Obtiene el tid de la tarea que tiene asignado el n inum en el grupo group. int inst = pvm_getinst(char *group, int inum) int size = pvm_getsize (char *group) int info = pvm_barrier (char *group, int count) La tarea se bloquea hasta que count miembros de group han invocado esta funcin. Se produce un error si las tareas que llaman a la funcin usan un valor de count distinto. Normalmente se usa count=(n miembros del grupo). count=-1 PVM usa el valor obtenido con pvm_ info = 0 xito. info<0 errores.

int info = pvm_bcast (char *group, int msgtag) No-bloqueante. Enva el mensaje almacenado en el buffer activo a todos los procesos que forman parte de group excepto a la tarea que invoca la funcin. Se puede invocar la funcin sin pertenecer al grupo. info = pvm_initsend( PvmDataRaw); info = pvm_pkint( array, 10, 1); etiqueta = 5; info = pvm_bcast (grupo, etiqueta);

int info = pvm_reduce(void (*func) (), void *data, int count, int datatype, int msgtag, char *group, int rootginst) No-bloqueante. Debe ser invocada por todas las tareas que forman el grupo. Puede ser necesario llamar a pvm_barrier para sincronizar las tareas implicadas. func: funcin que define la operacin a realizar sobre los datos. PvmMax, PvmMin, PvmSum y PvmProduct. Se pueden usar funciones definidas por el usuario. void func (int *datatype, void *data, void *y, int *count, int * info) y: valores recibidos de las otras tareas implicadas en la funcin pvm_reduce. data: puntero a la direccin del array que contiene los valores locales. Al terminar el proceso root tendr el resultado final de la operacin. count: n de elemntos del array. rootginst: instancia de la tarea root.

Nmero de rden de la tarea

Contenido del vector de datos

23

0 1 2 tarea_root = 1;

1,2,3,4,5 10,20,30,40,50 100,200,300,400,500

info = pvm_reduce( PvmSum, &datos, 5, PVM_INT, msgtag, calculador, tarea_root); Resultado despus de la op.: Nmero de rden de la tarea 0 1 2 tarea_root = 1; info = pvm_reduce( multiplicar, &datos, 5, PVM_INT, msgtad, calculador, tarea_root); void multiplicar( int *datataype, double *x, double y, int *num, int *info){ int i; for (i = 0; i< num; i++) x[i]*=y[i]; } Resultado despus de la op.: Nmero de rden de la tarea 0 1 2 Contenido del vector de datos No definido 1000,8000,27000,64000,75000 No definido Ejemplo Contenido del vector de datos No definido 111,222,333,444,555 No definido

int info = pvm_scatter (void *result, void *data, int count, int datatype, int msgtag, char *group, int rootginst) La tarea root enva a cada una de las tareas del grupo, incluida la que inicia el envo, una seccin del array. info = pvm_scatter(&getmyrow, &matriz, 10, PVM_INT, etiqueta, grupo, raiz)

int pvm_gather( void *result, void *data, int count, int datatype, int msgtag, char *group, int rootginst) Rutina para que la tarea root reciba un mensaje de cada uno de los integrantes del grupo, incluido ella, y recopile toda la informacin enviada en un nico array. pvm_gather es no bloqueante. Si una tarea llama a pvm_gather y abandona posteriormente el grupo antes de que la raz haya llamado a pvm_gather puede ocurrir un error.

24

5.5 Ejemplos PVM


5.5.1 Padre-Hijo
#include <stdio.h> #include <stdlib.h> #include <pvm3.h> int main() { int tid; int Hijos[2]; tid=pvm_mytid(); if (tid < 0) { printf("No puedo conectarme con PVM\n"); return -1; } printf("Soy el proceso padre con ID: %d. Ahora voy a lanzar 2 hijos\n", tid); if (pvm_spawn("plantilla-hijo", NULL, PvmTaskDefault, 0, 2, Hijos) != 2) { printf("ERROR lanzando la ejecucion de los procesos hijo\n"); pvm_exit(); return -1; } printf("Soy el proceso padre, Todo fue bien. Terminamos\n"); pvm_exit(); return 0; } Fichero PADRE

#include <stdio.h> #include <stdlib.h> #include <pvm3.h> int main() { int tid, parent_tid; tid=pvm_mytid(); parent_tid=pvm_parent(); if (tid < 0) { printf("No puedo conectarme con PVM\n"); pvm_exit(); return -1; } printf("Soy un proceso hijo, de identificador %d\n", tid); printf("El identidicador del padre es %d\n", parent_tid); pvm_exit(); return 0; } Fichero HIJO

25

5.5.2 Envo de mensajes


#include <stdio.h> #include <stdlib.h> #include <pvm3.h> int main() { int tid; int Hijos[2]; int temporal; tid=pvm_mytid(); if (tid < 0) { printf("No puedo conectarme con PVM\n"); return -1; } if (pvm_spawn("comunica-hijo", NULL, PvmTaskDefault, 0, 2, Hijos) != 2) { printf("ERROR lanzando la ejecucion de los procesos hijo\n"); pvm_exit(); return -1; } printf("Soy el proceso padre. Voy a enviar un entero a cada hijo\n"); /* Inicializando el buffer */ if (pvm_initsend(PvmDataDefault) < 0) { printf("Problemas en el Padre al inicializar el buffer\n"); pvm_exit(); return -1; } /* Colocando la informacion en el buffer */ temporal=1; if (pvm_pkint(&temporal, 1, 1) < 0) { printf("Problemas en el Padre al manipular el buffer\n"); pvm_exit(); return -1; } /* Envio la informacion a un hijo */ if (pvm_send(Hijos[0], 2) < 0) { printf("Problemas en el Padre al enviar el buffer al hijo 1\n"); pvm_exit(); return -1; } /* /* /* /* /* if Inicializando el buffer. Necesario porque no se borra */ Prueba a comentar esta seccion y vera como el hijo 2 */ Recibe un 1 en vez de un 2. Si la comenta prueba a que */ el hijo 2 realice dos operaciones pvm_recv y vera como */ el primer dato es 1 y el segundo 2 */ (pvm_initsend(PvmDataDefault) < 0) { printf("Problemas en el Padre al inicializar el buffer\n"); pvm_exit(); return -1;

} /* Colocando la informacion en el buffer */ temporal=2; if (pvm_pkint(&temporal, 1, 1) < 0) { printf("Problemas en el Padre al manipular el buffer\n"); pvm_exit(); return -1; } /* Envio la informacion a un hijo */ if (pvm_send(Hijos[1], 2) < 0) { printf("Problemas en el Padre al enviar el buffer al hijo 2\n"); pvm_exit(); return -1;

26

} printf("Soy el proceso padre. Todo fue bien. Terminamos\n"); pvm_exit(); return 0; } Envo de mensajes MAESTRO #include <stdio.h> #include <stdlib.h> #include <pvm3.h> int main() { int tid, parent_tid; int temporal; tid=pvm_mytid(); parent_tid=pvm_parent(); if (tid < 0) { printf("No puedo conectarme con PVM\n"); pvm_exit(); return -1; } if(pvm_recv(parent_tid, 2) < 0) { printf("Error al recibir datos, fin"); pvm_exit(); return -1; } if(pvm_upkint(&temporal, 1, 1) < 0) { printf("Error al leer el primer dato de buffer y fin\n"); pvm_exit(); return -1; } printf("Soy el hijo %d y he recibido de %d lo siguiente: %d\n", tid, parent_tid, temporal); pvm_exit(); return 0; } Envo de mensajes HIJO

27

5.5.3 Uso de grupos


#include <stdio.h> #include <stdlib.h> #include <pvm3.h> int main() { int tid, tid_grupo; int Hijos[2]; int temporal; /* Conectando con PVM */ tid=pvm_mytid(); if (tid < 0) { printf("No puedo conectarme con PVM\n"); return -1; } /* Soy el padre. Creo el Grupo de nombre CyP */ if (pvm_joingroup("CyP") < 0) { printf("ERROR al crear el padre el grupo de nombre CyP\n"); pvm_exit(); return -1; } /* guardo mi tid en el grupo. Soy el padre luego se que es 0 */ tid_grupo= pvm_getinst("CyP", tid); if (pvm_spawn("grupos-hijo", NULL, PvmTaskDefault, 0, 2, Hijos) != 2) { printf("ERROR lanzando la ejecucion de los procesos hijo\n"); pvm_lvgroup("CyP"); pvm_exit(); return -1; } printf("Soy el proceso padre. Voy a enviar un entero a cada hijo\n"); /* Sincronismo de entrada con el grupo. Andes de cualquier operacion con el grupo conviene estar seguros de que todos los procesos del grupo han conseguido unirse correctamente. En nuestro caso somos */ /* 3: el padre y dos hijos */ if ( pvm_barrier("CyP", 3) < 0) { printf("Problemas en el Padre en sincronismo de entrada al grupo\n"); pvm_lvgroup("CyP"); pvm_exit(); return -1; } /* Inicializando el buffer */ if (pvm_initsend(PvmDataDefault) < 0) { printf("Problemas en el Padre al inicializar el buffer\n"); pvm_lvgroup("CyP"); pvm_exit(); return -1; } /* Colocando la informacion en el buffer */ temporal=1; if (pvm_pkint(&temporal, 1, 1) < 0) { printf("Problemas en el Padre al manipular el buffer\n"); pvm_lvgroup("CyP"); pvm_exit(); return -1; } /* Envio la informacion a un hijo */ if (pvm_send(pvm_gettid("CyP", 1), 2) < 0) { printf("Problemas en el Padre al enviar el buffer al hijo 1\n"); pvm_lvgroup("CyP"); pvm_exit(); return -1;

28

} if (pvm_send(pvm_gettid("CyP", 2), 2) < 0) { printf("Problemas en el Padre al enviar el buffer al hijo 2\n"); pvm_lvgroup("CyP"); pvm_exit(); return -1; } printf("Soy el proceso padre. Todo fue bien. Terminamos\n"); /* Sincronismo de salida con el grupo. Andes de abandonar el grupo conviene estar seguros de que todos las operaciones entre procesos del grupo han concluido correctamente. */ if (pvm_barrier("CyP", 3) < 0) { printf("Problemas en el Padre en sincronismo de salida de grupo\n"); pvm_lvgroup("CyP"); pvm_exit(); return -1; } /* Notifico a PVM que abandono el grupo */ pvm_lvgroup("CyP"); /* Notifico a PVM que abandono la maquina virtual */ pvm_exit(); return 0; } Uso de grupos MAESTRO #include <stdio.h> #include <stdlib.h> #include <pvm3.h> int main() { int tid, parent_tid, tid_grupo; int temporal; tid=pvm_mytid(); parent_tid=pvm_parent(); if (tid < 0) { printf("No puedo conectarme con PVM\n"); pvm_exit(); return -1; } /* Soy un hijo. Me uno al grupo de nombre CyP */ if (pvm_joingroup("CyP") < 0) { printf("ERROR al unise al grupo CyP un hijo\n"); pvm_exit(); return -1; } /* guardo mi tid en el grupo */ tid_grupo= pvm_getinst("CyP", tid); printf("Soy un hijo. Mi ID en PVM es %d y mi ID en el grupo %d\n", tid, tid_grupo); /* /* /* /* if Sincronismo de entrada con el grupo. Andes de cualquier operacion */ con el grupo conviene estar seguros de que todos los procesos del */ grupo han conseguido unirse correctamente. En nuestro caso somos */ 3: el padre y dos hijos */ (pvm_barrier("CyP", 3) < 0) { printf("Problemas en un hijo en sincronismo de entrada al grupo\n"); pvm_lvgroup("CyP"); pvm_exit(); return -1;

} if(pvm_recv(pvm_gettid("CyP", 0), 2) < 0) { printf("Error al recibir datos, fin"); pvm_exit(); return -1;

29

} if(pvm_upkint(&temporal, 1, 1) < 0) { printf("Error al leer el primer dato de buffer y fin\n"); pvm_exit(); return -1; } printf("Soy el hijo %d y he recibido de %d lo siguiente: %d\n", tid, parent_tid, temporal); /* Sincronismo de salida con el grupo. Andes de abandonar el grupo conviene estar seguros de que todos las operaciones entre procesos del grupo han concluido correctamente. */ if (pvm_barrier("CyP", 3) < 0) { printf("Problemas en un hijo en sincronismo de salida de grupo\n"); pvm_lvgroup("CyP"); pvm_exit(); return -1; } /* Notifico a PVM que abandono el grupo */ pvm_lvgroup("CyP"); pvm_exit(); return 0; } Envo de mensajes ESCLAVO

30

5.5.4 Informacin de la PVM


#include <stdio.h> #include "pvm3.h" #define USO "infor n" #define MAX_TAREAS 10 #define MUERTO 10 int main (int argc, char* argv[]) { int mytid, myparent; struct pvmhostinfo *PVM; struct pvmtaskinfo *taskp; int info, i, nhost, narch, j, ntask, tareas_lanzadas, datos, buffer; int array_tids[MAX_TAREAS]; int tareas = 3; mytid = pvm_mytid(); myparent = pvm_parent(); if (myparent == PvmNoParent) { /* Soy el padre */ if (argc == 2) tareas = atoi (argv[1]); if ((tareas < 1) || (tareas > MAX_TAREAS)) { pvm_exit (); printf ("\nError: Nmero de tareas debe ser mayor de 1 y menor de %d\n", MAX_TAREAS); exit (0); } info = pvm_config( &nhost, &narch, &PVM); printf ("\nNmero de nodos que componen la PVM: %d\n", nhost); printf ("Tipos de arquitecturas que componen la PVM: %d\n", narch); tareas_lanzadas = pvm_spawn (argv[0], (char**)0, PvmTaskDefault, 0, tareas, array_tids); printf ("Tareas PVM lanzadas con xito: %d\n", tareas_lanzadas); if (tareas_lanzadas == 0) { pvm_exit (); exit (-1); } for (i = 0; i < tareas_lanzadas; i++) printf ("\tTID %d: %x.\n", (i+1), array_tids[i]); for (i = 0; i < nhost; i++) { printf("\nNodo %d: DTID:%x", i+1,PVM[i].hi_tid); printf ("\n\tNombre: %s", PVM[i].hi_name); printf ("\n\tARQ: %s\n", PVM[i].hi_arch); info = pvm_tasks(PVM[i].hi_tid, &ntask,&taskp); printf("\tTareas PVM: %d\n\n", ntask); for (j = 0; j < ntask; j++) { printf("\t\tTID tarea: %x\n",taskp[j].ti_tid); printf("\t\tTID tarea padre: %x\n",taskp[j].ti_ptid); printf("\t\tTID demonio: %x\n",taskp[j].ti_host); printf("\t\tNombre tarea: %s\n",taskp[j].ti_a_out); } } printf ("\nIniciando el asesinato de las tareas:\n"); pvm_initsend(PvmDataDefault); info = pvm_mcast (array_tids, tareas, 0); if (info < 0) { printf ("\nError al hacer pvm_mcast a las %d tareas.\n", tareas); pvm_exit(); exit(-1); } for (i = 0; i < tareas_lanzadas; i++) { buffer = pvm_recv (-1, MUERTO);

31

pvm_upkint (&datos, 1, 1); printf ("\tTarea %x muerta.\n", datos); } pvm_exit(); exit (0); } /* Soy el hijo */ buffer = pvm_recv (myparent, -1); pvm_initsend (PvmDataDefault); pvm_pkint (&mytid, 1, 1); pvm_send (myparent, MUERTO); pvm_exit (); exit (0); } Informacin de la PVM

32

5.5.5 Producto escalar de dos vectores


#include <stdio.h> #include <stdlib.h> #include "pvm3.h" #define USO "padre_pe longitud_de_los_vectores" #define ESCLAVO "hijo_pe" int main(int argc, char *argv[]) { int i, info, Nlocal, narch, N_NODOS; int mytid = pvm_mytid(); int N = atoi(argv[1]); int *array_tids; struct pvmhostinfo *hostp; double *vector_a, *vector_b, producto_escalar; pvm_config(&N_NODOS, &narch, &hostp); printf("La mquina PVM est compuesta por %d computadores\n", N_NODOS); array_tids = (int *)malloc(N_NODOS * sizeof(*array_tids)); Nlocal = (float)(N + N_NODOS - 1) / N_NODOS; N = Nlocal * N_NODOS; vector_a= (double *)malloc (N * sizeof (*vector_a)); vector_b= (double *)malloc (N * sizeof (*vector_b)); for (i = 0; i < N; i++) { vector_a[i] = rand() / (float)RAND_MAX; vector_b[i] = rand() / (float)RAND_MAX; } info = pvm_spawn (ESCLAVO, (char **)0, PvmTaskDefault, 0, N_NODOS, array_tids); /* Envo de la informacin a los esclavos */ for (i = 0; i < N_NODOS; i++) { pvm_initsend (PvmDataDefault); pvm_pkint (&Nlocal, 1, 1); pvm_pkdouble (&vector_a[i * Nlocal], Nlocal, 1); pvm_pkdouble (&vector_b[i * Nlocal], Nlocal, 1); pvm_send (array_tids[i], 1000); } /* Recepcin de resultados parciales y suma total */ producto_escalar = 0; for (i = 0; i < N_NODOS; i++) { double suma_parcial = 0; pvm_recv (-1, 2000); pvm_upkdouble (&suma_parcial, 1, 1); producto_escalar += suma_parcial; } printf("Longitud vectores= %d\n",N); printf ("Vector A: "); for (i=0; i < N; i++) printf (" %f", vector_a[i]); printf ("\nVector B: "); for (i=0; i < N; i++) printf (" %f", vector_b[i]); printf("\nProducto escalar= %f con N_NODOS= %d\n", producto_escalar, N_NODOS); free (vector_a); free (vector_b); free (array_tids); pvm_exit(); exit (0); } Producto escalar de dos vectores PADRE #include "pvm3.h"

33

int main(void) { int I, Nlocal, padre; double *vector_a, *vector_b, suma_parcial; /* Recepcin de los datos del padre */ padre = pvm_parent (); pvm_recv (padre, 1000); pvm_upkint (&Nlocal, 1, 1); vector_a = (double *)malloc( Nlocal * sizeof(*vector_a)); vector_b = (double *)malloc( Nlocal * sizeof(*vector_b)); pvm_upkdouble (vector_a, Nlocal, 1); pvm_upkdouble (vector_b, Nlocal, 1); /* Clculo de la suma parcial */ suma_parcial = 0; for ( i = 0; i < Nlocal; i++) suma_parcial += vector_a[i] * vector_b[i]; /* Envo de resultado al maestro */ pvm_initsend (PvmDataDefault); pvm_pkdouble (&suma_parcial, 1, 1); pvm_send (padre, 2000); free(vector_a); free(vector_b); pvm_exit(); return 0 } Producto escalar de dos vectores HIJO

34

5.5.6 Producto de dos matrices cuadradas


#include <stdio.h> #include <stdlib.h> #include "pvm3.h" #define #define #define #define #define USO "mul_mat M" GRUPO "MUL" ETI_DATOS 1000 ETI_REPARTO 2000 ETI_RECOGIDA 3000

int main(int argc, char *argv[]) { int i, j, k, m, info, N_TAREAS, N_MEZCLA, instancia, N = 3; int *matriz_a, *matriz_b, *matriz_c, *mezcla, *mezcla_resultados, *array_tids, *fila_columna; int elemento[3]; if (pvm_parent () == PvmNoParent) { instancia = pvm_joingroup (GRUPO); if (argc > 1) N = atoi(argv[1]); N_TAREAS N_MEZCLA matriz_a matriz_b matriz_c mezcla = = N*N-1; = 2 * (N*N*N + N*N); = (int *)malloc(N * N * sizeof(int)); = (int *)malloc(N * N * sizeof(int)); = (int *)malloc(N * N * sizeof(int)); (int *)malloc(N_MEZCLA * sizeof(int));

mezcla_resultados = (int *)malloc(3 * N * N * sizeof(int)); array_tids = (int *)malloc(N_TAREAS * sizeof(int)); for (i=0; i<N*N; i++) { matriz_a[i] = (rand()/(float) RAND_MAX) * 10; matriz_b[i] = (rand()/(float) RAND_MAX) * 10; } k = 0; for (i=0; i<N; i++) { for (j=0; j<N; j++) { mezcla[k] = i+1; k++; for (m=0; m<N; m++) { mezcla[k] = matriz_a[i*N+m]; k++; } mezcla[k] = j+1; k++; for (m=0; m<N; m++) { mezcla[k] = matriz_b[m*N+j]; k++; } } } printf ("Matriz A:\n"); for (i=0; i<N; i++) { for (j=0; j<N; j++) printf ("\t%d", matriz_a[i*N+j]); printf ("\n"); } printf ("Matriz B:\n"); for (i=0; i<N;i++) { for (j=0; j<N; j++) printf ("\t%d",matriz_b[i*N+j]); printf ("\n"); } info = pvm_spawn (argv[0], (char **)0, PvmTaskDefault, 0, N_TAREAS, array_tids); printf ("\nEjecutndose %d tareas ms el padre. Total: %d.\n", info, info+1);

35

if (info != N_TAREAS) { pvm_perror ("No se han creado todas las tareas.\n"); pvm_lvgroup (GRUPO); pvm_halt (); return -1; } pvm_initsend (PvmDataDefault); pvm_pkint (&N, 1, 1); pvm_mcast (array_tids, N_TAREAS, ETI_DATOS); pvm_barrier (GRUPO, N_TAREAS+1); info = pvm_scatter(fila_columna, mezcla, 2*(1+N), PVM_INT, ETI_REPARTO, GRUPO, instancia); elemento[0] = fila_columna[0]; elemento[1] = fila_columna[N+1]; elemento[2] = 0; for (i=0 ; i<N; i++) elemento[2] += fila_columna[i+1] * fila_columna [i+2+N]; info = pvm_gather (mezcla_resultados, elemento, 3, PVM_INT, ETI_RECOGIDA, GRUPO, instancia); for (i=0; i<3*N*N; i=i+3) { j = N * (mezcla_resultados[i]-1) + (mezcla_resultados[i+1]-1); matriz_c[j] = mezcla_resultados [i+2]; } printf ("Matriz C:\n"); for (i=0; i<N; i++) { for (j=0; j<N; j++) printf ("\t%d", matriz_c[i*N+j]); printf ("\n"); } pvm_barrier (GRUPO, N_TAREAS+1); } else { /* Soy el hijo */ pvm_joingroup (GRUPO); pvm_recv (pvm_parent(), ETI_DATOS); pvm_upkint (&N, 1, 1); N_TAREAS = N * N; N_MEZCLA = 2 * (N * N * N + N * N); fila_columna = (int *)malloc ( 2*(1+N) * sizeof(int)); pvm_barrier (GRUPO, N_TAREAS); info = pvm_scatter(fila_columna, 0, 2*(N+1), PVM_INT, ETI_REPARTO, GRUPO, pvm_getinst(GRUPO, pvm_parent())); elemento[0] = fila_columna[0]; elemento[1] = fila_columna[N+1]; elemento[2] = 0; for (i=0 ; i<N; i++) elemento[2] += fila_columna[i+1] * fila_columna [i+2+N]; info = pvm_gather (0, elemento, 3, PVM_INT, ETI_RECOGIDA, GRUPO, pvm_getinst(GRUPO, pvm_parent())); pvm_barrier (GRUPO, N_TAREAS); } pvm_lvgroup (GRUPO); pvm_exit(); exit(0); } Producto de dos matrices cuadradas

36

Das könnte Ihnen auch gefallen