Introdução
- A linguagem mpC foi desenvolvida pelo Institute System Programming - Russian Academy of Sciences na segunda metada de 1990 para suportar eficientemente a programação paralela em máquinas distribuídas, especialmente, em redes heterogêneas.
- Segundo Victor Ivannikov [5]: " A linguagem mpC é baseada na noção de networks consistindo de processadores virtuais de diferentes tipos e performace conectados através de um link com diferente taxas de transmissão. Onde o usuário pode definir networks, distribute data e comunicação sobre a network. Networks são uma região do espaço computacional o qual pode ser utilizado para executar uma aplicação".
- A linguagem de programação mPC é uma extensão da linguagem ANSI C, projetada especialmente para a programação paralela entre os computadores em redes homogêneas ou heterogêneas, com maior ênfase nesta última. O principal objetivo é a resolução de determinados problemas de forma rápida e eficiente.
- Então, o programador pode descrever uma topologia de rede, criando e descartando as mesmas, distribuindo dados e computando-os sobre esta rede. Uma vantagem do mPC é justamente a possibilidade de descrever a topologia da rede e assim tentar ganhar a melhor performace possível. Descrevendo uma topologia (redes de máquinas que farão parte da estrutura que executarão uma aplicação), o mPC utiliza as informações descritas nela para mapear os processos sobre os processadores de uma máquina alvo resultando assim em uma eficiência na execução da aplicação.
-
Atualmente o ambiente de programação inclui: compilador, run-time, biblioteca e interface de linha de comando.
- Compilador - traduz um programa .mpc para uma programa .c com chamadas de funções no run time system support. (mpcc)
- Run-time system support - gerencia o espaço computacional, o qual consiste do número de processos executando sobre distributed memory machine (DMM), além disso prove a comunicação entre eles.
- Biblioteca - consiste de um número de funções o qual suporta debugging de programas mpC, bem como prove facilidade para escrever um código. (mpc.h)
- Interface de linha-de-comando - consiste de um conjunto de shell-script para criação de VPM, compilação, execução da aplicação que está sendo executada.
Conceitos básicos
Computing space and network object (network)
- Computing space, é definido como um conjunto de processadores virtuais, com diferentes capacidades de processamento conectados através de um link, que também possui diversas taxas de transmissão. Network, é uma região do espaço computacional o qual pode ser utilizado para processar uma determinada aplicação. Portanto, redes contém processadores virtuais com diferentes processamentos interligados, com links de diferentes velocidades, mas nada impede de que ele contenha computadores com mesmo grau de processamento.
Subnetwork
- Subnetworks é outra característica chave da linguagem mpC. Ela permite um programador especificar sub-regiões que já estão alocadas do espaço computacional.
Distribution of data
- No mpC é introduzida a noção de dados distribuídos. Os dados distribuído sobre uma região do espaço computacional compreendem um conjunto de componentes de qualquer um tipo, de modo que cada processador de uma determinada região possa executar algum destes componentes.
Distribution of computations
- Em mpC, informações à respeito da aplicação podem ser avaliadas não somente em um processador mas também em uma região do espaço computacional. Portanto a execução da aplicação pode ser realizada sobre uma região, a qual pode conter nós com mesmo poder de processamento ou com processamento diferente. O mesmo pode ocorrer em relação a taxa de transmissão entre os nós... alguns terem uma transmissão maior e outros menores.
Network functions
- Para suportar a criação de programas paralelos, network functions são introduzidas nesta linguagem. Network function, é chamada e executada em algum lugar da rede, onde argumentos e valores também são distribuídos sobre esta área.
Virtual Parallel Machine (VPM)
- Uma aplicação mPC, é executada sobre um conjunto de computadores definidos na Virtual Parallel Machine (VPM). Quando uma aplicação é iniciada cada computador da VPM carrega em memória uma instância da aplicação. Caso, a VPM possua nós que são compatíveis ela executa o mesmo programa para todos eles, ou seja, a aplicação é compilada em um host e enviado para os outros nós da rede. Assim sendo existe apenas um programa executável, o qual é compartilhado entre os nós da rede (broadcasting).
- Se a VPM contém nodos que não são compatíveis (iguais) então os executáveis para estes nodos deveriam ser construídos separadamente. Nestes casos, os nós não compatíveis deveriam ter cada um o seu próprio compilador, enquanto os demais nós deveriam possuir somente um ambiente de desenvolvimento instalado.
- Na VPM, o usuário pode definir apenas as máquinas individuais que serão utilizadas para o processamento paralelo. Ou grupos de máquinas com mesmo hardware que estão dentro do ambiente computacional.
- Quando falamos de grupo, deve-se levar em conta quais nós da rede são compatíveis, ou seja, possuem mesmo hardware e se eles irão compartilhar o mesmo meio de armazenamento (disco).
- Como já foi comentado, a VPM contém o nome do nó ou nós que irão fazer parte do ambiente que o mPC utilizará para fazer o processamento das aplicações. Esse processamento das aplicações pode ser feito de duas maneiras:
- Aplicação é compilada nos construtores, e então broadcasting para os demais nós dos grupos. Um membro do grupo, guarda uma cópia do executável que é compartilhada com os demais nós, o membro do grupo que guarda o executável é conhecido como keeper. O nó que compila e distribui o executável para os demais é conhecido como dispacher. O dispacher é responsável também em conhecer quais nós estão trabalhando e quais nós estão ociosos. Uma vez que ele sabe isso, é possível distribuir as tarefas com maior eficiência.
- Caso não exista grupo, mas somente máquinas que são totalmente diferentes em termos de hardware, cada uma delas deveria possuir o seu próprio compilador.
Comunicação e Sincronização
- Em programas paralelos, deve haver uma comunicação entre os processos e além disso deve haver também uma sincronização caso seja necessário. Para a comunicação entre os processos o mPC, utiliza a troca de mensagens entre eles (SEND-RECEIVE).
- O mecanismo básico de sincronização para processos paralelos que interagem via mensagem é uma barreira (barrier). A barreira é um ponto do programa paralelo onde um processo espera por todos outros processos com os quais ele sincroniza o seu trabalho. Somente depois de todos os processos sincronizados e a barreira for atingida é que a execução da aplicação pode continuar executando. Se por alguma razão alguns dos processos não chegarem a atingir a barreira, todos os outros processos irão "travar/pendurar" neste ponto do programa e o programa nuncar irá para, ou seja, ele irá travar. ( MPC_Barrier )
Onde é aplicado
- Muitos testes já foram realizados com mpC, e algumas tecnologias já foram desenvolvidas. Abaixo citamos onde o mpC pode ser utilizado:
- Eficiente uso em redes heterogêneas para executar software palarelos proprietários
- Utilizado para resolver problemas irregulares (simulação de galáxias). Tanto em redes homogêneas como em rede heterogêneas
- Utilizado para resolução de problemas regulares (problemas algébricos). Com maior eficiência quando aplicado em redes heterogêneas
Instalando o ambiente mpC
Pré-Requisitos
- Alguns pré-requisitos necessário para a instalação do mpC:
- Compilador C (qualquer um)
- MPI
- LAM MPI versão 6.3.2 ou superior
- MPICH versão 1.2.0 ou superior
- HP-MPI
- RSH - para comunicação entre os nós
Instalando MPI
- Aqui intalação específica para o sistema Mandriva... através de pacotes rpm
- Download -> lam-7.1.1-2.i586.rpm
-
http:// www.lam-mpi.org/7.1/download.php
- rpm -ivh lam-7.1.1-2.i586.rpm
- Colocar o caminho do diretório no bash_profile do usuário...(.bash_profile)
- Para testar a instalação mpicc --version
Instalando mpC
- Uma vez todos os pré-requisitos instalados é possível iniciarmos a instalação e configuração do mpC.
A versão utilizada aqui é a 2.2.0. Já está disponível para download a versão 2.3.0 beta.
- Download -> mpc2.2.0.tar.gz
- http://www.isprs.ru/~mpc/mpc-220.html
- tar -xvzf mpc2.2.0.tar.gz
- Permissão para o diretório criado: chmod -Rf 755 *
- Para iniciar a instalação basta digitar: ./install
- Ao disparar o script ./install surgirá uma série de perguntas como veremos abaixo:
| Pergunta ???? |
Explicação |
| Continue with installation: |
Deseja continuar a instalação |
| Please select installation type: 0 NORMAL / 1 SINGLE |
NORMAL: aplicação será construída em nós diferentes
SINGLE: aplicação será construída em supercomputadores/clusters |
Please select PLATAFORM:
0 LINUX
1 FREEBSD
2 SOLARIS
3 HPUX |
Em qual plataforma se deseja instalar o mpC |
Please select MPI implementation:
0 LAM
1 MPICH
2 HP-MPI |
Qual MPI está instalado na máquina |
Please select C compiler:
0 cc
1 gcc |
Escolher qual compilador C deseja utilizar |
Please select make utility:
0 make
1 gmake |
O recomendado é o gmake. |
Enter value for mpC Root Installation:
[/usr/local/mpc] |
Diretório onde será instalado o mpC |
| Look for preprocessor on you disk (yes/no) |
|
| Enter value for Path to begin search:[/] |
A partir de qual diretório iniciará a procura
pelo preprocessor |
Please select valid compilador:
0 /usr/bin/cpp
1 /usr/lib/gcc/cpp |
Escolher um compilador válido. |
- Após essas questões a instalação do mpC iniciará. Caso não ocorra nenhum erro uma mensagem será apresentada Installation succeeded, se por ventura acontecer algum erro basta olhar no arquivo log.txt que é criado dento do diretório do próprio mpC.
- Após a instalação basta exportar algumas variáveis de ambiente e pronto a instalação está completa.. :)))
- Editando o arquivo .bash_profile para exportar as variáveis MPCHOME / MPCLOCAL:
- #Configuracao das variaveis do MPC
- export MPCHOME=/usr/local/mpc/MPCHOME
- export MPCLOCAL=/usr/local/mpc/MPCLOCAL
- # User specific environment and startup programs
- PATH=$PATH:$HOME/bin:/usr/local/mpc/MPCHOME/utils:$MPCHOME:
$MPCLOCAL:/usr/local/mpc
Exemplos
- Após a instalação alguns exemplos foram testado
- Aqui apresentamos 3 programas criados em mpC. Uma vez que todo o sistemas esteja instalado e funcionando corretamente e alguns exemplos criados agora basta compilar este programa e executar. Mostraremos abaixo como isso pode ser feito.
- Passos a serem seguidos:
- Primeiro devemos inializar a Virtual Parallel Machine (VPM)
- mpccreate maquina_virtual
- Segundo devemos traduzir o programa ".mpc" para um programa ".c"
- Terceiro devemos informar que o processamento será realizado em vários hosts, e com isso é necessários despachar este código para estes hosts. (note que agora é o código ".c")
- Quarto será realizada a compilação do programa.
- mpcload -o nodes_virtual nodes_virtual.c -lm
- Agora já é possível rodarmos o programas através do comando
- Por fim, devemos encerrar a máquina virtual iniciada antes do processo realizado.
- Um exemplo de um código .mpc
#include <mpc.h>
int [*]main() {
int i;
repl int one;
repl int number_of_processes;
one = 1;
number_of_processes = one[+];
MPC_Printf("\n Quantidade de processos definidas para este processador:
%d processos. \n\n", number_of_processes);
for (i=1; i <= number_of_processes; i++) {
MPC_Printf(" Olá mundo! %d de %d processos !!!! \n",i,number_of_processes);
}
}
Existem algumas diferenças para a linguagem .c normal, por exemplo, no int [*]main() o [*] quer dizer que a aplicação será executadas em todos os processadores disponíveis do espaço computacional. Em outros casos é possível identificar um nó da rede em que o processamento será efetuado da seguinte forma int [host]main().
Abaixo o mesmo código .mpc só que agora transformado para um arquivo .c
/* This file was generated by mpC compiler
From file "nodes_hello.mpc"*/
static char* MPC_file_name="nodes_hello.mpc";
#include <mpCInternal.h>
#include <topo.h>
#include <mpc_macro.h>
static MPC_Basic MPC_int={{kMPC_Basic,"const int ",1,sizeof(const int ),1,MPC_DTN},7};
/*"/usr/local/mpc/MPCHOME/h/mpc.h"*/
int MPC_Abort(int errcode);
int MPC_Exit(int exitcode);
int MPC_Printf(const char *format,...);
double MPC_Wtime();
int MPC_Total_nodes();
void MPC_Refresh_landscape();
/* Net type SimpleNet declaration */
int MPC_NetType_SimpleNet_node(int pnum,const int *ppar,int ppower,int **pnodes,
int **plinks);
int MPC_NetType_SimpleNet_link(int pnum1,int pnum2,const int *ppar,int ppower,int **pnodes,
int **plinks);
int MPC_NetType_SimpleNet_parent(const int *ppar,int ppower,int **pnodes,int **plinks);
int MPC_NetType_SimpleNet_power(const int *ppar,int ppower,int **pnodes,int **plinks);
void MPC_NetType_SimpleNet_number2coord(int pnum,const int *ppar,int *pcoord,
int ppower,int **pnodes,int **plinks);
int MPC_NetType_SimpleNet_coord2number(const int *pcoord,const int *ppar,int ppower,
int **pnodes,int **plinks);
int MPC_NetType_SimpleNet_node(int pnum,const int *ppar,int ppower,int **pnodes,
int **plinks) {
return 2;
}
int MPC_NetType_SimpleNet_link(int pnum1,int pnum2,const int *ppar,int ppower,
int **pnodes,int **plinks) {
return 0;
}
int MPC_NetType_SimpleNet_parent(const int *ppar,int ppower,int **pnodes,int **plinks) {
/*"nodes_hello.mpc"*/
int coordinate[1];
coordinate[0] = 0;
return MPC_NetType_SimpleNet_coord2number(coordinate,ppar,ppower,pnodes,plinks);
}
int MPC_NetType_SimpleNet_power(const int *ppar,int ppower,int **pnodes,int **plinks) {
return * ppar;
}
void MPC_NetType_SimpleNet_number2coord(int pnum,const int *ppar,int *pcoord,
int ppower,int **pnodes,int **plinks) {
* pcoord = pnum;
}
int MPC_NetType_SimpleNet_coord2number(const int *pcoord,const int *ppar,
int ppower,int **pnodes,int **plinks) {
return * pcoord;
}
MPC_NetType MPC_NetType_SimpleNet={1,
MPC_NetType_SimpleNet_node,
MPC_NetType_SimpleNet_link,
MPC_NetType_SimpleNet_parent,
MPC_NetType_SimpleNet_power,
MPC_NetType_SimpleNet_number2coord,
MPC_NetType_SimpleNet_coord2number};
/*"/usr/local/mpc/MPCHOME/h/mpc.h"*/
int MPC_Assign(MPC_Net* MPC_Net_arg,
const int n,
const int *source,void *s_buffer,const int s_step,const int count,const
int *destination,void *d_buffer,const int d_step);
int MPC_Bcast(MPC_Net* MPC_Net_arg,
const int n,
const int *source,void *s_buffer,const int s_step,const int count,
void *d_buffer,const int d_step);
int MPC_Scatter(MPC_Net* MPC_Net_arg,
const int n,
const int *source,void *s_buffer,const int *disps,const int *lens,
const int count,void *d_buffer);
int MPC_Gather(MPC_Net* MPC_Net_arg,
const int n,
const int *source,void *d_buffer,const int *disps,const int *lens,
const int count,void *s_buffer);
int MPC_Barrier(MPC_Net* MPC_Net_arg,
const int n);
int MPC_Global_barrier();
int MPC_Processors_static_info(int *num_of_processors,double **performances);
int MPC_Get_number_of_processors();
void MPC_Get_processors_info(int *imap,double *dmap);
/*"nodes_hello.mpc"*/
int main(int argc, char **argv) {
MPC_Init(&argc,&argv,
MPC_The_init_strategy,
MPC_Trivial_error_print,
MPC_The_get_env,
MPC_The_strategy,
MPC_The_topology_data,
MPC_The_processors_info);
{
int i;
int one;
int number_of_processes;
MPC_Debug_source_name=MPC_file_name;
one = 1;
{
{
MPC_Reduce(&MPC_Net_global,&one,&number_of_processes,
(MPC_Dt)(&MPC_int),
(MPC_Dt)(&MPC_int),MPC_SUM);
}
;
}
MPC_Printf("\n Quantidade de processos definidas para este processador: %d processos.
\n\n",number_of_processes);
for(i = 1;i <= number_of_processes;i ++ ) {
{
MPC_Printf(" Olá mundo! %d de %d processos !!!! \n",i,number_of_processes);
}
}
MPC_Exit(0);
}
}
Ótimas referências para consultas sobre mpC (especificações sobre a linguagem), podem ser pesquisadas abaixo:
Bibliografia
- [1] Alexey Lastovetsky, "mpC - a Multi-Paradigm Programming Language for Massively Parallel Computers", ACM SIGPLAN Notices, 31(2):13-20, February 1996.
- [2] Dmitry Arapov, Alexey Kalinov, Alexey Lastovetsky, Ilya Ledovskih, and Ted Lewis, "A Programming Environment for Heterogenous Distributed Memory Machines", Proceedings of 6th Heterogenous Computing Workshop (HCW'97), IEEE Computer Society, Geneva, Switzerland, April 1997, pp.32-45
- [3] Sergey Gaissaryan, and Alexey Lastovetsky, "ANSI C Superset for Vector and Superscalar Computers and Its Retargetable Compiler", Journal of C Language Translation, 5(3):183-198, 1994
- [4] Dmitry Arapov, Alexey Kalinov, and Alexey Lastovetsky, "Resource Management in the mpC Programming Environment", Proceedings of the 30th Hawaii International Conference on System Sciences (HICSS'30), IEEE Computer Society, HI, January 1997
- [5] Dmitry Arapov, Victor Ivannikov, Alexey Kalinov, Alexey Lastovetsky, Ilya Ledovskih, and Ted Lewis, "A Parallel Language for Modular Distributed Programming", Proceedings of the 2nd Aizu International Symposium on Parallel Algorithms/Architectures Synthesis, IEEE Computer Society, Aizu, Japan, March 1997, pp. 248-255
- [6] D.Arapov, A.Kalinov, A.Lastovetsky, and I.Ledovskih, "A Language Approach to High Performance Computing on Heterogeneous Networks", Parallel and Distributed Computing Practices, 2(3), 2000, pp.87-96
- [7] A.Kalinov, and I.Ledovskikh, "The mpC parallel debugger", "Proceedings of the International Conference on Parallel and Distributed Procesing Techniques and Applications"(PDPTA'2001), CSREA Press, June 25-28, Las Vegas, Nevada, 2001, pp.1439-1445.
- [8] A.Kalinov, A.Lastovetsky, I.Ledovskih and M.Posypkin, "Effective Solving Scientific Problems on heterogeneous Networks with mpC", Journal of Computational Methods in Sciences and Engineering, Cambrige International Science Publishing, 2(1-2), 2002, pp.135-140
- [9] A.Kalinov, A.Kossatchev, A.Petrenko, M.Posypkin, and V.Shishkov, "Coverage-driven Automated Compiler Test Suite Generation", Electronic Notes in Theoretical Computer Science, Vol. 82(3), 2003, Proccedings of LDTA'2003
- [10] E.Dovolnov, A.Kalinov, and S.Klimov, "Natural Block Data Decomposition for Heterogeneous Clusters", in Proceedings of 17th International Parallel and Distributed Processing Symposium, Nice, France, April 2003
- [11] A. Kalinov, Scalability Analysis of Matrix-Matrix Multiplication on Heterogeneous Clusters, in Proceedings of 3rd ISPDC/HeteroPar'04, Cork, Ireland, July 05 - 07, 2004, IEEE CS Press, pp. 303-309