• Nenhum resultado encontrado

3 Estruturas de objetos concorrentes

N/A
N/A
Protected

Academic year: 2019

Share "3 Estruturas de objetos concorrentes"

Copied!
44
0
0

Texto

(1)

PROF. LU´ISFERNANDO DE OLIVEIRA

Introduc

¸˜

ao a Linguagem

Charm++

Programac¸˜

ao paralela e distribu´ıda

Universidade do Estado do Rio de Janeiro Centro de Tecnologia e Ciˆencias

Instituto de F´ısica

(2)

1 Vis˜ao geral sobre a linguagem Charm++ 6

1.1 Orientac¸˜ao a objeto e objetos concorrentes . . . 7

1.2 Universo Paralelo . . . 8

1.3 Processamento no Charm++ . . . 9

1.4 Func¸˜oes ´uteis no Charm++ . . . 11

2 Elementos b´asicos da linguagem Charm++ 13 2.1 Objeto sequencial . . . 14

2.2 Objeto concorrente simples . . . 15

2.2.1 mainchare . . . 17

2.2.2 Dados com acessosomente para leitura . . . 18

2.2.3 Passagem de argumentos . . . 20

2.3 Mensagens . . . 25

2.3.1 Mensagem de tamanho fixo . . . 27

2.3.2 Mensagem de tamanho vari´avel . . . 30

2.3.3 Mensagens no modosomente leitura . . . 35

2.3.4 Mensagem de linha de comando . . . 35

3 Estruturas de objetos concorrentes 37 3.1 Lista de objetos concorrentes . . . 37

3.2 Colec¸˜oes de objetos concorrentes . . . 44

3.2.1 Grupos de objetos concorrentes . . . 44

3.2.2 N´os de objetos concorrentes . . . 44

3.3 Callbackereduction. . . 44

(3)

Lista de Figuras

1.1 Caracter´ısticas do Charm++. . . 6 1.2 Troca de mensagens como princ´ıpio de funcionamento do Charm++.. . . 7 1.3 Caracter´ısticas do paradigma da orientac¸˜ao a objeto. . . 8 1.4 Papel do objetoPROXYem relac¸˜ao ao objeto remoto. . . 9 1.5 Noc¸˜ao de grupo de n´os. . . 10

(4)

O Charm++ ´e uma linguagem de programac¸˜ao distribu´ıda baseada no paradigma da orientac¸˜ao a objeto. A sintaxe do Charm++ ´e idˆentica a da linguagem C++. Por vezes, o leitor poder´a se perguntar se o Charm++ ´e realmente uma outra linguagem ou se ´e uma biblioteca que implementa paralelismo e distribuic¸˜ao de processos dada a semelhanc¸a entre ele e o C++. No discurso do grupo1 que desenvolveu o Charm++ encontra-se informac¸˜oes que indicam ambas as opc¸˜oes. O Charm++ ´e uma linguagem superposta `a linguagem C++.

Como poder´a ser constatado ao longo deste material de apoio, a semelhanc¸a n˜ao ´

e mera coincidˆencia. O compiladorcharmc opera como um pr´e-compilador, isto ´e, ele pr´e-processa o c´odigo fonte, introduz uma s´erie de instruc¸˜oes no c´odigo C++ e depois requisita a compilac¸˜ao do c´odigo processado usando o compilador C++ dispon´ıvel.

Independente desta discuss˜ao, ´e fato que o Charm++ hoje ´e uma linguagem ma-dura com suporte para operar em conjunto com outras ferramentas de paralelismo/dis-tribuic¸˜ao de processos como o MPI. Projetos implementados usando Charm++ foram desenvolvidos e executados em supercomputadores de renome (BlueGene).

Uma caracter´ıstica ´ımpar do Charm++ ´e a possibilidade de o desenvolvedor (ana-lista/projetista) resgatar a capacidade de organizar sua l´ogica de programac¸˜ao indepen-dente da arquitetura de processamento paralelo/distribu´ıdo. Tudo se passa como se o projeto estivesse sendo executado no computador do programador.

Outro elemento interessante do Charm++ s˜ao as ferramentas de depurac¸˜ao e avaliac¸˜ao de desempenho. A ferramenta de avaliac¸˜ao de desempenho chamada Projec-tions´e capaz de apresentar, entre outras coisas interessantes, a carga de processamento em cada processador. Para o Charm++, um processador como o Phenom II X4 da AMD ou Core I7 da Intel ´e visto como um pequeno cluster de 4 processadores. Cada n´ucleo ´e utilizado independentemente e pode ser explorado em seu potencial de processamento. Ent˜ao, um programa implementado em Charm++ explora o recurso dispon´ıvel no pro-cessador e exibe isto atrav´es da ferramentaProjections.

Por fim, o Charm++ permite que o analista/projetista simule o comportamento do projeto implementado numa arquitetura que ele n˜ao possui, ou seja, o desenvolvimento do projeto pode ser implementado num sistema computacional que n˜ao possui todas as caracter´ısticas do sistema alvo. Mesmo que o computador utilizado durante o desen-volvimento do projeto possua apenas 4 n´ucleos, o programa compilado em Charm++

1Parallel Programming Laboratory, University of Illinois

(5)

5

pode ser executado com qualquer n´umero de processos que se deseje. ´E ´obvio que a performance nesta simulac¸˜ao cai, mas n˜ao impede que o projeto seja analisado quanto `a l´ogica, ao processo de troca de mensagens, transferˆencias de dados entre processadores e outros aspectos.

Tudo isto torna o Charm++ uma linguagem de destaque. Muitas outras carac-ter´ısticas ser˜ao apresentadas ao longo deste material.

Boa leitura.

(6)

Vis˜

ao geral sobre a linguagem

Charm++

O Charm++ ´e uma linguagem orientada a objetos concorrentes. A execuc¸˜ao de um programa compilado em Charm++ ocorre atrav´es da troca de mensagens entre os objetos concorrentes que comp˜oem a l´ogica da programac¸˜ao (fig. 1.1).

Figura 1.1: Caracter´ısticas do Charm++.

Mas se diferencia das demais ferramentas de paralelismo baseadas em troca de mensagem (fig. 1.2), pois um objeto concorrente s´o inicia a realizac¸˜ao de uma deter-minada tarefa quando este recebe a mensagem enviada. O termo utilizado neste caso ´e dirigido a mensagem (message-driven). Isso caracteriza umaassincronicidade interes-sante, uma independˆencia temporal na execuc¸˜ao das tarefas. ´E natural que a linguagem Charm++ oferec¸a instruc¸˜oes para que a distribuic¸˜ao e o recolhimento dos resultados distribu´ıdos no sistema de processamento ocorra de forma organizada. Por´em, n˜ao ha necessidade de o analista/projetista prever barreiras ou sem´aforos explicitamente no c´odigo fonte.

Por tr´as do Charm++, existe um elemento operando ativamente que ´e o geren-ciador de execuc¸˜ao (Charm++ kernel). Este agente ´e ativado automaticamente na

(7)

7

Figura 1.2: Troca de mensagens como princ´ıpio de funcionamento do Charm++.

carga do programa em Charm++. O gerenciador de execuc¸˜ao monitora continuamente a emiss˜ao de mensagens, intercepta-as e as envia para o objeto concorrente de destino. Fica transparente ao usu´ario o momento em que o gerenciador realizar´a esta tarefa. Por este motivo, o processamento atrav´es do gerenciador de execuc¸˜oes ´e ass´ıncrono e exige do desenvolvedor (analista/projetista) a habilidade de compor sua l´ogica de forma que esta assincronicidade seja aproveitada.

1.1

Orientac

¸˜

ao a objeto e objetos concorrentes

O Charm++ oferece um conjunto de classes de objetos que podem ser utilizados na codificac¸˜ao da l´ogica distribu´ıda. Essencialmente, as classes de objetos dizem respeito a: objetos concorrentes (chare objects, chare array objects, chare group objetcs, chare nodegroup objects), objetos de comunicac¸˜ao (message objects) e objetos “globais” somente para leitura (readonly objects).

Como o Charm++ se superp˜oe `a linguagem C++, todas as caracter´ısticas da programac¸˜ao orientada a objeto suportada pela linguagem C++ s˜ao herdadas pelo Charm++ (fig. 1.3). Logo, os objetos concorrentes do Charm++ s˜ao instˆancias de classes devidamente programadas para suportar o processamento paralelo/distribu´ıdo.

As classes do Charm++ encapsulam atributos e m´etodos, assim como no C++, que podem ser p´ublicos e privados. Os m´etodos p´ublicos das classes de objetos concor-rentes do Charm++ s˜ao chamados de m´etodos de entrada da classe(entry methods) e podem ser invocados remotamente de forma ass´ıncrona. Isto significa que o objeto requerente n˜ao espera pela execuc¸˜ao do m´etodo do objeto remoto e n˜ao espera que o m´etodo retorne um resultado. Logo, os m´etodos de entrada da classe devem se comportar como procedimentos (procedures,subroutines).

(8)

Figura 1.3: Caracter´ısticas do paradigma da orientac¸˜ao a objeto.

referenciar uma informac¸˜ao atrav´es de ponteiros.

1.2

Universo Paralelo

A linguagem Charm++ possui uma caracter´ıstica que representa um diferencial perante as demais ferramentas de programac¸˜ao paralela: ela resgata o controle do de-senvolvedor sobre a l´ogica da programac¸˜ao. A princ´ıpio, isto pode n˜ao parecer sig-nificativo, pois toda programac¸˜ao est´a baseada em l´ogica, seja usando a linguagem Charm++ ou qualquer outra linguagem. A diferenc¸a est´a no fato de o desenvolvedor olhar para sua l´ogica de programac¸˜ao de forma praticamente independente da arquite-tura de computac¸˜ao paralela/distribu´ıda. Em momento algum, como ser´a visto ao longo deste material, o desenvolvedor precisa prever ou determinar que trecho de c´odigo ser´a executado em um processador espec´ıfico. Mais, a codificac¸˜ao completa n˜ao precisa ser clonada em todos os processadores do sistema de computac¸˜ao; somente a tarefa dese-jada ´e executada remotamente. O efeito final ´e que o desenvolvedor olha para sua l´ogica como se tudo se passasse na sua unidade de processamento, no seu computador pessoal, no computador de desenvolvimento, independente dos recursos de arquitetura presen-tes neste (se ´e monoprocessado ou multiprocessado, se os processadores s˜ao sim´etricos, escalares ou vetoriais).

(9)

ge-9

rada pelogerenciador de execuc¸˜ao. Quando o desenvolvedor programa uma troca de mensagens entre dois objetos concorrente no universo virtual, por exemplo a solicitac¸˜ao de execuc¸˜ao de um m´etodo do objeto remoto (virtual), o gerenciador de execuc¸˜ao in-tercepta esta mensagem e replica no universo real, ou seja, o objeto requerente (real) requisita a execuc¸˜ao do mesmo m´etodo do objeto remoto (real).

Os objetos concorrente virtuais s˜ao chamados tecnicamente dePROXY. Este termo ´

e muito comum nos servic¸os de internet e de bancos de dados distribu´ıdos. Um elemento PROXY ´e um simulacro de um elemento real. Ele age como a entidade real, mas n˜ao existe realmente. Ele existe na concepc¸˜ao l´ogica da programac¸˜ao. Cada objeto remoto real possui um objetoPROXY correspondente. O objetoPROXYest´a para o n´ıvel l´ogico assim como o objeto remoto est´a para o n´ıvel de execuc¸˜ao (fig.1.4).

Figura 1.4: Papel do objetoPROXY em relac¸˜ao ao objeto remoto.

1.3

Processamento no Charm++

Um programa em Charm++ consiste de um n´umero de objetos Charm++ dis-tribu´ıdos sobre o n´umero de processadores dispon´ıveis. Portanto, a unidade b´asica de computac¸˜ao paralela nos programas Charm++ ´e o chare, um objeto Charm++ que pode ser criado em qualquer processador dispon´ıvel e pode ser acessado de qualquer processador remoto. Chares podem ser criados dinamicamente e v´arios charespodem ser ativados simultaneamente. Charesenviam mensagens para outros charespara invo-car m´etodos assincronamente.

M´etodos de um chare podem ser invocados remotamente atrav´es dos chamados m´etodos de entrada(entry methods). M´etodos de entrada podem receber um ou v´arios parˆametros passados por valor ou um ponteiro para uma mensagem (message object). M´etodos de entrada s˜ao completamente n˜ao-preemptivos, isto ´e, o Charm++ nunca ir´a interromper um m´etodo em execuc¸˜ao para iniciar um qualquer outro trabalho e as invocac¸˜oes solicitadas s˜ao atendidas de foma ass´ıncrona.

(10)

gerenciador de execuc¸˜ao ir´a alocar o objeto remoto no processador menos carregado (realizando a menor quantidade de tarefas ou desocupado). Uma vez que o c´odigo n˜ao precisa identificar o processador que receber´a o objeto remoto, os objetos remotos podem migrar de um processador para outro, ou seja, eles podem ser realocados. Este mecanismo ´e o fundamento do balanceamento de carga.

Outros objetos Charm++ s˜ao colec¸˜oes de objetos remotos. S˜ao eles: listas de objetos remotos (chare arrays), grupos de objetos remotos (chare groups) e grupos de n´os de objetos remotos (chare nodegroups).

Uma lista de objetos remotos ´e uma colec¸˜ao decharesrealoc´aveis, indexados por algum tipo de ´ındice. O Charm++ admite uma lista decharesesparsa. N˜ao h´a necessi-dade de que a indexac¸˜ao seja cont´ınua a partir de um valor inicial. Isto significa que a lista pode ser segmentada em relac¸˜ao ao ´ındice adotado. S´o ´e necess´ario que o n´umero total de elementos na lista seja finito.

Grupo e grupo de n´os de objetos remotos s˜ao colec¸˜oes de chares, assim como a lista, por´em est˜ao organizados na forma de membros (ramificac¸˜oes). Um grupo de objetos remotos aloca umchare(um membro do grupo) por processador. Um grupo de n´os n˜ao enxerga os processadores, mas o agrupamento de processadores num mesmo recurso computacional. Por exemplo, 10 computadores com 6 processadores em cada ´e visto pelo Charm++ como 10 n´os (cada computador ´e um recurso computacional) de 6 processadores. Neste sentido, um grupo de n´os de objetos remotos aloca umchareem um processador por n´o, totalizando 10 membros do grupo de n´o (fig.1.5).

Figura 1.5: Noc¸˜ao de grupo de n´os.

Todo programa Charm++ deve ter, pelo menos, um mainchare, um objeto con-corrente que desempenhe o papel demestre. Cada objeto mestre ´e criado pelo sistema no processador0quando o programa ´e iniciado. ´E o ´unico objeto do Charm++ que ´e alocado em um processador conhecido. O gerenciador de execuc¸˜ao inicia o programa Charm++ alocando todos osmaincharescodificados e executando os m´etodos constru-tores correspondentes. Tipicamente, cada construtor ´e respons´avel por alocar os demais objetos Charm++ que tenham sido codificados.

(11)

gerenci-11

ador de execuc¸˜ao precisa saber os tipos de objetos remotos que o desenvolvedor est´a implementando em seu c´odigo, os m´etodos que ser˜ao invocados, os argumentos destes m´etodos e assim por diante. Toda esta informac¸˜ao deve estar documentada no c´odigo de interfaceamento do Charm++. O gerenciador de execuc¸˜ao identifica de forma ´unica e autom´atica cada um destes elementos e gera a definic¸˜ao dos objetos PROXY que o desenvolvedor enxergar´a e usar´a no seu n´ıvel l´ogico de programac¸˜ao. Torna-se, por-tanto, totalmente transparente ao desenvolvedor a alocac¸˜ao dos elementos concorrente, pois a responsabilidade de conhecer, identificar, localizar e acessar cada um deles ´e do gerenciador de execuc¸˜ao. Por isso o gerenciador ´e okerneldo Charm++.

1.4

Func

¸˜

oes ´

uteis no Charm++

A linguagem Charm++ possui um conjunto de func¸˜oes intr´ınsecas que cumprem pap´eis importantes dentro da l´ogica da programac¸˜ao. Elas ser˜ao apresentadas aqui sem o compromisso, neste momento, de inseri-las em um c´odigo elaborado. Far-se-´a isso em outro momento mais oportuno.

• void CkAssert(int express~ao)

Aborta o programa seexpress~aofor nulo.

• void CkAbort(const char *messagem de erro)

Aborta o programa imprimindo mensagem de erro no terminal de sa´ıda. Esta func¸˜ao n˜ao retorna. Isto significa que qualquer instruc¸˜ao ap´os esta invocac¸˜ao nunca ser´a executada.

• void CkExit()

Esta chamada informa okernel que a computac¸˜ao de todos os processos deve ser encerrada. Esta func¸˜ao n˜ao retorna. Como a requisic¸˜ao de encerramento ´e geren-ciada pelokernele okerneltrabalha de forma ass´ıncrona, os processos podem n˜ao parar simultaneamente.

• double CkWallTimer()

Retorna o tempo transcorrido em segundos desde o in´ıcio do programa.

• int CkNumPes()

Retorna o n´umero total de elementos de processamento (PEs) global.

• int CkMyPe()

Retorna o ´ındice do PE local.

• int CkNumNodes()

Retorna o n´umero total de n´os l´ogicos.

• int CkMyNode()

(12)

• int CkMyRank()

Retorna o sub´ındice do PE no n´o l´ogico (inicia em 0).

• int CkNodeFirst(int nd)

Retorna o ´ındice do primeiro PE no n´o l´ogicond.

• int CkNodeSize(int nd)

Retorna o n´umero total de PEs no n´o l´ogicond.

• int CkNodeOf(int pe)

Retorna o ´ındice do n´o l´ogico ao qual pertence o PE de ´ındicepe.

• int CkRankOf(int pe)

Retorna o sub´ındice do PE de ´ındicepeno n´o l´ogico local.

• int CkPrintf(format[,arg]*)

Func¸˜ao printf() da linguagem C adaptada para funcionar na rede.

• int CkScanf(format[,arg]*)

(13)

Cap´ıtulo 2

Elementos b´

asicos da linguagem

Charm++

Um programa Charm++ ´e estruturalmente semelhante a um programa C++ e pode ser distribu´ıdos em v´arios arquivos de c´odigo fonte. A maior parte de um programa Charm++ ´e c´odigo C++ e as principais unidades sint´aticas s˜ao definic¸˜oes de classe.

Existem cinco categorias de objetos no Charm++:

• objetos sequenciais (como no C++);

chares- objetos concorrentes simples;

chare messages - mensagens como organizac¸˜oes de dados heterogˆeneos trocados

entre objetos concorrente;

chare arrays- listas de objetos concorrentes (colec¸˜oes de objetos concorrentes

in-dexados);

chare groups - grupos de objetos concorrentes (colec¸˜oes de objetos concorrentes

clonados por processador);

chare nodegroups- n´os de grupo de objetos concorrentes.

Para que o gerenciador de execuc¸˜ao (Charm++kernel) identifique corretamente cada categoria de objeto concorrente, ´e necess´ario o uso de uma interface entre o Charm++ e o C++. Esta interface ´e codificada em um ou mais arquivos de texto cha-mados de aquivos de interface cuja extens˜ao ´e “.ci”. Um tradutor ´e usado para gerar a codificac¸˜ao correta dos objetos concorrentes do Charm++ e que ser´a usada no processo de compilac¸˜ao do c´odigo do desenvolvedor.

Cada objeto concorrente deve estar declarado em um arquivo de interface e inse-rido em umm´odulo(module) que deve se identificado por um nome. Um programa em Charm++ pode conter diversos m´odulos sendo que um deles deve ser identificado como om´odulo principal(mainmodule). Os demais m´odulos agregados ao m´odulo principal devem estar identificados pela chaveextern.

(14)

Exemplo: se o m´odulo principal se chamarABC, a interface dever´a ser codificada como

// arquivo ABC . ci m a i n m o d u l e ABC {

// corpo do modulo

};

O processo de traduc¸˜ao dos arquivos de interface gera dois outros arquivos com sufixos “.decl.h” e “.def.h” para cada m´odulo declarado na interface. Estes arquivos contˆem, respectivamente, declarac¸˜oes e definic¸˜oes dos objetos concorrentes declarados em cada m´odulo.

Exemplo: se a interface cont´em um m´odulo identificado pelo r´otulo ABC, ent˜ao, ap´os o processo de traduc¸˜ao da interface, dois arquivos ser˜ao criados, um chamado “ABC.decl.h” e outro chamado “ABC.def.h”. Como s˜ao arquivos de cabec¸alho da lingua-gem C/C++, recomenda-se que o arquivo de declarac¸˜oes seja inclu´ıdo no in´ıcio da codificac¸˜ao do arquivo de cabec¸alho do m´odulo correspondente, por exemplo, “ABC.h” e o arquivo de definic¸˜oes seja inserido no final do arquivo de codificac¸˜ao em C++ do m´odulo, exemplo, “ABC.cpp”.

Como a codificac¸˜ao da interface do Charm++ ´e pr´oprio para cada tipo de objeto concorrente, deixar-se-´a para cada sec¸˜ao que os descreve para apresentar a interface correspondente.

Ser˜ao apresentados, a seguir, cada um dos objetos concorrentes do Charm++.

2.1

Objeto sequencial

Objetos sequenciais s˜ao todos os objetos padr˜ao da linguagem C++. Esta cate-goria de objetos ´e conhecido e acessado localmente, isto ´e, os objetos sequenciais n˜ao s˜ao reconhecidos pelo gerenciador de execuc¸˜ao e seus m´etodos n˜ao podem ser invoca-dos remotamente. N˜ao h´a codificac¸˜ao de classes de objetos sequenciais na interface do Charm++.

Exemplo de declarac¸˜ao de uma classe de um objeto sequencial chamadoPonto3D:

// d e f i n i c a o do objeto s e q u e n c i a l class Ponto3D {

p r o t e c t e d:

double x , y , z ;

public:

Ponto3D (void) { x = y = z = 0; }

Ponto3D (double ix ,double iy ,double iz ) { x = ix ; y = iy ; z = iz ;

(15)

15

void X (double ix ) { x = ix ; }

void Y (double iy ) { y = iy ; }

void Z (double iz ) { z = iz ; }

double X (void) { return x ; }

double Y (void) { return y ; }

double Z (void) { return z ; } };

2.2

Objeto concorrente simples

Os objetos concorrentes simples (chares) s˜ao os elementos mais importantes em um programa Charm++. S˜ao codificados de forma semelhante aos objetos sequenciais em C++, por´em s˜ao filiados a uma superclasse do Charm++ chamada CBase que as modela.

Enquanto objetos concorrentes, precisam ser declaradas na interface do Charm++ comochare. Os m´etodos dispon´ıveis para invocac¸˜ao remota devem ser definidos como m´etodos de entrada e identificados na interface do Charm++ com a palavra chave

entry. Estes m´etodos de entrada podem receber argumentos, mas n˜ao retornam qual-quer tipo de informac¸˜ao. Logo, s˜ao declarados em C++ comovoid.

Umcharedeve possuir pelo menos um m´etodo de entrada que ´e o seu construtor. ´

E natural que o construtor dochareseja um m´etodo de entrada, pois a criac¸˜ao do objeto remoto implica na invocac¸˜ao de seu construtor.

No exemplo a seguir, vˆe-se a declarac¸˜ao e a implementac¸˜ao de umcharechamado

chareTipo. No arquivo de interface, indica-se a natureza de chareTipo como chare e lista-se os m´etodos de entrada previstos: o construtor de chareTipo e um m´etodo chamado NomeMetodoEntrada. Se os m´etodos de entrada possuem argumentos, estes devem constar dos prot´otipos dos m´etodos de entrada na interfaces.

// . ci

// -// i n t e r f a c e do chare c h a r e T i p o

// -chare c h a r e T i p o {

// -// i n t e r f a c e do c o n s t r u t o r

// -entry c h a r e T i p o ( args1 );

// -// i n t e r f a c e do metodo de entrada N o m e M e t o d o E n t r a d a // -entry void N o m e M e t o d o E n t r a d a ( args2 );

(16)

A implementac¸˜ao da classe chareTipo deve ser descendente de uma classe pri-mitiva chamadaCBase chareTipo. Esta classe primitiva ´e gerada no processamento do arquivo de interface a partir da superclasseCBase. O desenvolvedor n˜ao deve editar a codificac¸˜ao de CBase chareTipo (n˜ao h´a necessidade disto). Qualquer demanda deve ser codificada na classe descendentechareTipoque est´a sendo implementada.

// . h

// -// d e f i n i c a o da classe do chare c h a r e T i p o

// -class c h a r e T i p o : public C B a s e _ c h a r e T i p o {

public:

// -// p r o t o t i p o do c o n s t r u t o r

//

-c h a r e T i p o ( args1 );

// -// p r o t o t i p o do metodo de entrada N o m e M e t o d o E n t r a d a // -void N o m e M e t o d o E n t r a d a ( args2 );

};

Al´em da gerac¸˜ao da classe primitiva CBase chareTipo, o processamento do ar-quivo de interface produz a classePROXYcorrespondente:CProxy chareTipo. O instan-ciamento da classechareTipoocorre a n´ıvel dePROXYatrav´es de um m´etodo intr´ınseco da classeCProxy chareTipo chamado ckNew. Este m´etodo admite os argumentos de-clarados no construtor dechareTipo. Na terminologia do Charm++,chareNome ´e um objetoPROXYassociado `a classechareTipo.

// . cpp

// -// i n s t a n c i a m e n t o da classe c h a r e T i p o

//

-C P r o x y _ c h a r e T i p o c h a r e N o m e ;

c h a r e N o m e = C P r o x y _ c h a r e T i p o :: ckNew ( args1 );

A execuc¸˜ao de qualquer m´etodo de entrada ´e ass´ıncrona e n˜ao-preemptiva. No n´ıvel l´ogico, a invocac¸˜ao de um m´etodo de entrada ´e realizada atrav´es do objetoPROXY associado ao chare. O gerenciador de execuc¸˜ao ´e respons´avel pela invocac¸˜ao real do m´etodo de entrada dochare.

(17)

17

2.2.1 mainchare

Toda programac¸˜ao em Charm++ deve possuir um objeto principal (o objeto mes-tre) que cumpre um papel similar aointmain()da linguagem C/C++. Ele ´e um objeto concorrente simples, umchare, identificado na interface do Charm++ comomainchare. ´

E o ´unico objeto a ser instanciado e invocado pelo gerenciador de execuc¸˜ao. ´E referen-ciado na codificac¸˜ao atrav´es de seu objeto PROXY associado: CProxy mainchareTipo mainchareNome.

// . ci

// -// d e s c r i c a o da i n t e r f a c e do charm ++

// -m a i n -m o d u l e m o d u l e N o m e {

// -// i n t e r f a c e do m a i n c h a r e m a i n c h a r e T i p o

// -m a i n c h a r e m a i n c h a r e T i p o {

// -// i n t e r f a c e do c o n s t r u t o r

// -entry m a i n c h a r e T i p o ( args1 );

// -// i n t e r f a c e do metodo de entrada

// N o m e M e t o d o E n t r a d a

// -entry void N o m e M e t o d o E n t r a d a ( args2 );

}; };

// . h

// -// d e f i n i c a o da classe do m a i n c h a r e m a i n c h a r e T i p o // -class m a i n c h a r e T i p o : public C B a s e _ m a i n c h a r e T i p o {

public:

// -// p r o t o t i p o do c o n s t r u t o r

//

-m a i n c h a r e T i p o ( args1 );

// -// p r o t o t i p o do metodo de entrada

// N o m e M e t o d o E n t r a d a

// -void N o m e M e t o d o E n t r a d a ( args2 );

(18)

// . cpp

// -// i m p l e m e n t a c a o do c o n s t r u t o r

//

-m a i n c h a r e T i p o :: -m a i n c h a r e T i p o ( args1 ) {

// codigo C ++

}

// -// i m p l e m e n t a c a o do metodo de entrada

// N o m e M e t o d o E n t r a d a

// -void m a i n c h a r e T i p o :: N o m e M e t o d o E n t r a d a ( args2 ) {

// codigo C ++

}

2.2.2 Dados com acesso somente para leitura

Por conta da natureza distribu´ıda da execuc¸˜ao em Charm++, n˜ao faz sentido a declarac¸˜ao de vari´aveis/objetos globais em sentido estrito. Para cumprir um efeito semelhante ao da declarac¸˜ao de dados globais, o Charm++ disponibiliza um mecanismo particular para que dados possam ser compartilhados por todos os objetos concorrentes. Para que este compartilhamento funcione, os objetos concorrentes devem enxergar os “dados globais” comosomente para leitura(read-only access). Para isto, os referidos “dados globais” devem ser declarados na interface do Charm++ com o modificador

readonly.

Por exemplo, o objeto principal (instˆancia do mainchare) no c´odigo Charm++ ´e instanciado a partir da classe CProxyassociada (conforme mencionado na sec¸˜ao ante-rior). Para que os objetos concorrente acessem os m´etodos do objeto principal, o objeto principal deve ser declarado como na interface comoreadonly. No arquivo.hda classe

mainchareTipo, o objeto principal ´e referenciado com o modificadorextern.

// . ci

// -// d e s c r i c a o da i n t e r f a c e do charm ++

// -m a i n -m o d u l e m o d u l e N o m e {

// -// i n t e r f a c e para o objeto p r i n c i p a l

// -r e a d o n l y C P r o x y _ m a i n c h a r e T i p o m a i n c h a r e N o m e ;

// -// i n t e r f a c e do m a i n c h a r e m a i n c h a r e T i p o

// -m a i n c h a r e m a i n c h a r e T i p o {

(19)

-19

// i n t e r f a c e do c o n s t r u t o r

// -entry m a i n c h a r e T i p o ( args1 );

// -// i n t e r f a c e do metodo de entrada

// N o m e M e t o d o E n t r a d a

// -entry void N o m e M e t o d o E n t r a d a ( args2 );

}; };

// . h

// -// r e f e r e n c i a m e n t o externo do objeto p r i n c i p a l

// -extern C P r o x y _ m a i n c h a r e T i p o m a i n c h a r e N o m e ;

// -// d e f i n i c a o da classe do m a i n c h a r e m a i n c h a r e T i p o // -class m a i n c h a r e T i p o : public C B a s e _ m a i n c h a r e T i p o {

public:

// -// p r o t o t i p o do c o n s t r u t o r

//

-m a i n c h a r e T i p o ( args1 );

// -// p r o t o t i p o do metodo de entrada

// N o m e M e t o d o E n t r a d a

// -void N o m e M e t o d o E n t r a d a ( args2 );

};

// . cpp

// -// i n s t a n c i a m e n t o do objeto PROXY p r i n c i p a l

// -/* r e a d o n l y */ C P r o x y _ m a i n c h a r e T i p o m a i n c h a r e N o m e ;

// -// i m p l e m e n t a c a o do c o n s t r u t o r

//

-m a i n c h a r e T i p o :: -m a i n c h a r e T i p o ( args1 ) {

// codigo C ++

}

// -// i m p l e m e n t a c a o do metodo de entrada

// N o m e M e t o d o E n t r a d a

(20)

-void m a i n c h a r e T i p o :: N o m e M e t o d o E n t r a d a ( args2 ) {

// codigo C ++

}

Al´em do objeto principal, outros dados podem ser identificados comoreadonly, tais como mensagens e dados homogˆeneos (dados indexados).

O fato do dado ser identificado comoreadonlyimp˜oe que ele seja instanciado e inicializado assim que o programa ´e executado e que seu conte´udo n˜ao seja alterado durante toda a execuc¸˜ao.

Este assunto ser´a retomado posteriormente na sec¸˜ao sobre mensagens.

2.2.3 Passagem de argumentos

Em Charm++, objetos concorrentes se comunicam atrav´es da invocac¸˜ao de m´etodos de entrada. Os m´etodos podem requerer diversos parˆametros apresentados como argu-mentos ou agrup´a-los manualmente em uma ´unica estrutura de comunicac¸˜ao. Indepen-dente da forma como os parˆametros sejam transferidos, a comunicac¸˜ao entre objetos remotos sempre se d´a por meio da troca de mensagens.

No modelo tradicionalde passagem de parˆametros da linguagem C/C++, cada dado ´e declarado no escopo de argumentos do m´etodo correspondente. Como o m´etodo pode ser de um objeto remoto, n˜ao ´e poss´ıvel utilizar-se ponteiros entre os argumentos, ou seja, n˜ao h´a passagem de parˆametros por referˆencia, somente por c´opia.

O outro modelo de passagem de argumentos ´e a passagem de mensagens propri-amente dita. Neste caso, os dados s˜ao organizados em um objeto pr´oprio (derivado da classe primitiva CMessage, como ser´a apresentado futuramente) e enviados para o objeto remoto. Neste caso, o envio das mensagens ´e de responsabilidade do kernel do Charm++. O kernel utiliza um buffer de mensagens e, para isso, ele precisa de re-ferˆencias das mensagens (ponteiros).

Vejamos um exemplo de passagem de argumentos no modelo tradicional.

// pgm . ci

// -m a i n -m o d u l e pgm

{

// -// objeto PROXY p r i n c i p a l r e f e r e n c i a d o

// " g l o b a l m e n t e "

// -r e a d o n l y C P r o x y _ m a i n m a i n P r o x y ;

m a i n c h a r e main {

// c o n s t r u t o r

(21)

21

// metodo

entry void r e s u l t a d o (int pe ); };

chare remoto {

// c o n s t r u t o r

entry remoto (void);

// metodo remoto

entry void metodo (int val ); };

};

// pgm . h

// -# ifndef PGM_H

# define PGM_H

// -// r e f e r e n c i a a classe p r i n c i p a l ( mestre )

// -extern C P r o x y _ m a i n m a i n P r o x y ;

// -// classe p r i n c i p a l ( mestre )

// -class main : public C B a s e _ m a i n

{

private:

int cont ;

public:

// c o n s t r u t o r

main ( C k A r g M s g * m );

// metodos da classe ( acesso remoto ) void r e s u l t a d o (int pe );

};

//

// -// classe c o n c o r r e n t e ( escravo )

// -class remoto : public C B a s e _ r e m o t o

{

private:

public:

// c o n s t r u t o r

(22)

// metodos da classe ( acesso local ) void metodo (int val );

};

// -# endif

// pgm . C

// -# include " pgm . decl . h "

//

-# include < math .h >

# include " pgm . h "

// -// r e f e r e n c i a a classe p r i n c i p a l ( mestre )

//

-C P r o x y _ m a i n m a i n P r o x y ;

// -// c o n s t r u t o r da classe p r i n c i p a l ( mestre )

//

-main :: -main ( C k A r g M s g * m ) {

int npes = C k N u m P e s ();

int i ;

C P r o x y _ r e m o t o p r o c e s s o ;

// -// r e f e r e n c i a ao objeto m a i n P r o x y no p r o c e s s a d o r // ’ mestre ’

//

-m a i n P r o x y = t h i s h a n d l e ;

cont = npes ;

C k P r i n t f (" \ nTotal de PEs : % d \ n ", npes );

C k P r i n t f (" P a r t i n d o do mestre ( PE % d ).\ n ", CkMyPe ());

for ( i =0; i < npes ; i ++) {

p r o c e s s o = C P r o x y _ r e m o t o :: ckNew (); p r o c e s s o . metodo ( i );

} }

//

(23)

23

// -void main :: r e s u l t a d o (int pe )

{

cont - -;

C k P r i n t f (" \ t C o n t a t o do PE % d \ n ", pe );

if (! cont ) {

C k P r i n t f (" V o l t a m o s para o mestre ( PE % d ).\ n \ n ", CkMyPe ()); CkExit ();

} }

//

// -// metodo de entrada do objeto c o n c o r r e n t e

// -void remoto :: metodo (int val )

{

int pe = CkMyPe ();

C k P r i n t f (" \ t \ tRecebi % d .\ n ", val ); m a i n P r o x y . r e s u l t a d o ( pe );

}

//

// -# include " pgm . def . h "

//

-$ < caminho para o compilador >/ charmc -c pgm . ci $ < caminho para o compilador >/ charmc -o pgm pgm . cc $ ./ c h a r m r u n ./ pgm + p4 ++ local

Uma an´alise deste exemplo.

A classe principal (mainchare) se chama main, conforme arquivo de interface pgm.ci. Deriva da classe baseCBase main, como pode ser visto no arquivo de cabec¸alho pgm.h. Seu objetoPROXYse chamaCProxy main mainProxy. Isso pode ser reconhecido na codificac¸˜ao em C++ (pgm.C) e pela referˆencia na interface (comoreadonly).

Existe um objeto concorrente instanciado da classe remoto, derivada da classe baseCBase remoto. O instanciamento ocorre no construtor domain, cujo objetoPROXY correspondente se chamaCProxy remoto processo. Este objeto n˜ao ´e “global”.

Os dois construtores (domain e doremoto) s˜ao definidos como m´etodos de en-trada (como devem ser). Al´em dos construtores, as classes preveem dois outros m´etodos de entrada: resultado(int pe)nomainemetodo(int val)noremoto.

(24)

m´etodo de entradaprocesso.metodo, passando, como argumento, um n´umero inteiro que indica a ordem de instanciamento. Por conseguinte, os objetos remotos recebem estes n´umeros inteiros e, cada um, imprime o valor recebido. O passo seguinte dos objetos remotos ´e invocar o m´etodo de entradamainProxy.resultadopassando, como argumento, o ´ındice do PE correspondente (o ´ındice do processador onde o objeto con-corrente foi alocado). O m´etodo mainProxy.resultado imprime o ´ındice do PE que enviou a mensagem e s´o encerra o programa quando tiver recebido os dados de todos.

Algumas coisas importantes para serem observadas.

• A func¸˜ao CkPrintf(...) ´e invocada no objeto principal e nos remotos. Repare

que a impress˜ao sempre se d´a na tela do computador que aloca o objeto princi-pal. Segundo, as impress˜oes s˜ao ass´ıncronas porque cada objeto remoto “roda” independentemente. V´arios motivos podem interferir na ordem de chegada das mensagens (o que ser´a impresso tamb´em ´e tratado como mensagem).

• Pela l´ogica do programa, n˜ao h´a necessidade de se manter as referˆencias de cada

objeto concorrente alocado. Como eles s˜ao invocados apenas uma ´unica vez, a referˆenciaprocessopode ser reutilizada. Nem sempre ´e este o caso. Mas aqui d´a para fazer isso. Este exemplo simples permite. Al´em disso, os objetos concorrente n˜ao se falam entre si. Se fosse este o caso, a referˆenciaprocesso precisaria ser “global” e ´unica para cada objeto concorrente. As opc¸˜oes seriam usar uma lista (chare array) ou um grupo (chare group) de objetos concorrente.

• A referˆencia do objeto PROXY principal ´e efetivamente realizada na instruc¸˜ao:

mainProxy = thishandle, onde thishandle cumpre um papel semelhante ao

this do C++. thishandle n˜ao ´e um ponteiro (assim como mainProxy), mas “carrega” todas as informac¸˜oes necess´arias para o completo referenciamento do objeto em quest˜ao.

Em relac¸˜ao `a passagem de argumentos, repare o modo tradicional de passagem de dados por c´opia.

No entanto, ´e comum a passagem de ponteiros para estruturas homogˆeneas como listas e matrizes. Mas como o Charm++ n˜ao permite a passagem de ponteiros (pelo fato de os PEs estarem em segmentos de mem´orias n˜ao compartilhadas), o mecanismo teve que ser adaptado. A linguagem Charm++ substitui a passagem por ponteiros (passa-gem de parˆametros por referˆencia) pela declarac¸˜ao da estrutura acompanhada do total de elementos que ela suporta. Por exemplo, o desenvolvedor precisa passar uma lista de valoresdoublecomnelementos como argumento de um m´etodo de entrada chamada

misc. A inserc¸˜ao do m´etodo na interface do Charm++ ser´a:

(25)

25

onde arr ´e o nome da estrutura homogˆenea a ser utilizado no escopo do m´etodo de entrada. O prot´otipo do m´etodo em C++ ser´a:

void misc (int n, double *arr);

Pronto, est´a feita a confus˜ao...

— Mas o Charm++ n˜ao tem problemas com ponteiros?

Pois ´e. O Charm++ tem problemas com ponteiro sim. Problemas no sentido de n˜ao se poder utilizar ponteiros entre objetos concorrentes.

Bem, a linguagem C/C++ n˜ao reconhece a sintaxe que ´e utilizada na interface do Charm++ e n˜ao pode passar ponteiros. Ent˜ao como a “coisa” funciona?

Quem intercepta a referˆencia `a lista (ponteiro) ´e okerneldo Charm++. A presenc¸a do ponteiro no prot´otipo do m´etodo de entrada ´e utilizada por umbufferque armazena os valores da estrutura referenciada e monta uma mensagem. Esta mensagem ´e transmi-tida para o destinat´ario. Okerneldesmonta a mensagem e coloca os dados da estrutura (que foram transmitidos pela mensagem) em umbuffer alocado na mem´oria do objeto remoto. Obuffer´e acessado pelo ponteiro presente no argumento do m´etodo de entrada do objeto remoto.

Isto produz implicac¸˜oes. Tradicionalmente, em linguagem C/C++, quando um dado ´e passado por referˆencia atrav´es de ponteiro, se o dado original for alterado, quem tem acesso via referˆencia “vˆe” o dado alterado. Mas isso acontece porque a referˆencia ´e o enderec¸o do dado e n˜ao o dado em si. No caso do Charm++, existe umbufferno meio do caminho. Isso desvincular´a a referˆencia do dado original (que pode estar em um pro-cessador) do enderec¸o do dado original em si (que pode estar em outro propro-cessador). Ent˜ao, apesar de se usar ponteiros na sintaxe do prot´otipo do m´etodo de entrada, estes existem por conta dobufferlocal que ´e usado pelokernelpara receber os dados. Depois, os dados copiados nobuffers˜ao transmitidos para obufferdo objeto remoto. L´a, obuffer ´

e acessado via ponteiro no m´etodo de entrada do objeto remoto.

— E por que colocar o n´umero (quantidade) de valores?

Osbuffers locais (no remetente e no destinat´ario) s˜ao alocados dinamicamente. Para se acertar o tamanho dobuffer, se faz necess´ario informar a quantidade de valores e sua natureza. Tudo isso ´e registrado pela compilac¸˜ao da interface do Charm++.

2.3

Mensagens

(26)

As mensagens s˜ao objetos que compactam diferentes tipos de dados em uma ´unica estrutura e que podem ser trocados entre objetos remotos. Elas s˜ao transmitidas e rece-bidas de forma ass´ıncrona, ou seja, s˜ao enviadas para o gerenciador de execuc¸˜ao que ir´a despach´a-las para seus destinat´arios em algum instante de tempo ap´os a recepc¸˜ao das mesmas. Para controlar a recepc¸˜ao e o envio de mensagens, o gerenciador de execuc¸˜ao trabalha com um dep´osito (workpool) onde as mensagens v˜ao sendo enfileiradas ( queu-eing) e retransmitidas segundo a disponibilidade dos destinat´arios.

Enquanto objetos, as mensagens tamb´em encapsulam m´etodos. Por´em, estes n˜ao precisam ser identificados como m´etodos de entrada, pois este tipo de identificac¸˜ao se refere somente aos m´etodos que ser˜ao invocados remotamente. Como as mensagens s˜ao literalmente transmitidas de um processador para outro, seus m´etodos podem ser acessados localmente tanto pelo objeto remetente antes da transmiss˜ao como pelo objeto destinat´ario ap´os a transmiss˜ao.

A classe primitiva que modela toda mensagem se chamaCMessage. Esta classe ´e gen´erica e deve ser adequada `a codificac¸˜ao da mensagem elaborada pelo desenvolvedor. Esta tarefa n˜ao precisa ser realizada pelo desenvolvedor, pois o processo de traduc¸˜ao da interface (arquivos.ci) gera as adaptac¸˜oes necess´arias e registra o resultado nos arquivos de declarac¸˜oes e definic¸˜oes (“.decl.h” e “.def.h”). A classe derivada da classe primitiva recebe um nome que ´e o nome da classe primitiva CMessage conjugado ao nome da classe do desenvolvedor. A classe do desenvolvedor deve ser descendente desta classe derivada para ser reconhecida pelo Charm++. Por exemplo, se a classe do desenvolve-dor se chamamsg, ent˜ao o nome da classe derivada gerada pela traduc¸˜ao da interface ser´aCMessage msg.

// classe msg d e s c e n d e n t e de C M e s s a g e _ m s g // que deriva de C M e s s a g e

class msg : public C M e s s a g e _ m s g {

// a t r i b u t o s // c o n s t r u t o r

};

Na interface do Charm++, a mensagem ´e identificada pela chavemessageseguida do nome da classe do desenvolvedor.

Seguindo o exemplo anterior, se a classe elaborada se chamamsg, ent˜ao, na inter-face, esta mensagem ser´a identificada como “message msg”.

m a i n m o d u l e m o d u l e N o m e {

// d e c l a r a c a o de msg message msg ;

// demais d e c l a r a c o e s do modulo m a i n c h a r e m a i n c h a r e N o m e {

(27)

27

};

O Charm++ reconhece dois tipos diferentes de mensagem: amensagem de ta-manho fixo, composto por atributos de tata-manho fixo, e a mensagem de tamanho vari´avel, indicando, normalmente, atributos na forma de lista indexada (vetores e ma-trizes) declaradas atrav´es de ponteiros. Na forma fixa, o Charm++ n˜ao exige maiores codificac¸˜oes na declarac¸˜ao da mensagem na interface. J´a no caso da mensagem de ta-manho vari´avel, como o atributo ´e um ponteiro, o Charm++ imp˜oe ao desenvolvedor a alocac¸˜ao de mem´oria necess´aria para acomodar os dados.

2.3.1 Mensagem de tamanho fixo

Exemplo de mensagem com tamanho fixo:

// arquivo . h

class mgs : public C M e s s a g e _ m g s {

public:

// a t r i b u t o s que compoem a m e n s a g e m u n s i g n e d int a ; // 4 bytes

double b ; // 8 bytes

// total 12 bytes

// c o n s t r u t o r

mgs (void) { } };

Na interface, a declarac¸˜ao da mensagem ´e idˆentica ao exemplo anterior.

// arquivo : . ci

m a i n m o d u l e m a i n m o d u l e N o m e {

// d e c l a r a c a o de msg message msg ;

// demais d e c l a r a c o e s do modulo m a i n c h a r e m a i n c h a r e N o m e {

entry m a i n c h a r e N o m e (void); };

};

(28)

programa Charm++. A flexibilidade do Charm++ reside justamente na possibilidade de se alocar mem´oria para uma mensagem somente quando esta ´e realmente necess´aria. A operac¸˜ao de alocac¸˜ao ´e realizada atrav´es do operadornew, tradicional da linguagem C++. O processo de transmiss˜ao ´e respons´avel pela desalocac¸˜ao da mem´oria no lado do remetente e da alocac¸˜ao de mem´oria do lado do destinat´ario.

Exemplo completo de troca de mensagem de tamanho fixo:

// arquivo : E x M e s s a g e . ci m a i n m o d u l e E x M e s s a g e {

r e a d o n l y C P r o x y _ M e s t r e P r o x y M e s t r e ;

// i n t e r f a c e da m e n s a g e m Msg message Msg ;

m a i n c h a r e Mestre {

// c o n s t r u t o r do m a i n c h a r e entry Mestre ( C k A r g M s g * marg );

// metodo de entrada do m a i n c h a r e entry void M e t o d o M e s t r e (void); };

chare Remoto {

// c o n s t r u t o r do objeto remoto entry Remoto (void);

// metodo de entrada do objeto remoto entry void M e t o d o R e m o t o ( Msg * m ); };

};

// arquivo : E x M e s s a g e . cc # include " charm ++. h "

# include " E x M e s s a g e . decl . h "

// objeto proxy do m a i n c h a r e Mestre // d e c l a r a d o como somente leitura // papel s e m e n h a n t e ao de uma // v a r i a v e l global

C P r o x y _ M e s t r e P r o x y M e s t r e ;

// d e f i n i c a o da m e n s a g e m Msg class Msg : public C M e s s a g e _ M s g {

public:

// dados de tamanho fixo

u n s i g n e d int a ; // 4 bytes

double b ; // 8 bytes

char str [32]; // 32 bytes

// total : 44 bytes

(29)

29

};

// m a i n c h a r e Mestre

class Mestre : public C B a s e _ M e s t r e {

public:

// c o n s t r u t o r do m a i n c h a r e Mestre

Mestre ( C k A r g M s g * marg ) {

// objeto proxy do chare Remoto

C P r o x y _ R e m o t o P r o x y R e m o t o ;

// objeto m e n s a g e m de dado

Msg * m ;

// d e s a l o c a c a o da m e n s a g e m de a r g u m e n t o s delete marg ;

// i d e n t i f i c a d o r deste objeto proxy

P r o x y M e s t r e = t h i s h a n d l e ;

// i n s t a n c i a m e n t o do objeto proxy

C k P r i n t f (" I n s t a n c i a n d o chare P r o x y R e m o t o ...\ n "); P r o x y R e m o t o = C P r o x y _ R e m o t o :: ckNew ();

// i n s t a n c i a m e n t o da m e n s a g e m

C k P r i n t f (" I n s t a n c i a n d o m e n s a g e m m ...\ n "); m = new Msg ;

// a t r i b u i c a o dos dados

m - > a = 10; m - > b = 29.9;

strcpy (m - > str ," string copiada ... ");

// r e q u i s i c a o do metodo remoto com // a t r a n s m i s s a o da mensgem de dado

C k P r i n t f (" E n v i a n d o m e n s a g e m m para chare " " P r o x y R e m o t o ...\ n ");

P r o x y R e m o t o . M e t o d o R e m o t o ( m ); }

// metodo de entrada do m a i n c h a r e Mestre void M e t o d o M e s t r e (void) {

// e n c e r r a m e n t o do p r o c e s s a m e n t o // c o n c o r r e n t e

C k P r i n t f (" E n c e r r a n d o p r o g r a m a " " ( m a i n c h a r e )...\ n "); CkExit ();

} };

// chare Remoto

class Remoto : public C B a s e _ R e m o t o {

private:

(30)

u n s i g n e d int x ;

double y ;

char s [48];

public:

// c o n t r u t o r do chare Remoto

Remoto (void) {

x = 0; y = 0; strcpy (s ," "); }

// metodo de entrada da classe Remoto void M e t o d o R e m o t o ( Msg * m ) {

C k P r i n t f (" R e c e b e n d o m e n s a g e m em " " P r o x y R e m o t o ...\ n ");

// leitura dos dados t r a n s m i t i d o s

x = m - > a ; y = m - > b ;

strcpy (s ,m - > str );

// d e s a l o c a c a o da m e n s a g e m de dados delete m ;

C k P r i n t f (" x = % d \ ty = % lf \ n ",x , y ); C k P r i n t f (" s = % s \ n ",s );

// r e q u i s i c a o do metodo de entrada // do objeto Mestre

C k P r i n t f (" C o n t a c t a n d o m a i n c h a r e ...\ n "); P r o x y M e s t r e . M e t o d o M e s t r e ();

} };

# include " E x M e s s a g e . def . h "

$ < caminho do compilador >/ charmc -c E x M e s s a g e . ci

$ < caminho do compilador >/ charmc -o E x M e s s a g e E x M e s s a g e . cc $ ./ c h a r m r u n ./ E x M e s s a g e ++ local

2.3.2 Mensagem de tamanho vari´avel

No caso da mensagem de tamanho vari´avel, os atributos que precis˜ao ser alocados dinamicamente devem constar da declarac¸˜ao na interface do Charm++. Se a mensa-gem prevˆe atributos de tamanho fixo, estes n˜ao precisam ser declarados na interface, mas devem, naturalmente, ser definidos na codificac¸˜ao da mensagem em si.

// arquivo . h

(31)

31

public:

// -// a t r i b u t o s de tamanho v a r i a v e l

// p r e c i s a m ser d e c l a r a d o s na i n t e r f a c e // -u n s i g n e d char * atrb1 ;

int * atrb2 ;

// -// a t r i b u t o s de tamanho fixo

// nao sao d e c l a r a d o s na i n t e r f a c e

// -u n s i g n e d int atrb3 ; // 4 bytes

double atrb4 ; // 8 bytes

// total 12 bytes fixos

// c o n s t r u t o r

varmsg ( params ) { } };

// arquivo : . ci

m a i n m o d u l e m a i n m o d u l e N o m e {

// -// d e c l a r a c a o de varmsg

// -message varmsg {

// -// a t r i b u t o s de tamanho v a r i a v e l // -u n s i g n e d char atrb1 [];

int atrb2 []; };

// -// demais d e c l a r a c o e s do modulo

// -m a i n c h a r e m a i n c h a r e T i p o {

entry m a i n c h a r e T i p o (); };

};

A alocac¸˜ao de mem´oria para os atributos de tamanho vari´avel pode ser realizada tanto no construtor da mensagem quanto atrav´es do comando de alocac¸˜ao de mem´oria

new modificado pelo Charm++. Neste caso, os comprimentos dos atributos vari´aveis s˜ao inseridos entre o comandonewe o nome da classe de mensagem e o construtor n˜ao deve alocar mem´oria (isso ´e realizado pelokernel).

(32)

// arquivo : E x V a r M s g . ci m a i n m o d u l e E x V a r M s g {

r e a d o n l y C P r o x y _ M e s t r e P r o x y M e s t r e ;

// i n t e r f a c e da m e n s a g e m VarMsg message VarMsg {

char varstr []; // a t r i b u t o s de

float seq []; // c o m p r i m e n t o v a r i a v e l

};

m a i n c h a r e Mestre {

// c o n s t r u t o r do m a i n c h a r e entry Mestre ( C k A r g M s g * marg );

// metodo de entrada do m a i n c h a r e entry void M e t o d o M e s t r e (void); };

chare Remoto {

// c o n s t r u t o r do objeto remoto entry Remoto (void);

// metodo de entrada do objeto remoto entry void M e t o d o R e m o t o ( VarMsg * m ); };

};

// arquivo : E x V a r M s g . C # include " charm ++. h "

# include " E x V a r M s g . decl . h "

// -// objeto proxy do m a i n c h a r e Mestre //

-C P r o x y _ M e s t r e P r o x y M e s t r e ;

// -// d e f i n i c a o da m e n s a g e m VarMsg

// -class VarMsg : public C M e s s a g e _ V a r M s g {

public:

// -// dados de tamanho fixo

// nao devem estar na i n t e r f a c e // -u n s i g n e d int n , m ;

(33)

33

// -char * varstr ;

float * seq ;

// -// c o n s t r u t o r da m e n s a g e m

//

-VarMsg (int p , int q ) { n = p ; m = q ;

// a l o c a c a o manual de memoria

varstr = new char[ n ]; seq = new float[ m ]; }

// -// d e s t r u t o r da m e n s a g e m

//

-~ VarMsg (void) { n = m = 0;

delete[] varstr ; delete[] seq ; varstr = NULL ; seq = NULL ; }

};

// -// m a i n c h a r e Mestre

// -class Mestre : public C B a s e _ M e s t r e {

public:

// -// c o n s t r u t o r do m a i n c h a r e Mestre //

-Mestre ( C k A r g M s g * marg ) {

// objeto proxy do chare Remoto

C P r o x y _ R e m o t o P r o x y R e m o t o ;

// objeto m e n s a g e m de dado

VarMsg * m ;

// d e s a l o c a c a o da m e n s a g e m de a r g u m e n t o s delete marg ;

// i d e n t i f i c a d o r deste objeto proxy

P r o x y M e s t r e = t h i s h a n d l e ;

// i n s t a n c i a m e n t o do objeto proxy

C k P r i n t f (" I n s t a n c i a n d o chare P r o x y R e m o t o ...\ n "); P r o x y R e m o t o = C P r o x y _ R e m o t o :: ckNew ();

// i n s t a n c i a m e n t o da m e n s a g e m

(34)

// c o m p r i m e n t o s de varstr e seq , // r e s p e c t i v a m e n t e : (10 ,20)

m = new VarMsg (10 ,20);

// a t r i b u i c a o dos dados

strcpy (m - > varstr ," string ... "); memset (m - > seq ,0 ,20);

// r e q u i s i c a o do metodo remoto com // a t r a n s m i s s a o da mensgem de dado

C k P r i n t f (" E n v i a n d o m e n s a g e m m para chare " " P r o x y R e m o t o ...\ n ");

P r o x y R e m o t o . M e t o d o R e m o t o ( m ); }

// -// metodo de entrada do m a i n c h a r e Mestre // -void M e t o d o M e s t r e (void) {

// e n c e r r a m e n t o do p r o c e s s a m e n t o // c o n c o r r e n t e

C k P r i n t f (" E n c e r r a n d o p r o g r a m a " " ( m a i n c h a r e )...\ n "); CkExit ();

} };

// -// chare Remoto

// -class Remoto : public C B a s e _ R e m o t o {

private:

// a t r i b u t o s da classe Remoto int l1 , l2 ;

char * s ;

float * f ;

public:

// -// c o n t r u t o r do chare Remoto

//

-Remoto (void) { l1 = l2 = 0; }

// -// metodo de entrada da classe Remoto // -void M e t o d o R e m o t o ( VarMsg * m ) {

(35)

35

// leitura dos dados t r a n s m i t i d o s

l1 = m - > n ; s = new char[ l1 ]; l2 = m - > m ; f = new float[ l2 ];

strcpy (s ,m - > varstr );

memcpy (f ,m - > seq ,sizeof(float)* l2 );

// d e s a l o c a c a o da m e n s a g e m de dados delete m ;

C k P r i n t f (" l1 = % d \ n \ tvarstr = % s \ n ", l1 , s ); C k P r i n t f (" l2 = % d \ n ", l2 );

for ( int i =0; i < l2 ; i ++ )

C k P r i n t f (" \ tf [% d ] = % f \ n ", i , f [ i ]);

// r e q u i s i c a o do metodo de entrada // do objeto Mestre

C k P r i n t f (" C o n t a c t a n d o m a i n c h a r e ...\ n "); P r o x y M e s t r e . M e t o d o M e s t r e ();

} };

# include " E x V a r M s g . def . h "

$ < caminho do compilador >/ charmc -c E x V a r M s g . ci

$ < caminho do compilador >/ charmc -o E x V a r M s g E x V a r M s g . C $ ./ c h a r m r u n ./ E x V a r M s g ++ local

2.3.3 Mensagens no modosomente leitura

Al´em de viabilizar a passagem de parˆametros entre objetos remotos, as mensagens podem cumprir um papel importante quando se faz necess´ario o compartilhamento de dados – como em um banco de dados. Imaginando dados que dever˜ao ser consultados por todos os objetos concorrentes, estes poderiam ser acomodados em uma mensagem e disponibilizados atrav´es da mesma como somente leitura(readonly). O Charm++ tratar´a esta mensagem como se fosse global e ter´a visibilidade para todos os objetos concorrentes.

2.3.4 Mensagem de linha de comando

Vocˆe deve ter percebido que o construtor do mainchare declara uma mensagem como argumento: CkArgMsg* marg. Que mensagem ´e esta?

(36)

de parˆametros passados em linha de comando (incluindo o nome do programa) echar* argv[]s˜ao os parˆametros propriamente ditos na forma destrings.

No Charm++, os parˆametros de linha de comando s˜ao passados ao construtor do mainchareatrav´es da mensagem instanciada a partir da classeCkArgMsg. Ela deve ser declarada como ponteiro pelo mesmo motivo apresentado anteriormente; quem trata da mensagem ´e okerneldo Charm++. Esta mensagem possui dois campos principais que s˜ao os mesmos da func¸˜aomain:int argcechar* argv[].

O desenvolvedor pode criar outros construtores paramainchare, mas um constru-tor obrigat´orio ´e o construtor que recebe uma mensagem da classeCkArgMsg. Esse n˜ao pode faltar.

(37)

Cap´ıtulo 3

Estruturas de objetos concorrentes

3.1

Lista de objetos concorrentes

A lista de objetos concorrentes ´e uma colec¸˜ao decharesreferenciados por meio de ´ındices. Pode ter qualquer quantidade de PEs (n˜ao est´a restrita ao n´umero de

processa-dores do recurso computacional utilizado – hardware, rede,cluster,grid.

Sendo cada elemento da lista umchare, todas as caracter´ısticas apresentadas para objetos concorrentes simples se aplicam aos elementos da lista. A lista dechares´e decla-rada na interface do Charm++ usando a palavra chavearray[nD], onden´e um inteiro (1..6), e a classe do objeto em C++ ´e filiada a classe primitivaCBase arrayTipocomo em umchare.

// . ci

array[1 D ] a r r a y 1 D T i p o { /* metodos de entrada ... */ }

array[2 D ] a r r a y 2 D T i p o { /* metodos de entrada ... */ }

array[3 D ] a r r a y 3 D T i p o { /* metodos de entrada ... */ }

array[4 D ] a r r a y 4 D T i p o { /* metodos de entrada ... */ }

array[5 D ] a r r a y 5 D T i p o { /* metodos de entrada ... */ }

array[6 D ] a r r a y 6 D T i p o { /* metodos de entrada ... */ }

// . h

class a r r a y 1 D T i p o : public C B a s e _ a r r a y 1 D T i p o {...}

class a r r a y 2 D T i p o : public C B a s e _ a r r a y 2 D T i p o {...}

class a r r a y 3 D T i p o : public C B a s e _ a r r a y 3 D T i p o {...}

class a r r a y 4 D T i p o : public C B a s e _ a r r a y 4 D T i p o {...}

class a r r a y 5 D T i p o : public C B a s e _ a r r a y 5 D T i p o {...}

class a r r a y 6 D T i p o : public C B a s e _ a r r a y 6 D T i p o {...}

A lista ´e referenciada e alocada a partir do objeto CProxy arrayTipo no PE de ´ındice 0. Por outro lado, os elementos reais da lista s˜ao criados e destru´ıdos dinamica-mente em qualquer PE e podem ser movidos (migrarem) de um PE para outro em func¸˜ao de estrat´egias de balanceamento de carga.

(38)

Para alocar a lista com a dimens˜ao desejada, utiliza-se o m´etodockNew(params,lista de n´umero de elementos). A partir da dimens˜ao 3, a lista de n´umero de elementos deve ser inserida usando um objeto espec´ıfico chamadoCkArrayOptions. No quadro a seguir, vˆe-se as formas de alocac¸˜ao para cada dimens˜ao.

// . c . cc . C . cpp

C P r o x y _ a r r a y 1 D T i p o a r r 1 D N o m e ;

a r r 1 D N o m e = C P r o x y _ a r r a y 1 D T i p o :: ckNew ( args , dim1 );

C P r o x y _ a r r a y 2 D T i p o a r r 2 D N o m e ;

a r r 2 D N o m e = C P r o x y _ a r r a y 2 D T i p o :: ckNew ( args , dim1 , dim2 );

C P r o x y _ a r r a y 3 D T i p o a r r 3 D N o m e ;

a r r 3 D N o m e = C P r o x y _ a r r a y 3 D T i p o :: ckNew ( args , dim1 , dim2 , dim3 );

C P r o x y _ a r r a y 4 D T i p o a r r 4 D N o m e ;

C k A r r a y O p t i o n s opts = C k A r r a y O p t i o n s ( dim1 ,... , dim4 ); a r r 4 D N o m e = C P r o x y _ a r r a y 4 D T i p o :: ckNew ( args , opts );

C P r o x y _ a r r a y 5 D T i p o a r r 5 D N o m e ;

C k A r r a y O p t i o n s opts = C k A r r a y O p t i o n s ( dim1 ,... , dim5 ); a r r 5 D N o m e = C P r o x y _ a r r a y 5 D T i p o :: ckNew ( args , opts );

C P r o x y _ a r r a y 6 D T i p o a r r 6 D N o m e ;

C k A r r a y O p t i o n s opts = C k A r r a y O p t i o n s ( dim1 ,... , dim6 ); a r r 6 D N o m e = C P r o x y _ a r r a y 6 D T i p o :: ckNew ( args , opts );

Os m´etodos de entrada dos elementos da lista podem ser invocados individual-mente ou de forma conjunta (todos os elementos da lista).

Para a invocac¸˜ao individual, s˜ao necess´arios os ´ındices do elemento e o nome do m´etodo de entrada de interesse.

// . c . cc . C . cpp

// i n v o c a n d o M e t o d o E n t r a d a do e l e m e n t o ( i )

a r r 1 D N o m e ( i ). M e t o d o E n t r a d a A ( params );

// i n v o c a n d o M e t o d o E n t r a d a do e l e m e n t o (i , j )

a r r 2 D N o m e (i , j ). M e t o d o E n t r a d a B ( params );

// i n v o c a n d o M e t o d o E n t r a d a do e l e m e n t o (i ,j , k )

a r r 3 D N o m e (i ,j , k ). M e t o d o E n t r a d a C ( params );

// i n v o c a n d o M e t o d o E n t r a d a do e l e m e n t o (i ,j ,k , l )

a r r 4 D N o m e (i ,j ,k , l ). M e t o d o E n t r a d a D ( params );

(39)

39

a r r 5 D N o m e (i ,j ,k ,l , m ). M e t o d o E n t r a d a E ( params );

// i n v o c a n d o M e t o d o E n t r a d a do e l e m e n t o (i ,j ,k ,l ,m , n )

a r r 6 D N o m e (i ,j ,k ,l ,m , n ). M e t o d o E n t r a d a F ( params );

A linguagem Charm++ tamb´em implementa um mecanismo para invocac¸˜ao de m´etodos de entrada por difus˜ao (broadcast) de forma que, em apenas uma instruc¸˜ao, o mesmo m´etodo de entrada ´e invocado simultaneamente em todos os elementos da lista. Para isto, basta retirar-se os ´ındices do elemento da lista1.

// . c . cc . C . cpp

// i n v o c a n d o metodo de entrada na lista toda ( b r o a d c a s t )

a r r 1 D N o m e . M e t o d o E n t r a d a A ( params ); a r r 2 D N o m e . M e t o d o E n t r a d a B ( params ); a r r 3 D N o m e . M e t o d o E n t r a d a C ( params ); a r r 4 D N o m e . M e t o d o E n t r a d a D ( params ); a r r 5 D N o m e . M e t o d o E n t r a d a E ( params ); a r r 6 D N o m e . M e t o d o E n t r a d a F ( params );

Uma vez dentro de um m´etodo de entrada remoto, o elemento da lista pode recu-perar seus ´ındices atrav´es do atributothisIndex. Este atributo se adapta `a dimens˜ao da lista:

lista 1 D : t h i s I n d e x

lista 2 D (x , y ) : t h i s I n d e x .x , t h i s I n d e x . y

lista 3 D (x ,y , z ): t h i s I n d e x .x , t h i s I n d e x .y , t h i s I n d e x . z

lista 4 D (w ,x ,y , z ): t h i s I n d e x .w , t h i s I n d e x .x , t h i s I n d e x .y , t h i s I n d e x . z

lista 5 D (v ,w ,x ,y , z ): t h i s I n d e x .v , t h i s I n d e x .w , t h i s I n d e x .x , t h i s I n d e x .y , t h i s I n d e x .z ,

lista 6 D ( x1 , y1 , z1 , x2 , y2 , z2 ): t h i s I n d e x . x1 , t h i s I n d e x . y1 , t h i s I n d e x . z1 , t h i s I n d e x . x2 , t h i s I n d e x . y2 , t h i s I n d e x . z2

O Charm++ permite a criac¸˜ao de listas vazias e a inserc¸˜ao individual de elemen-tos que se realiza atrav´es do m´etodo primitivoarrayNome(´ındices).insert(params).

1Deve-se ter em mente, sempre, que entre os objetosPROXY’s e os objetos concorrentes reais existe o

(40)

Ap´os a inserc¸˜ao de todos os elementos necess´arios, deve-se invocar o m´etodo primi-tivo arrayNome.doneInserting() (invocac¸˜ao em broadcast). Somente a partir desta invocac¸˜ao ´e que os objetos inseridos poder˜ao “entrar em ac¸˜ao”.

Veja um exemplo para o caso de uma lista unidimensional. Ser´a criada uma lista vazia e depois ser˜ao inseridos dois elementos de ´ındices 2 e 10. Veja que n˜ao h´a neces-sidade de se utilizar ´ındices em um intervalo fechado.

// . ci

array[1 D ] a r r a y 1 D e x { /* metodos de entrada ... */ }

// . h

class a r r a y 1 D e x : public C B a s e _ a r r a y 1 D e x {...}

// . c . cc . C . cpp

C P r o x y _ a r r a y 1 D e x p r o x y _ a r r ;

// criando lista vazia

p r o x y _ a r r = C P r o x y _ a r r a y 1 D e x :: ckNew ();

// i n s e r i n d o ( criando ) os e l e m e n t o s de indice 2 e 10

p r o x y _ a r r (2). insert ( params ); p r o x y _ a r r (10). insert ( params );

// e n c e r r a n d o as i n s e r c o e s ( b r o a d c a s t )

p r o x y _ a r r . d o n e I s e r t i n g ();

Por fim, os elementos da lista podem ser destru´ıdos individualmente atrav´es do m´etodo primitivo arrayNome(´ındices).ckDestroy(). Ap´os a destruic¸˜ao de um ele-mento, este pode ser novamente inserido usando o m´etodo primitivoarrayNome(´ ındi-ces).insert(params).

Apresenta-se, a seguir, um exemplo de uso simples de uma lista de 3 dimens˜oes.

// . ci

m a i n m o d u l e pgm {

// -// objeto PROXY p r i n c i p a l r e f e r e n c i a d o " g l o b a l m e n t e " // -r e a d o n l y C P r o x y _ m a i n m a i n P r o x y ;

// -// chare p r i n c i p a l

// -m a i n c h a r e main

{

(41)

41

entry main ( C k A r g M s g * m );

// metodo

entry void r e s u l t a d o (int pe ); };

// -// chare array 3 D remoto

// -array [3 D ] remoto

{

// c o n s t r u t o r

entry remoto (void);

// metodo remoto

entry void metodo (void); };

};

// . h

# ifndef PGM_H

# define PGM_H

// -// r e f e r e n c i a a classe p r i n c i p a l ( mestre )

// -extern C P r o x y _ m a i n m a i n P r o x y ;

// -// classe p r i n c i p a l ( mestre )

// -class main : public C B a s e _ m a i n

{

private:

int cont ;

public:

// -// c o n s t r u t o r

//

-main ( C k A r g M s g * m );

// -// metodo de entrada da classe p r i n c i p a l

// -void r e s u l t a d o (int pe ) {

cont - -;

C k P r i n t f (" \ t C o n t a t o do PE % d \ n ", pe );

if (! cont ) {

C k P r i n t f (" V o l t a m o s para o mestre ( PE % d ).\ n \ n ", CkMyPe ());

(42)

} } };

// -// classe c o n c o r r e n t e ( escravo )

// -class remoto : public C B a s e _ r e m o t o

{

public:

// -// c o n s t r u t o r

//

-remoto (void) {}

// d e c l a r a c a o de c o n s t r u t o r necessaria , pois os

// e l e m e n t o s da lista podem migrar de um PE para outro

remoto ( C k M i g r a t e M e s s a g e * marr ) {}

// -// metodo de entrada do objeto c o n c o r r e n t e

// -void metodo (void) {

int pe = CkMyPe ();

C k P r i n t f (" \ t \ t E l e m e n t o (% d ,% d ,% d ) no PE % d \ n ",

t h i s I n d e x .x , t h i s I n d e x .y , t h i s I n d e x .z , pe ); m a i n P r o x y . r e s u l t a d o ( pe );

} };

# endif

// . C . cc . cpp . c

// -# include " pgm . decl . h "

//

-# include < math .h >

# include " pgm . h "

// -// r e f e r e n c i a a classe p r i n c i p a l ( mestre )

//

-C P r o x y _ m a i n m a i n P r o x y ;

// -// c o n s t r u t o r da classe p r i n c i p a l ( mestre )

//

-main :: -main ( C k A r g M s g * m ) {

(43)

43

if (m - > argc != 4) { C k P r i n t f (" \ n ");

C k P r i n t f (" linha de comando deve ser :\ n \ n ");

C k P r i n t f (" \ t .\\ c h a r m r u n .\\ pgm < ne1 > < ne2 > < ne3 > " " +p <n > ++ local \ n \ n ");

C k P r i n t f (" \ tonde :\ n ");

C k P r i n t f (" \ t \t < ne1 >: num . de elem . da 1 a d i m e n s a o \ n "); C k P r i n t f (" \ t \t < ne2 >: num . de elem . da 2 a d i m e n s a o \ n "); C k P r i n t f (" \ t \t < ne3 >: num . de elem . da 3 a d i m e n s a o \ n "); C k P r i n t f (" \ t \t <n > : numero de PEs \ n ");

C k P r i n t f (" \ n \ n ");

C k P r i n t f (" \ t e x e m p l o :\ n \ n ");

C k P r i n t f (" \ t .\\ c h a r m r u n .\\ pgm 2 3 2 + p6 ++ local \ n \ n "); CkExit ();

}

ne1 = atoi (m - > argv [1]); ne2 = atoi (m - > argv [2]); ne3 = atoi (m - > argv [3]);

delete m ;

// -// d e c l a r a n d o o PROXY da lista p r o c e s s o da classe remoto //

-C P r o x y _ r e m o t o p r o c e s s o ;

// -// r e f e r e n c i a ao objeto m a i n P r o x y no p r o c e s s a d o r ’ mestre ’ //

-m a i n P r o x y = t h i s h a n d l e ;

// -// total de e l e m e n t o s

//

-cont = ne1 * ne2 * ne3 ;

C k P r i n t f (" \ n ");

C k P r i n t f (" Mestre em PE % d .\ n ", CkMyPe ()); C k P r i n t f (" Total de PEs : % d \ n ", C k N u m P e s ());

C k P r i n t f (" Total de e l e m e n t o s da lista : (% d ,% d ,% d )\ n ", ne1 , ne2 , ne3 );

// -// usando objeto da classe C k A r r a y O p t i o n s

//

(44)

// -// i n v o c a n d o metodo remoto por b r o a d c a s t

//

-p r o c e s s o . metodo (); }

// -# include " pgm . def . h "

//

-$ < caminho do compilador >/ charmc -c pgm . ci $ < caminho do compilador >/ charmc -o pgm pgm . C $ ./ c h a r m r u n ./ pgm 3 3 3 + p4 ++ local

3.2

Colec

¸˜

oes de objetos concorrentes

3.2.1 Grupos de objetos concorrentes

Um grupo de objetos concorrente ´e um tipo especial de organizac¸˜ao de objetos remotos. Cada grupo ´e uma colec¸˜ao de objetos, como a lista, com um e apenas um membro do grupo por processador. Todos os membros de grupo partilham uma mesma identificac¸˜ao. Um membro espec´ıfico pode ser acessado identificando-se o processador onde ele reside. Isto fere a caracter´ıstica b´asica oferecida pelo Charm++ que ´e n˜ao se preocupar onde o objeto est´a. Mas, em casos espec´ıficos em que um membro em particular precisa ser acessado, ser´a necess´ario identificar o processador.

Um grupo ´e declarado na interface do Charm++ usando a palavra chavegroup. Na codificac¸˜ao em C++, o objeto de grupo ´e filiado `a mesma superclasse do chare,

CBase.

3.2.2 N´os de objetos concorrentes

3.3

Callback

e

reduction

Imagem

Figura 1.1: Caracter´ısticas do Charm++.
Figura 1.2: Troca de mensagens como princ´ıpio de funcionamento do Charm++.
Figura 1.3: Caracter´ısticas do paradigma da orientac¸˜ ao a objeto.
Figura 1.4: Papel do objeto PROXY em relac¸˜ ao ao objeto remoto.
+2

Referências

Documentos relacionados

Apenas foram submetidos aos protocolos de provocação e/ou dessensibilização com AAS, os pacientes com asma controlada e, portanto, os pacientes que tinham asma grave não

- Se o estagiário, ou alguém com contacto direto, tiver sintomas sugestivos de infeção respiratória (febre, tosse, expetoração e/ou falta de ar) NÃO DEVE frequentar

O Documento Orientador da CGEB de 2014 ressalta a importância do Professor Coordenador e sua atuação como forma- dor dos professores e que, para isso, o tempo e

Quando conheci o museu, em 2003, momento em foi reaberto, ele já se encontrava em condições precárias quanto à conservação de documentos, administração e organização do acervo,

F REQUÊNCIAS PRÓPRIAS E MODOS DE VIBRAÇÃO ( MÉTODO ANALÍTICO ) ... O RIENTAÇÃO PELAS EQUAÇÕES DE PROPAGAÇÃO DE VIBRAÇÕES ... P REVISÃO DOS VALORES MÁXIMOS DE PPV ...

I, Seltan Segued, emperor of Ethiopia, believe and profess that Saint Peter, prince of the Apostles was nominated head of the Christian Church by Christ our Lord, who bestowed

como enfoque o processo da reforma educativa em curso em Angola. Para isso, será realizada a análise à percepção dos professores e directores de escola face à

Dessa maneira, os resultados desta tese são uma síntese que propõe o uso de índices não convencionais de conforto térmico, utilizando o Índice de Temperatura de Globo Negro e