• Nenhum resultado encontrado

Introdução a Computação Paralela: Rotinas MPI em Clusters Beowulf

N/A
N/A
Protected

Academic year: 2021

Share "Introdução a Computação Paralela: Rotinas MPI em Clusters Beowulf"

Copied!
99
0
0

Texto

(1)

Introdução a Computação Paralela:

Rotinas MPI em Clusters Beowulf

Miguel Dias Costa

João Viana Lopes

(2)

Estrutura do Curso

Motivação Conceitos de Computação Paralela

Rotinas MPI (Message Passing Interface)

(3)

Estrutura do Curso

Motivação

Conceitos de Computação Paralela

Rotinas MPI (Message Passing Interface)

(4)

Estrutura do Curso

Motivação

Conceitos de Computação Paralela

Rotinas MPI (Message Passing Interface)

(5)

Recursos Online

Livro “MPI - The Complete Reference”:

http://www.netlib.org/utk/papers/mpi-book/mpi-book.html

Distribuição MPICH:

http://www-unix.mcs.anl.gov/mpi/mpich/

Distribuição LAM:

http://www.lam-mpi.org

Standards MPI:

http://www.mpi-forum.org

(6)

Bibliotecas Matemáticas

ScaLAPACK

(Scalable LAPACK)

LAPACK

(Linear Algebra PACKage)

PBLAS

(Parallel BLAS)

BLACS

(Basic Linear Algebra Communications

Subprograms)

(7)

Limitações

Limitações da Computação Sequencial Aplicações científicas exigem (tipicamente)

velocidade de processamento memória

Lei de Moore não chega

(8)

Limitações

Limitações da Computação Sequencial Aplicações científicas exigem (tipicamente) velocidade de processamento

memória

Lei de Moore não chega

(9)

Limitações

Limitações da Computação Sequencial Aplicações científicas exigem (tipicamente)

velocidade de processamento memória

Lei de Moore não chega

(10)

Limitações

Limitações da Computação Sequencial Aplicações científicas exigem (tipicamente)

velocidade de processamento memória

Lei de Moore não chega

(11)

Limitações

Limitações da Computação Sequencial Aplicações científicas exigem (tipicamente)

velocidade de processamento memória

Lei de Moore não chega

(12)

Soluções

Máquinas Paralelas de Memória Partilhada

Máquinas Paralelas de Memória Distribuída

(13)

Soluções

Máquinas Paralelas de Memória Partilhada Máquinas Paralelas de Memória Distribuída

Vantagem:

Não é necessário paralelizar explicitamente

(14)

Soluções

Máquinas Paralelas de Memória Partilhada Máquinas Paralelas de Memória Distribuída

Desvantagem:

Preço

(15)

Soluções

Máquinas Paralelas de Memória Partilhada

Máquinas Paralelas de Memória Distribuída

(16)

Soluções

Máquinas Paralelas de Memória Partilhada Máquinas Paralelas de Memória Distribuída Vantagem:

Escalonável

(17)

Soluções

Máquinas Paralelas de Memória Partilhada Máquinas Paralelas de Memória Distribuída Desvantagens:

É necessário paralelizar explicitamente

(18)

O Cluster Beowulf do CFP

(19)

Especificações

Dual-Athlons MP 1.2 MHz Motherboards Tyan Tiger

1 GB de RAM DDR por máquina

Software livre (Linux)

(20)

Single System Image

Todo o cluster comporta-se como se fosse uma única máquina, com

adição “a quente” de nodos (Beoboot) espaço de processos partilhado (Bproc) fila de espera (Beowulf Batch Queue)

monitorização em tempo real (Beostatus)

(21)

Conceitos de Computação Paralela

Paralelismo - capacidade de várias tarefas

independentes avançarem simultaneamente no sentido de completar um cálculo

Paralelismo disponível - número máximo de tarefas que podem correr simultaneamente

Por vezes reduzido ou nulo

No entanto, isto é pouco frequente. Porquê?

(22)

Conceitos de Computação Paralela

Paralelismo - capacidade de várias tarefas

independentes avançarem simultaneamente no sentido de completar um cálculo

Paralelismo disponível - número máximo de tarefas que podem correr simultaneamente Por vezes reduzido ou nulo

No entanto, isto é pouco frequente. Porquê?

(23)

Conceitos de Computação Paralela

Paralelismo - capacidade de várias tarefas

independentes avançarem simultaneamente no sentido de completar um cálculo

Paralelismo disponível - número máximo de tarefas que podem correr simultaneamente

Por vezes reduzido ou nulo

No entanto, isto é pouco frequente. Porquê?

(24)

Conceitos de Computação Paralela

Paralelismo - capacidade de várias tarefas

independentes avançarem simultaneamente no sentido de completar um cálculo

Paralelismo disponível - número máximo de tarefas que podem correr simultaneamente

Por vezes reduzido ou nulo

No entanto, isto é pouco frequente. Porquê?

(25)

Origem do Paralelismo

Usamos máquinas paralelas porque uma dada aplicação demora demasiado tempo (CPU) ou é demasiado grande (RAM).

Componente grande:

Número de Tamanho de A componente grande é, tipicamente, a fonte de

paralelismo.

(26)

Origem do Paralelismo

Usamos máquinas paralelas porque uma dada aplicação demora demasiado tempo (CPU) ou é demasiado grande (RAM).

Componente grande:

Número de partículas Tamanho de

A componente grande é, tipicamente, a fonte de

paralelismo.

(27)

Origem do Paralelismo

Usamos máquinas paralelas porque uma dada aplicação demora demasiado tempo (CPU) ou é demasiado grande (RAM).

Componente grande:

Número de parâmetros Tamanho de

A componente grande é, tipicamente, a fonte de

paralelismo.

(28)

Origem do Paralelismo

Usamos máquinas paralelas porque uma dada aplicação demora demasiado tempo (CPU) ou é demasiado grande (RAM).

Componente grande:

Número de tarefas...

Tamanho de A componente grande é, tipicamente, a fonte de

paralelismo.

(29)

Origem do Paralelismo

Usamos máquinas paralelas porque uma dada aplicação demora demasiado tempo (CPU) ou é demasiado grande (RAM).

Componente grande:

Número de tarefas...

Tamanho de estrutura A componente grande é, tipicamente, a fonte de

paralelismo.

(30)

Origem do Paralelismo

Usamos máquinas paralelas porque uma dada aplicação demora demasiado tempo (CPU) ou é demasiado grande (RAM).

Componente grande:

Número de tarefas...

Tamanho de imagem A componente grande é, tipicamente, a fonte de

paralelismo.

(31)

Origem do Paralelismo

Usamos máquinas paralelas porque uma dada aplicação demora demasiado tempo (CPU) ou é demasiado grande (RAM).

Componente grande:

Número de tarefas...

Tamanho de base de dados...

A componente grande é, tipicamente, a fonte de

paralelismo.

(32)

Origem do Paralelismo

Usamos máquinas paralelas porque uma dada aplicação demora demasiado tempo (CPU) ou é demasiado grande (RAM).

Componente grande:

Número de tarefas...

Tamanho de base de dados...

(33)

Quantidade de Paralelismo

Paralelismo “embaraçoso” : Por exemplo, correr

o mesmo cálculo para diferentes condições iniciais ou parâmetros.

Paralelismo insuficiente:

Relação causal entre

sub-tarefas dificulta a paralelização.

(34)

Quantidade de Paralelismo

Paralelismo “embaraçoso” : Por exemplo, correr o mesmo cálculo para diferentes condições iniciais ou parâmetros.

Paralelismo insuficiente:

Relação causal entre

sub-tarefas dificulta a paralelização.

(35)

Quantidade de Paralelismo

Paralelismo “embaraçoso” : Por exemplo, correr o mesmo cálculo para diferentes condições iniciais ou parâmetros.

Paralelismo insuficiente: Relação causal entre

sub-tarefas dificulta a paralelização.

(36)

Lei de Amdahl

“Se apenas 1% de um problema não pode ser paralelizado, o problema nunca pode ser resolvido

mais de 100 vezes mais rápido do que no caso sequencial, qualquer que seja o paralelismo

disponível para o resto”

No entanto, os problemas escalam, tipicamente, à

custa das componentes paralelas.

(37)

Lei de Amdahl

“Se apenas 1% de um problema não pode ser paralelizado, o problema nunca pode ser resolvido

mais de 100 vezes mais rápido do que no caso sequencial, qualquer que seja o paralelismo

disponível para o resto”

No entanto, os problemas escalam, tipicamente, à

custa das componentes paralelas.

(38)

Paralelismo em Clusters

O cenário mais comum é um problema ser

paralelizável mas de uma forma difícil de explorar com um cluster.

Comunicações demasiado frequentes podem

neutralizar a vantagem da paralelização.

(39)

Decomposição de Problemas

Decomposição por Domínios Os dados são divididos em pedaços

aproximadamente iguais e divididos entre os processadores

Decomposição por Tarefas O problema é dividido em sub-tarefas que são

atribuídas aos processadores à medida que estes

ficam disponíveis

(40)

Decomposição de Problemas

Decomposição por Domínios

Os dados são divididos em pedaços

aproximadamente iguais e divididos entre os processadores

Decomposição por Tarefas O problema é dividido em sub-tarefas que são

atribuídas aos processadores à medida que estes

ficam disponíveis

(41)

Decomposição de Problemas

Decomposição por Domínios

Os dados são divididos em pedaços

aproximadamente iguais e divididos entre os processadores

Decomposição por Tarefas

O problema é dividido em sub-tarefas que são

(42)

Classificação de Algoritmos Paralelos

Regularidade estruturas de dados rectangulares?

Sincronicidade secções diferentes têm de permanecer

sincronizadas?

razão entre comunicação e computação

(43)

Classificação de Algoritmos Paralelos

Regularidade

estruturas de dados rectangulares?

Sincronicidade secções diferentes têm de permanecer

sincronizadas?

razão entre comunicação e computação

(44)

Classificação de Algoritmos Paralelos

Regularidade

estruturas de dados rectangulares?

Sincronicidade

secções diferentes têm de permanecer sincronizadas?

razão entre comunicação e computação

(45)

Classificação de Algoritmos Paralelos

Regularidade

estruturas de dados rectangulares?

Sincronicidade

secções diferentes têm de permanecer

sincronizadas?

(46)

Objectivos da Paralelização

O principal objectivo da paralelização é obter melhor performance do que no caso sequencial. Para tal, é necessário ter em conta os seguintes aspectos:

“load balancing”

minimizar a comunicação

sobrepor comunicação e computação

(47)

Objectivos da Paralelização

O principal objectivo da paralelização é obter melhor performance do que no caso sequencial. Para tal, é necessário ter em conta os seguintes aspectos:

“load balancing”

minimizar a comunicação

sobrepor comunicação e computação

(48)

Objectivos da Paralelização

O principal objectivo da paralelização é obter melhor performance do que no caso sequencial. Para tal, é necessário ter em conta os seguintes aspectos:

“load balancing”

minimizar a comunicação

sobrepor comunicação e computação

(49)

Objectivos da Paralelização

O principal objectivo da paralelização é obter melhor performance do que no caso sequencial. Para tal, é necessário ter em conta os seguintes aspectos:

“load balancing”

minimizar a comunicação

sobrepor comunicação e computação

(50)

Comunicação

Em geral, o tempo de comunicação de uma mensagem é dado por

com

lat

tamanho

largura de banda

largura de banda

10 MB/s

latência

200

(51)

Rotinas MPI

Processo MPI :

programa C ou Fortran

(MPI-2 suporta C++ e Fortran 90) +

biblioteca MPI

(mpicc (MPICH) ou hcc (LAM) em vez do gcc)

e

(52)

Código Fonte

Em geral, todos os processos de uma aplicação MPI têm o mesmo código fonte

Como evitamos que todos os processos façam exactamente a mesma coisa?

A função MPI_COMM_RANK diz-nos qual o número de ordem de um processo dentro do comunicador

MPI_COMM_WORLD (o conjunto de todos os

processos)

(53)

Código Fonte

Em geral, todos os processos de uma aplicação MPI têm o mesmo código fonte

Como evitamos que todos os processos façam exactamente a mesma coisa?

A função MPI_COMM_RANK diz-nos qual o número de ordem de um processo dentro do comunicador

MPI_COMM_WORLD (o conjunto de todos os

processos)

(54)

Código Fonte

Em geral, todos os processos de uma aplicação MPI têm o mesmo código fonte

Como evitamos que todos os processos façam exactamente a mesma coisa?

A função MPI_COMM_RANK diz-nos qual o número

de ordem de um processo dentro do comunicador

(55)

Inicialização e Finalização

...

MPI_Init(&argc,&argv);

MPI_Comm_Rank(MPI_Comm_World, &rank);

MPI_Comm_Size(MPI_Comm_World, &size);

...

rotinas de comunicação MPI ...

MPI_Finalize();

(56)

Comunicadores

A maior parte das rotinas de comunicação MPI requer a especificação de um comunicador que define o contexto em que a comunicação é feita.

As rotinas MPI_Comm_Size e MPI_Comm_Rank permitem escrever programas que se ajustam

dinamicamente, quando executados, ao número de

processadores disponíveis.

(57)

Rotinas de Comunicação

MPI_Send e MPI_Recv

MPI_Send( buffer, count, datatype, dest, tag, comm ) MPI_Recv( buffer, count, datatype, src, tag, comm )

Conteúdo da mensagem:

(58)

Rotinas de Comunicação

MPI_Send e MPI_Recv

MPI_Send( buffer, count, datatype, dest, tag, comm ) MPI_Recv( buffer, count, datatype, src, tag, comm )

Conteúdo da mensagem:

(59)

Rotinas de Comunicação

MPI_Send e MPI_Recv

MPI_Send( buffer, count, datatype, dest, tag, comm ) MPI_Recv( buffer, count, datatype, src, tag, comm )

Conteúdo da mensagem:

buffer: dados a enviar/receber

(60)

Rotinas de Comunicação

MPI_Send e MPI_Recv

MPI_Send( buffer, count, datatype, dest, tag, comm ) MPI_Recv( buffer, count, datatype, src, tag, comm )

Conteúdo da mensagem:

count: número de elementos do tipo datatype

(61)

Rotinas de Comunicação

MPI_Send e MPI_Recv

MPI_Send( buffer, count, datatype, dest, tag, comm ) MPI_Recv( buffer, count, datatype, src, tag, comm )

Conteúdo da mensagem:

datatype: tipo de variável MPI

(62)

Rotinas de Comunicação

MPI_Send e MPI_Recv

MPI_Send( buffer, count, datatype, dest, tag, comm ) MPI_Recv( buffer, count, datatype, src, tag, comm )

Envelope (selecção de mensagens):

(63)

Rotinas de Comunicação

MPI_Send e MPI_Recv

MPI_Send( buffer, count, datatype, dest, tag, comm ) MPI_Recv( buffer, count, datatype, src, tag, comm )

Envelope (selecção de mensagens):

src/dest: número do processador origem/destino

dentro do comunicador comm

(64)

Rotinas de Comunicação

MPI_Send e MPI_Recv

MPI_Send( buffer, count, datatype, dest, tag, comm ) MPI_Recv( buffer, count, datatype, src, tag, comm )

Envelope (selecção de mensagens):

tag: etiqueta para identificar a comunicação

(65)

Rotinas de Comunicação

MPI_Send e MPI_Recv

MPI_Send( buffer, count, datatype, dest, tag, comm ) MPI_Recv( buffer, count, datatype, src, tag, comm )

Envelope (selecção de mensagens):

comm: comunicador

(66)

Tipos de Dados

datatype tem de ser um dos tipos de dados MPI:

C:

MPI_CHAR

MPI_UNSIGNED_CHAR MPI_SHORT

MPI_INT MPI_LONG

MPI_UNSIGNED_SHORT

MPI_UNSIGNED

MPI_UNSIGNED_LONG MPI_FLOAT

MPI_DOUBLE

MPI_LONG_DOUBLE MPI_BYTE

Fortran:

(67)

Hello World

#include <mpi.h>

#include <stdio.h>

int main( int argc, char **argv){

int rank, size, partner, len;

char name[MPI_MAX_PROCESSOR_NAME];

char greeting[sizeof(name) + 100];

MPI_Init(&argc, &argv);

(68)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles // e imprimo-as

// mas, se eu for um dos outros

// só envio a minha saudação

(69)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles // e imprimo-as

// mas, se eu for um dos outros

// só envio a minha saudação

(70)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles // e imprimo-as

// mas, se eu for um dos outros

// só envio a minha saudação

(71)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles // e imprimo-as

// mas, se eu for um dos outros

// só envio a minha saudação

(72)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação // Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles // e imprimo-as

// mas, se eu for um dos outros

// só envio a minha saudação

(73)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master // imprimo a minha saudação

// e para todos os outros

// recebo as saudações deles // e imprimo-as

// mas, se eu for um dos outros

// só envio a minha saudação

(74)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles // e imprimo-as

// mas, se eu for um dos outros

// só envio a minha saudação

(75)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles // e imprimo-as

// mas, se eu for um dos outros

// só envio a minha saudação

(76)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles // e imprimo-as

// mas, se eu for um dos outros

// só envio a minha saudação

(77)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles // e imprimo-as

// mas, se eu for um dos outros

// só envio a minha saudação

(78)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles // e imprimo-as

// só envio a minha saudação

(79)

Hello World

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Get_processor_name(name, &len);

sprintf(greeting, “Olá mundo: número %d de %d a correr no %s!\n”, rank, size, name);

if (rank == 0) {

fputs(greeting, stdout);

for(partner=1; partner < size; partner++) {

MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, partner, 1, MPI_COMM_WORLD, &stat);

fputs(greeting, stdout);

// Quantos processadores?

// Qual sou eu?

// Onde estou a correr?

// Escrever uma saudação

// Se eu for o master

// imprimo a minha saudação // e para todos os outros

// recebo as saudações deles

// e imprimo-as

(80)

Hello World

$ mpicc -o hello hello.c

Numa única máquina:

$ mpirun -np 4 ./hello

Olá mundo: número 0 de 4 a correr no miu-1!

Olá mundo: número 1 de 4 a correr no miu-1!

Olá mundo: número 2 de 4 a correr no miu-1!

Olá mundo: número 3 de 4 a correr no miu-1!

No cluster:

$ mpirun -np 4 -nolocal ./hello

Olá mundo: número 0 de 4 a correr no .0!

Olá mundo: número 1 de 4 a correr no .0!

Olá mundo: número 2 de 4 a correr no .1!

Olá mundo: número 3 de 4 a correr no .1!

(81)

Handshake

E quando todos enviam e recebem?

fputs(greeting, stdout);

MPI_Send(greeting, ..., partner, ...);

MPI_Recv(greeting, ..., partner, ...);

fputs(greeting, stdout);

fputs(greeting, stdout);

MPI_Send(greeting, ..., partner, ...);

MPI_Recv(greeting, ..., partner, ...);

fputs(greeting, stdout);

(82)

Handshake

E quando todos enviam e recebem?

fputs(greeting, stdout);

MPI_Send(greeting, ..., partner, ...);

MPI_Recv(greeting, ..., partner, ...);

fputs(greeting, stdout);

fputs(greeting, stdout);

MPI_Recv(greeting, ..., partner, ...);

MPI_Send(greeting, ..., partner, ...);

fputs(greeting, stdout);

(83)

Bloqueio

Quando se usam estas funções MPI_Send e MPI_Recv standard, é necessário que o envio e recepção de mensagens coincidam, sob o risco de o

programa bloquear.

Soluções:

garantir explicitamente que para cada Send

existe um Recv antes de outras funções MPI

(84)

Funções Colectivas

Operações que envolvem todos os processos dentro de um comunicador

São chamadas da mesma forma dentro de todos os processos

Os argumentos determinam as diferenças de

comportamento

(85)

Funções Colectivas

MPI_Broadcast, MPI_Gather, MPI_Scatter, MPI_Reduce

MPI_Broadcast(buffer, count, datatype, sender_rank, comm)

MPI_Reduce(send_buffer, recv_buffer, count,

datatype, operation, receiver_rank, comm)

(86)

Broadcast

Dados

Processos

A A

A

A

(87)

Broadcast

Dados

Processos

A

A

A

A

(88)

Scatter

Dados

Processos

A B C D

B

C

D

(89)

Scatter

Dados

Processos

A B C D

B

C

D

(90)

Gather

Dados

Processos

A B C D

B

C

D

(91)

Gather

Dados

Processos

A B C D

B

C

D

(92)

Reduce

Dados

Processos

A B C D (..,..,..) = MPI_SUM, MPI_PROD, MPI_MAX,

MPI_MIN, MPI_BAND, MPI_BOR, MPI_BXOR,

MPI_LAND, MPI_LOR, MPI_LXOR

(93)

Reduce

Dados

Processos

A (A,B,C,D) B

C D (..,..,..) = MPI_SUM, MPI_PROD, MPI_MAX,

MPI_MIN, MPI_BAND, MPI_BOR, MPI_BXOR,

MPI_LAND, MPI_LOR, MPI_LXOR

(94)

Reduce

Dados

Processos

A (A,B,C,D) B

C D

(..,..,..) = MPI_SUM, MPI_PROD, MPI_MAX,

MPI_MIN, MPI_BAND, MPI_BOR, MPI_BXOR,

(95)

Reduce - Exemplo

MPI_Reduce (&hist_local, &hist_global, 100, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD)

global

Np

k=1

k local

Dados

Processos

[0,0]

[1,1]

[2,2]

[3,3]

(96)

Reduce - Exemplo

MPI_Reduce (&hist_local, &hist_global, 100, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD)

global

Np

k=1

k local

Dados

[0,0]

(97)

Reduce - Exemplo

MPI_Reduce (&hist_local, &hist_global, 100, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD)

global

Np

k=1

k local

Dados

[0,0] [6,6]

(98)

Funções Avançadas

Modo de Envio:

Standard, Buffered, Ready, Synchronous Tipos de Dados Derivados

MPI-2:

criação e gestão de processos, comunicação

unilateral, operações colectivas extendidas,

(99)

Obrigado pela Atenção

Livro “MPI - The Complete Reference”:

http://www.netlib.org/utk/papers/mpi-book/mpi-book.html

Distribuição MPICH:

http://www-unix.mcs.anl.gov/mpi/mpich/

Distribuição LAM:

http://www.lam-mpi.org

Standards MPI:

http://www.mpi-forum.org

Referências

Documentos relacionados

GVT na Medida 100 minutos de ligações locais fixo–fixo para qualquer operadora e minutos excedentes gratuitos para GVT GVT Ilimitado Local Ilimitado local para qualquer número

Essa autora afirma que Coudry, ao interpretar os estudos de Jakobson, quando esse se refere à prevalência de funcionamento de um eixo na afasia, postula que

dopo aver riaffermata la validità della vita religiosa nella Chiesa e nel mondo di oggi, dichiarò che i Capitoli nella vita degli Istituti sono un esame di coscienza, che ha

Não somente mercadoria, como tem feito há muito tempo, mas primeiro e primariamente, populações – o que também não é novidade, mas está se tornando urgente, até sobrepujante

Cerca de 140 médicos cirurgiões e outros profissionais de saúde que trabalham ou têm interesse em trabalhar com pacientes obesos atendidos pelo Sistema Único de Saúde

♦ Dar sugestões para um melhor funcionamento da Escola; ♦ Participar nas diversas actividades e clubes existentes na Escola; ♦ Utilizar os serviços de refeitório, de bufete,

Caso a tensão do circuito auxiliar de comando tenha que alimentar bobinas de contatores, válvulas solenóides, instrumentos de campo, CLP, fonte de alimentação DC, IHM, etc.,

[r]