next up previous
Next: Exemplo Up: Máquina Paralela Virtual (PVM) Previous: Introdução


Ambiente

Apresentação

A escolha do PVM como plataforma para o desenvolvimento de aplicações e instrumento pedagógico beneficia do facto de ser um dos ambientes de programação paralela mais usado actualmente, simples de instalar e utilizar. O suporte oferecido pelos seus autores tem-se traduzido em constantes actualizações, resultantes da evolução natural de um produto, acessível livremente, e das críticas e sugestões de um leque variado de utilizadores.

O ambiente de programação PVM é constituído por um conjunto de utensílios que dão facilidades aos utilizadores para monitorizar, corrigir e melhorar o desempenho das aplicações:

Características do PVM

O PVM não é apenas uma biblioteca de funções de comunicação para troca de mensagens. Uma parte importante do suporte lógico é dedicado à gestão de processos, das tarefas e de sinais na máquina virtual. Uma parte dessa gestão é assegurada pelo servidor pvmd.

As funções de administração dão ao utilizador a capacidade de gerir totalmente a programação da máquina permitindo a detecção de falhas dos computadores na rede, a criação dinâmica de grupos e a recuperação de falhas.

$\diamond$ Identificação

Em PVM todas as tarefas são identificadas por um inteiro TID escolhido pelo pvmd local que as representa de uma maneira única na máquina virtual. Uma tarefa pode ser também identificada por um nome de grupo e um número representando a sua posição no grupo.

Para obter a sua identificação a tarefa pode usar-se as funções pvm_mytid() e pvm_gettid() que retornam respectivamente a identificação global ou no grupo.

$\diamond$ Controlo de Processos

O PVM possui funções que tornam possível, a todo o momento, um processo (Unix) registar-se ou desassociar-se da máquina virtual. A administração da própria máquina virtual faz-se através de outras funções que alteram a constituição da máquina virtual, juntando ou retirando computadores acessíveis na rede.

A consola PVM é um interface com o utilizador para a gestão e monitorização das aplicações na máquina virtual. As tarefas de administração podem ser realizadas por qualquer tarefa na aplicação recorrendo às mesmas funções que a consola.

$\diamond$ Tolerância às falhas

A falha de qualquer computador ( excluindo o mestre) ou a perda de acessibilidade é detectada automaticamente pelo PVM que o retira do conjunto de máquinas que constituem a MV. Qualquer utilizador pode conhecer o estado da MV, mas a tolerância às falhas cabe ao programador que deverá prever essas situações por forma a desencadear os mecanismos que tornem possível a recuperação.

$\diamond$ Gestão Dinâmica de grupos

Durante a execução de uma aplicação as tarefas podem dinamicamente juntar-se ou retirar-se de grupos, não havendo qualquer limite para o número de grupos a que uma tarefa pode pertencer.

$\diamond$ Envio de Sinais

Em PVM há duas formas diferentes de uma tarefa enviar sinais às outras tarefas na aplicação. A primeira replica o mecanismo utilizado em Unix para o envio e recepção de sinais entre processos. A segunda é um mecanismo independente gerido pelo servidor pvmd que consiste no envio de avisos sob a forma de um valor inteiro a que se cola uma etiqueta.

Actualmente o PVM emite um aviso sempre que há alteração da máquina virtual por entrada ou saída de um computador ou quando uma tarefa termina.

$\diamond$ As rotinas de comunicação

O modelo de comunicação assume que uma tarefa pode enviar mensagens a qualquer outra tarefa, na máquina virtual, não havendo limites para o tamanho das mensagens.

Os modos de comunicação em PVM incluem a emissão bloqueante assíncrona, a recepção bloqueante assíncrona e a recepção não bloqueante. Na terminologia do PVM a emissão bloqueante liberta a tarefa emissora imediatamente após o tampão de memória da mensagem ficar livre. O assincronismo caracteriza as operações de emissão porque as tarefas não têm de esperar que seja lançada pela tarefa receptora a operação correspondente de recepção. Opcionalmente é permitido transferir directamente dados entre tarefas. Neste caso, se a mensagem for grande, o emissor bloqueia até que a transferência termine.

Em recepção não bloqueante a operação retorna imediatamente o valor da mensagem ou um sinal que permite determinar se a mensagem já está disponível. No caso da recepção bloqueante a tarefa fica literalmente suspensa até que a mensagem seja completamente depositada no tampão. Uma rotina suplementar permite a obtenção de informação sobre a própria mensagem, p.e. a identificação da tarefa emissora e da etiqueta da mensagem.

Para além dos modos de comunicação ponto a ponto, o modelo inclui ainda a difusão entre os elementos de um grupo e a difusão parcial para um conjunto de processos seleccionáveis pelo utilizador. As rotinas para comunicação alargada permitem também operações de cálculo global e redução, tais com a soma o máximo e mínimo.

$\diamond$ Sequência

O PVM garante que não há perda de sequência de mensagens, isto é, se a tarefa 1 envia a mensagem A à tarefa 2, seguida de uma outra mensagem B à mesma tarefa, então A precede B na tarefa 2. Além disso se as duas mensagens chegarem à tarefa 2 antes que esta inicie a operação complementar correspondente, então a recepção em 2 retornará sempre a mensagem A.

Os tampões de memória são alocados dinamicamente sendo o tamanho máximo de cada mensagem, a enviar ou a receber, limitado apenas pelo quantidade de memória disponível em cada computador.

$\diamond$ MPP

Construtores e investigadores têm vindo a desenvolver diferentes realizações do PVM para a maior parte da máquinas paralelas reais existentes, permitindo, desta forma, que uma mesma aplicação desenvolvido em PVM possa correr directamente em várias plataformas. A troca de mensagens entre os vários nodos de qualquer uma dessas máquinas faz-se, a alta velocidade, através das redes de comunicação nativas.

Nestas máquinas servidor pvmd é substituído por um mecanismo equivalente que se encarrega do encaminhamento das mensagens escrito e das tarefas de gestão de tarefas locais.

Interface

Apresentamos em seguida um resumo das principais rotinas da biblioteca PVM 3.3. A lista completa, organizada por ordem alfabética, pode ser encontrado no Apêndice B do documento de referência do PVM. A descrição de cada rotina inclui os parâmetros, os possíveis códigos de retorno e exemplos de aplicação escritos em linguagem C.

Controlo de Processos

 $$
int tid
pvm_mytid(void)

 $$
int tid
pvm_parent(void)

A rotina pvm_mytid é utilizada normalmente para registar o processo na máquina virtual e obter a respectiva identificação. O valor de retorno da rotina pvm_parent é a identificação da tarefa que lançou a tarefa actual. No caso desta não ter sido lançada através da primitiva pvm_spawn o valor de retorno é PVMNOPARENT.

 $$
int info
pvm_kill(tid)
int tid;

 $$
int info
pvm_exit(void)

As tarefas podem naturalmente desassociar-se da máquina virtual pvm_exit ou serem forçadas a terminar por uma outra tarefa recorrendo á primitiva pvm_kill.

 $$
int numt
pvm_spawn(file, argv, flags, where, count, tids)
char *file;
char **argv;
int flags;
char *where;
int count;
int *tids;

A rotina pvm_spawn lança count cópias de um programa FILE na máquina virtual. O parâmetro argv é um apontador para uma lista de argumento a entregar ao programa. A condição FLAG é usada para especificar um conjunto de opções descritos no ficheiro de inclusão pvm3.h.


Tabela 2.1: Opções de lançamento de tarefas.
Valor Opção Significado
0 PvmTaskDefault é o PVM que decide onde lançar as tarefas
1 PvmTaskHost o argumento WHERE é o nome de um computador
2 PvmTaskArch o argumento WHERE é o nome de uma arquitectura
4 PvmTaskDebug a execução das tarefas é monitorizada
8 PvmTaskTrace a execução gera traçados
16 PvmTaskMppFront tarefas lançadas num computador MPP
32 PvmTaskHostCompl complementa o conjunto computadores em WHERE


O valor NUMT de retorno da função determina o número de tarefas lançadas com sucesso ou contém um código de erro no caso não ter sido lançada nenhuma tarefa. A lista TIDS contém os identificadores globais de cada uma das tarefas laçadas com sucesso, para as tarefas que não poderem ser lançadas é obtido um código de erro que indica as razões de insucesso, colocado nas posições COUNT-NUMT da lista.

 $$
int info
pvm_catchout(file)
FILE *file;

A saída dados é normalmente dirigida para o diário em ficheiro /tmp/pvm.l<uid> , a rotina pvm_catchout() permite que a tarefa capture a saída de dados das tarefas descendentes. Todos os caracteres enviados para o stdout e stderr são colectadas pelo servidor local e enviadas sob a forma de mensagens de controlo para as tarefas progenitoras que são por sua vez ser registadas no diário. Cada linha do diário contém informação que permite identificar a tarefa que produziu essa informação. A tarefa ascendente é fica bloqueada se tentar terminar ter colectado totalmente as saída de dados, dos descendentes. Para evitar esta situação a tarefa deverá executar a rotina pvm_catchout(0) antes de terminar.

Informação

 $$
int
pvm_mstat(host)
char *host;

 $$
int
pvm_pstat(tid)
int tid;

Estas duas rotinas permitem conhecer o estado dos computadores e das tarefas na máquina virtual. Com base nestas rotinas o utilizador pode conhecer, em cada, os computadores na configuração, ou saber se uma tarefa está bloqueado.

 $$
int
pvm_tidtohost(tid)
int tid;

 $$
int
pvm_config(nhostp, narchp, hostp)
int *nhostp;
int *narchp;
struct pvmhostinfo **hostp;

A identificação do servidor dTID local, valor de retorno da função pvm_tidtohost, pode ser utilizada para dar a conhecer á tarefa o nome do computador em que está a ser executada. Informação mais detalhada pode ser obtida usando a função pvm_config que dá a conhecer o número de computadores na máquina virtual nhostp, e os diferentes formatos de dados NARCH. A variável hostp é um apontador para uma lista de estruturas do tipo PVMHOSTINFO. Cada uma destas estruturas contém o dTID do servidor, o nome do computador, o nome da arquitectura e a velocidade relativa do computador na máquina virtual.

 $$
int
pvm_tasks(which, ntaskp, taskp)
int wich;
int *ntaskp;
struct pvmtaskinfo **taskp;

Informação sobre todos as tarefas na máquina virtual pode ser obtida usando a rotina pvm_tasks. O parâmetro which nomeia as tarefas sobre as quais se pretende obter informação. O parâmetro terá o valor (0) para significar todas as tarefas, ou (TID) para particularizar a tarefa. O valor de retorno de NTASk representa o número de tarefas e TASKPé um apontador para uma lista de estruturas PVMTASKINFO. Cada uma destas estruturas contém o TID da tarefa, do progenitor e do servidor local, o nome do programa executável e uma indicação de estado.

Configuração Dinâmica

 $$
int info
pvm_addhosts(hosts, nhosts, svp)
char **hosts;
int nhosts;
int *svp;

 $$
int info
pvm_delhosts(hosts, nhosts, svp)
char ** hosts;
int nhosts;
int *svp;

Estas rotinas são usadas para alterar a máquina virtual juntando pvm_addhosts ou removendo pvm_delhosts computadores. O valor de retorno info contém o número de computadores que satisfizeram a operação requerida e o parâmetro SVP é uma lista de comprimento NHOSTS onde se pode obter o código de cada computador. Estas rotinas são particularmente úteis na definição da configuração inicial da máquina virtual, mas são mais normalmente usadas para aumentar a flexibilidade e as capacidades de tolerância às falhas de uma aplicação. Por exemplo sempre que é detectada a falha de um computador a rotina pvm_addhost permite substituí-lo por outro computador disponível na rede.

Sinais

 $$
int info
pvm_sendsig(tid, signum)
int tid;
int signum;
 $$
int info
pvm_notify(what, msgtag, count, tids)
int what;
int msgtag;
int count;
int *tids;

A rotina pvm_sendsig envia um sinal SIGNUM a uma tarefa TID como se tratasse de um processo Unix. Outros sinais, específicos do PVM, podem ser gerados para avisar uma tarefa da ocorrência de situações particulares de acordo com as seguintes opções:


Tabela 2.2: Tipos de notificação.
PvmTaskExit uma tarefa terminou
PvmHostDelete um computador removido
PvmHostAdd um computador acrescentado


Em resposta a um pedido de notificação pvm_notify o servidor PVMD envia á tarefa requerente uma mensagem com uma etiqueta igual á especificada em MSGTAG. O parâmetro TIDS é usado em caso de alteração da configuração da máquina virtual indicando as tarefas que deverão ser notificadas nesse caso.

Definição de Opções

 $$
int oldval
pvm_setopt(what, val)
int what;
int val;

 $$
int val
pvm_getopt(what)
int what;

Estas rotinas incluem um leque variado de opções que permitem especificar ou mostrar opções específicas que contemplam a geração automática de avisos de erro, definição de opções de depuração ( debug) ou de modos de comunicação, que condicionam a execução das rotinas evocadas posteriormente. Em ambas as rotinas o parâmetro WHAT pode assumir os seguintes valores:


Tabela 2.3: Opções gerais.
1 PvmRoute política de encaminhamento P/D/N
2 PvmDebugMask nível de monitorização  
3 PvmAutoErr relato automático de erros 1/0
4 PvmOutputTid saída de dados para os filhos TID (0)
5 PvmOutputCode etiqueta para saída de dados recepção
6 PvmTraceTid receptor dos traçados dos filhos tarefa responsável
7 PvmTraceCode etiqueta para traçados recepção
8 PvmFragSize tamanho dos fragmentos octetos
9 PvmResvTids etiquetas reservadas 1/0
10 PvmSelfOutputTid    
11 PvmSelfOutputCode    
12 PvmSelfTraceTid    
13 PvmSelfTraceCode    


Por exemplo pvm_setopt (PvmRoute, PvmRouteDirect) especifica que a comunicação é por encaminhamento directo de mensagens o que se traduz normalmente na duplicação da a velocidade de transferência. A contrapartida é que este mecanismo de comunicação poderá não ser aplicável em Unix, se aplicação envolver um grande número de tarefas que comunicam aleatoriamente entre si. Quando não tem condições para garantir o encaminhamento directo o PVM comuta automaticamente para o modo normal.

Passagem de Mensagens

O envio de mensagens em PVM compreende os passos que a seguir descrevemos, podendo o receptor aceitar mensagens de qualquer remetente e qualquer código de etiquetagem.

  1. alocação de um tampão de memória
  2. empacotamento no tampão da informação a enviar;
  3. envio da mensagem no tampão

A comunicação por troca de tampões de memória tem vantagens significativas que decorrem da facilidade com que podem ser incorporados mecanismos de comunicação de alta-velocidade em ambientes heterogéneos, ou a possibilidade de constituição de dados estruturados e respectivo empacotamento e desempacotamento.

O controlo de fluxo em PVM é assegurado pelo servidor pvmd que garante que as mensagens enviadas irão ser entregues mesmo que não tenha sido, até ao momento iniciada qualquer operação de recepção. O controlo de fluxo é efectivo enquanto houver recursos de memória até que o receptor por sua vez inicie o processo de recepção alocando uma área de memória tampão que possa conter a mensagem.

A perda de sequência na mensagens é ultrapassada graças a definição da mensagem como uma tuplo < emissor, informação, código de etiquetagem>.

Memória tampão

 $$
int bufid
pvm_initsend(enc) ou pvm_mkbuf(enc)
int enc;

 $$
int info
pvm_freebuf(bufid)
int bufid;

Estas rotinas servem para manipular os tampões de memória usados durante as transferências de dados. Em PVM há, em cada momento, apenas um tampão de memória activo. Na maior parte dos casos é apenas utilizada a rotina pvm_initsend que cria ou reinicia o tampão de memória activo para envio.

As funções pvm_mkbuf e pvm_freebuf, servem respectivamente para criar e recuperar, tampões de memória, nos casos em que o utilizador tem necessidade de múltiplos tampões. Esta última rotina que deverá ser evocada imediatamente após uma mensagem ser enviada, liberta o tampão BUFID.

A rotina pvm_initsend tem uma dupla acção equivalente a evocação das rotinas pvm_mkuf e pvm_freebuf.

A criação de um novo tampão pressupõe a definição do modelo de codificação dos dados ENC. Em PVM estão disponíveis os seguintes métodos de codificação:

Esta última opção reduz o número de vezes que a mensagem que ser copiada. Em contrapartida o utilizador não poderá alterar a informação em memória até que os dados sejam efectivamente enviados.

Múltiplos tampões

 $$
int oldbuf
pvm_setrbuf(bufid) ou pvm_setsbuf(bufid)
int bufid;
 $$
int bufid
pvm_getsbuf(void) ou pvm_getrbuf(void)

As operações de envio ou recepção de empacotamento ou de desempacotamento afectam exclusivamente o tampão de memória activo no momento. No entanto, é possível criar vários tampões, enchê-los com dados diferentes e activá-los, em qualquer ordem, através das funções pvm_setsbuf ou pvm_setrbuf. Se o BUFID tiver o valo (0) então o tampão corrente é desactivado e o valor de retorno é o tampão previamente activo. As rotinas pvm_getsbuf e pvm_getrbuf retornam, respectivamente, os tampões activos de envio e de recepção.

É possível reencaminhar mensagens sem ser necessário reempacotá-las como se ilustra no exemplo:

bufid = pvm_rec(src, tag);
oldid = pvm_setsbuf(bufid);
info = pvm_send(dst, tag);
info= pvm_freebuf(oldid);

Empacotamento

As rotinas que a seguir apresentamos servem para encher os tampões com informação a que correspondem tipos de fortes, (reais, inteiros, cadeias de caracteres, ...). Podem ser evocadas múltiplas vezes para empacotar dados numa única mensagem, não havendo limites para a complexidade da informação contida numa única mensagem. Tem, apenas, de se garantir que as tarefas nas aplicações deverão desempacotar as mensagens utilizando as operações recíprocas.

 $$
int info

pvm_pkbyte(vx, nitem, stride), pvm_short, pvm_pkcplx, pvm_pkdouble, pvm_pkfloat, pvm_pkint, pvm_pklong, pvm_pkstr
tipo *vx;
int nitem;
int stride;

O primeiro argumento de cada uma destas rotinas VX é um apontador para o primeiro elemento do tipo de dados correspondente, NITEM refere o número de itens e STRIDE a extensão do tipo usada para empacotamento.

 $$
int info
pvm_packf(const char *fmt, ...)

Esta última rotina usa o estilo printf da linguagem C, para especificar os dados a empacotar e a forma como deverá ser efectivado o empacotamento.

Desempacotamento

A uma operação de empacotamento na emissão deverá corresponder a operação de desempacotamento inversa na recepção, que definirá o mesmo tipo de dados, o mesmo número de itens e idêntica extensão.

 $$
int info
pvm_upbyte(vx, nitem, stride), pvm_short, pvm_upcplx, pvm_updouble, pvm_upfloat, pvm_upint, pvm_uplong, pvm_upstr
tipo *vx;
int nitem;
int stride;

 $$
int info
pvm_unpackf(const char *fmt, ...)

Esta última rotina usa o estilo printf da linguagem C, da mesma forma que a correspondente a operação inversa pvm_packf para especificar os dados a desempacotar e a forma como deverá ser efectivado o desempacotamento.

Envio de Mensagens

 $$
int info
pvm_send(tid, msgtag)
int tid;
int msgtag;

 $$
int info
pvm_mcast(tids, ntask, msgtag)
int *tids;
int ntask;
int msgtag;

Para enviar uma mensagem pode usar-se a primitiva pvm_send e precisar o número TID de identificação do processo receptor mas, também, é necessário colar uma etiqueta mstag á mensagem.

A rotina pvm_mcast distingue-se da anterior na medida em que permite um envio personalizado de uma mesma mensagem a NTASK tarefas receptoras, com excepção de si própria, especificadas em TIDS.

 $$
int info
pvm_psend(tid, mstag, vp, cnt, type)
int tid;
int mstag;
void *vp;
int cnt;
int type;

Esta última rotina empacota e envia uma mensagem a uma lista de itens VP do tipo TYPE para a tarefa TID.

Recepção de Mensagens

 $$
int bufid
pvm_recv(tid, mstag), pvm_nrecv, pvm_probe
int tid;
int mstag;
O PVM disponibiliza vários métodos de recepção de mensagens, pvm_recv é uma função de recepção bloqueante. Enquanto a mensagem não for completamente recebida a tarefa receptora permanece bloqueada à espera.

Para evitar esta situação de espera e ganhar em eficácia, o PVM oferece as rotinas pvm_probe e pvm_rec que testam a chegada de uma nova mensagem que corresponda aos parâmetros da evocação. Em caso afirmativo, ambas as rotinas retornam a identificação do tampão que irá conter ou contém a mensagem. No primeiro caso a mensagem é efectivamente carregada no tampão, enquanto no segundo caso, para obter a mensagem torna-se necessário a evocação da rotina bloqueante pvm_rec.

 $$
int info
pvm_bufinfo(bufid, bytes, msgtag, tid)
int bufid;
int * bytes;
int * msgtag;
int *tid;

Ambas as rotinas a partir do momento que detectam a chegada de uma mensagem poderão recorrer á rotina pvm_bufinfo para determinar o tamanho BYTES da mensagem e identificar a tarefa emissora TID e a etiqueta MSGTAG associada.

 $$
int bufid
pvm_trecv(tid, mstag, tmout)
int tid;
int mstag;
struct timeval *tmout;

A rotina pvm_trecv, é uma rotina que estabelece a ponte entre a recepção bloqueante e a não bloqueante dando a possibilidade ao utilizador de efectuar uma recepção bloqueante que dura apenas o intervalo de tempo especificado em TMOUT. Esgotado esse tempo, a rotina comprta-se como se fora uma recepção não bloqueante.

Criação de Mensagens Complexas

O PVM oferece a possibilidade de compor mensagens que contêm diferentes tipos de dados:

 $$
envia_serviço(operário, nome, wd, ht, cf)
int operário;
char * nome;
int wd, ht;
double * cf;


{ 
 pvm\_initsend(PvmDataDefault);
 pvm\_pkstr(nome);
 pvm\_pkint(\&wd, 1, 1);
 pvm\_pkdouble(\&ht, 1, 1);
 pvm\_pkdouble(cd, 6);
 pvm\_send(operário, 12);
}

Para obter os diferentes no tampão de recepção é necessário usar as rotinas de recepção e de desempacotamento:

pvm_recv(-1, 12);
pvm_upkstr(nome);
pvm_upint(&wd, 1, 1);
pvm_upint(&wd, 1, 1);
pvm_updouble(cf, 6);

Grupos de Tarefas

 $$
int num
pvm_joingroup(group), pvm_lvgroup pvm_gsize
char *grupo;

Em PVM as rotinas de grupo pretendem ser muito gerais mesmo se desse facto possa resultar perda de eficiência. Em PVM qualquer tarefa pode juntar-se ou retirar-se a qualquer grupo sem que tenha de informar ninguém das ocorrências, ou difundir mensagens para grupos a que não pertence.

A primeira chamada a pvm_joingroup cria o grupo GROUP e junta a tarefa ao grupo. O valor NUM de retorno é a identificação da tarefa nesse grupo. A rotina pvm_lvgroup retira a tarefa do grupo libertando o identificador que possuía que pode voltar a ser atribuído a qualquer outra tarefa que se reuna ao grupo.

A rotina pvm_gsize retorna em cada momento o número de membros do grupo especificado.

 $$
int tid
pvm_gettid(group, inum)
char *group;
int inum;
 $$
int inum
pvm_getinst(group, tid)
char *group;
int tid;

Para obter o TID de uma tarefa identificada por INUM dentro de um grupoGROUp usa-se a rotina utiliza-se a rotina pvm_gettid. A rotina pvm_getinst, oferece a possibilidade de encontrar a identificacão INUm de uma tarefa TID no grupo GROUP.

Comunicação Alargada

 $$
int info
pvm_barrier(group, count)
char *group;
int count;

A evocação de pvm_barrier para um determinado grupo provoca uma suspensão da tarefa até que um número total COUNT de tarefas no mesmo grupo tenha evocado a mesma operação. A utilização do parâmetro COUNT é necessária porque sendo dinâmica tanto a entrada como a saída num grupo, o número de elementos que constitui um grupo é a todo o momento variável.

 $$
int info
pvm_bcast(group, msgtag)
char *group;
int msgtag;

Esta mensagem cola a etiqueta MSGTAG na mensagem que irá difundir para todos os elementos do grupo. Se uma tarefa se junta a um grupo durante a evocação da rotina pvm_bcast, poderá não chegar a receber a mensagem. Na mesma situação, mas no caso de abondono grupo, a tarefa que se retira continuará a receber a mensagem difundida.

 $$
int info
pvm_reduce(fc, data, nitem, datatype, msgtag, group, root)
void (*fc )();
void data;
int nitem;
int datatype;
int msgtag;
char *goup;
int root;

Esta operação global executa um cálculo aritmético global que envolve todos os elementos de um grupo. O resultado da redução é enviado par a tarefa ROOT. Presentemente o PVM disponibiliza quatro funções pré definidas PvmMAx, PvmMin, PvmSum e PvmProduct. Aos utilizadores, é oferecida a possibilidade de escreverem as suas próprias operações de cálculo global.


next up previous
Next: Exemplo Up: Máquina Paralela Virtual (PVM) Previous: Introdução

1999-06-26