39
OOPS OOPS Object-Oriented Parallel Object-Oriented Parallel System System Um framework de classes para programação científica paralela. Eloiza Helena Sonoda Orientador: Prof. Dr. Gonzalo Travieso Apoio financeiro

Eloiza Helena Sonoda

  • Upload
    ardice

  • View
    44

  • Download
    1

Embed Size (px)

DESCRIPTION

OOPS Object-Oriented Parallel System Um framework de classes para programação científica paralela. Eloiza Helena Sonoda. Orientador: Prof. Dr. Gonzalo Travieso. Apoio financeiro. Introdução. - PowerPoint PPT Presentation

Citation preview

Page 1: Eloiza Helena Sonoda

OOPSOOPSObject-Oriented Parallel Object-Oriented Parallel

SystemSystemUm framework de classes para programação científica

paralela.

Eloiza Helena Sonoda

Orientador: Prof. Dr. Gonzalo Travieso

Apoio financeiro

Page 2: Eloiza Helena Sonoda

Introdução

O desenvolvimento da tecnologia dos microprocessadores tem resultado em grande desempenho dos computadores.

O processamento paralelo tem se mostrado bastante apropriado para satisfazer a demanda crescente de desempenho computacional.

Aumento na disponibilidade de sistemas paralelos.

Page 3: Eloiza Helena Sonoda

Introdução

Aplicações com alta demanda de poder computacional tendem a ser desenvolvidas usando programação concorrente para execução paralela.

A programação concorrente é bastante complexa e a responsabilidade de desenvolver aplicações paralelas eficientes acaba sendo do programador da aplicação.

Tornam-se necessárias ferramentas apropriadas para auxiliar no desenvolvimento de aplicações paralelas.

Page 4: Eloiza Helena Sonoda

Abordagens para o desenvolvimento de

ferramentasCompiladores paralelizantes.

Diretivas de paralelização.

Linguagens.

Bibliotecas.

Page 5: Eloiza Helena Sonoda

Motivação do trabalho

Argumentamos que uma abordagem promissora é baseada em ferramentas

convencionais de programação seqüencial acrescida de uma biblioteca

de classes que forneça abstrações adequadas de concorrência.

Page 6: Eloiza Helena Sonoda

OOPS Object-Oriented Parallel

SystemProposta.

Conceitos básicos.

Apresentação de classes e exemplos.

Framework OOPS

Biblioteca MPI

Programa Usuário

Page 7: Eloiza Helena Sonoda

Proposta

Projeto e implementação do framework de classes OOPS para apoiar a programação científica paralela.

Características:

Voltado a aplicações científicas com necessidade de alto desempenho.

Técnicas de orientação a objetos para organizar o desenvolvimento do programa e encapsular detalhes de paralelismo.

Page 8: Eloiza Helena Sonoda

Proposta

Memória distribuída e passagem de mensagens.

Utiliza somente ferramentas convencionais de programação acrescida de uma biblioteca de classes.

Envolvimento do programador com aspectos paralelos de projeto.

Fornecimento de abstrações próximas aos modelos matemáticos.

Page 9: Eloiza Helena Sonoda

Proposta

Processadores virtuais.

Grupos de processadores virtuais.

Topologias.

Contêineres distribuídos.

Componentes paralelos.

Composições dos componentes paralelos:

Seqüencial.

Concorrente.

Page 10: Eloiza Helena Sonoda
Page 11: Eloiza Helena Sonoda

Classes básicas

OOPS::Main

Componente paralelo principal, realiza inicialização e finalização da máquina virtual paralela.

OOPS::Group

Grupo de processadores virtuais.

OOPS::Sendable

Classe básica para objetos que serão comunicados.

Page 12: Eloiza Helena Sonoda

Classes básicas

OOPS::Partner

Parceiro em uma comunicação.

OOPS::Workgroup

Grupo de trabalho para comunicações.

OOPS::Topology

Estrutura de comunicação entre os processadores de um grupo.

OOPS::Distribution

Modos de distribuição de contêineres.

Page 13: Eloiza Helena Sonoda

Topologias

Derivadas de OOPS::Topology.Fornece comunicação ponto a ponto entre os processadores de um grupo em um arranjo e comunicação coletiva em subgrupos.OOPS::TopologyPlainOOPS::TopologyPipeOOPS::TopologyPipeRingOOPS::TopologyLinearOOPS::TopologyRingOOPS::TopologyGridOOPS::TopologyTorus

Page 14: Eloiza Helena Sonoda
Page 15: Eloiza Helena Sonoda

#include <iostream>#include <mpi++.h>

int main(int argc, char **argv) { MPI::Init(argc, argv); int size, myID; size = MPI::COMM_WORLD.Get_size(); myID = MPI::COMM_WORLD.Get_rank(); int x = 0, tag = 99; if (!myID) { std::cout << "I have x = " << x << std::endl; x++; MPI::COMM_WORLD.Send(&x, 1, MPI::INT, 1, tag); } else { MPI::COMM_WORLD.Recv(&x, 1, MPI::INT, myID - 1, tag); std::cout << "I have x = " << x << std::endl; x++; if (myID != (size - 1)) MPI::COMM_WORLD.Send(&x, 1, MPI::INT, myID + 1, tag); } MPI::Finalize(); return 0;}

Page 16: Eloiza Helena Sonoda

#include <iostream>#include <mpi++.h>

int main(int argc, char **argv) { MPI::Init(argc, argv); int size, myID; size = MPI::COMM_WORLD.Get_size(); myID = MPI::COMM_WORLD.Get_rank();

int next = myID + 1; int previous = myID - 1; if (!myID) previous = MPI::PROC_NULL; if (myID == size - 1) next = MPI::PROC_NULL; int x = 0, tag = 99;

MPI::COMM_WORLD.Recv(&x, 1, MPI::INT, previous, tag); std::cout << "I have x = " << x << std::endl; x++; MPI::COMM_WORLD.Send(&x, 1, MPI::INT, next, tag); MPI::Finalize(); return 0;}

Page 17: Eloiza Helena Sonoda

#include <iostream>#include <oops>

void OOPS::Main::executeOn(const OOPS::Group *allProcs) { OOPS::TopologyPipe topo(allProcs); int x = 0; topo.fromPrevious(x); std::cout << "I have x = " << x << std::endl; x++; topo.toNext(x);}

Page 18: Eloiza Helena Sonoda

Modos de distribuição dos contêineres

Derivadas de OOPS::Distribution.

Tamanhos locais.

Conversões entre índices locais e globais.

OOPS::DistributionBlocked

OOPS::DistributionCyclic

OOPS::DistributionNone

Page 19: Eloiza Helena Sonoda
Page 20: Eloiza Helena Sonoda

Contêineres Distribuídos

Coleções de dados parametrizados no tipo do elemento armazenado.

Particionamento de dados determinado pela topologia e modo de distribuição.

OOPS::Vector<T>

OOPS::VectorRepl<T>

OOPS::Matrix<T>

Page 21: Eloiza Helena Sonoda

const int dim = 10000;void OOPS::Main::executeOn(const OOPS::Group *allProcs) { try { OOPS::TopologyLinear topo(allProcs); OOPS::DistributionBlocked block; OOPS::Vector<double> v1(dim, block, topo), v2(dim, block, topo), v(dim, block, topo); std::ifstream a1("vector1.dat"), a2("vector2.dat"); a1 >> v1; a2 >> v2; v = v1 * v2; std::ofstream saida("result.dat"); saida << v; double s = v.sum(); if (topo.group()->myID() == 0) std::cout << "Produto escalar = " << s << std::endl; } catch(Error_NotPositive e) { ...código... } catch(...) { std::cout << "\nOOPS!!\n " << std::endl; }}

Page 22: Eloiza Helena Sonoda

const int N = 1000;void OOPS::Main::executeOn(const OOPS::Group *allProcs) { try { OOPS::TopologyLinear topo_linear(allProcs); OOPS::TopologyGrid topo_grid(allProcs, allProcs->size()); OOPS::DistributionBlocked block; OOPS::DistributionNone none; OOPS::VectorRepl<double> a(N, topo_linear); OOPS::Vector<double> b(N, block, topo_linear); std::ifstream file_vec("vector.dat"); file_vec >> a; OOPS::Matrix<double> m(N, N, block, none, topo_grid); std::ifstream file_mat(“matrix.dat"); file_mat >> m;

b = m * a;

std::ofstream saida("result.dat"); saida << b; }}

Page 23: Eloiza Helena Sonoda

Estêncil

tji

tji

tji

tji

tji uuuuu 1,,11,,11, 4

1

Page 24: Eloiza Helena Sonoda

Atualização de bordas fantasmas

Page 25: Eloiza Helena Sonoda

void OOPS::Main::executeOn(const OOPS::Group *allProcs) { try { OOPS::TopologyGrid grid(allProcs); OOPS::DistributionBlocked block; int M, N; double Ts, Ti, diff_limit; readArgs(M, N, Ts, Ti, diff_limit); int ghost = 1; OOPS::Matrix<double> a(M, N, block, block, grid, ghost), b(M, N, block, block, grid, ghost); ... inicialização das matrizes a e b ... double max_diff; do { b.syncGhostsCart(); for (int i = 0; i < b.localRowSize(); i++)

for (int j = 0; j < b.localColSize(); j++) a.local(i,j) = (b.local(i,j-1) + b.local(i,j+1) +

b.local(i-1,j) + b.local(i+1,j)) / 4.0; a.syncGhostsCart(); max_diff = 0;

Page 26: Eloiza Helena Sonoda

for (int i = 0; i < b.localRowSize(); i++)for (int j = 0; j < b.localColSize(); j++) { b.local(i,j) = (a.local(i,j-1) + a.local(i,j+1) +

a.local(i-1,j) + a.local(i+1,j)) / 4.0; double diff = fabs(b.local(i,j) - a.local(i,j)); if (diff > max_diff) max_diff = diff;}

grid.max(max_diff); } while (max_diff > diff_limit);

std::ofstream result("result.dat"); result << b; }}

Page 27: Eloiza Helena Sonoda

Intertopologias

Derivadas de OOPS::InterTopology.

Função parametrizada no tipo de componente OOPS::Execute<T>(), com T apresentando um método estático T::executeOn().

Page 28: Eloiza Helena Sonoda
Page 29: Eloiza Helena Sonoda

Composição seqüencial

void OOPS::Main::executeOn(const OOPS::Group *allProcs) { try{ OOPS::TopologyGrid topo_grid(allProcs); OOPS::DistributionBlocked block; int N; OOPS::Matrix<double> m(N, N, block, block, topo_grid); foo(m); bar(m); std::ofstream result("result.dat"); result << m; }}

Page 30: Eloiza Helena Sonoda

Composição concorrenteclass InterTopologyPipe : public OOPS::InterTopology { OOPS::Partner *next, *prev;public: InterTopologyPipe(const OOPS::Group *g) : OOPS::InterTopology(g) { int n = g->myID() + 1; int p = g->myID() - 1; if (g->isFirst()) p = OOPS::PARTNER_NULL; if (g->isLast()) n = OOPS::PARTNER_NULL; next = new OOPS::Partner(g, n); prev = new OOPS::Partner(g, p); } void toNext(int &x) const { next->send(x); } void fromPrevious(int &x) const { prev->recv(x); }};

Page 31: Eloiza Helena Sonoda

class foo {public: static void executeOn(const OOPS::Group *g, const InterTopologyPipe *it);};

class bar {public: static void executeOn(const OOPS::Group *g, const InterTopologyPipe *it);}; void foo::executeOn(const OOPS::Group *g, const InterTopologyPipe *it) { int x; ... continuação do código ... it->toNext(x);}

void bar::executeOn(const OOPS::Group *g, const InterTopologyPipe *it) { int x; it->fromPrevious(x); ... continuação do código ...}

Page 32: Eloiza Helena Sonoda

void OOPS::Main::executeOn(const OOPS::Group *allProcs) { try{ int n = 2; int *IDs; IDs = new int[n]; IDs[0] = 0; IDs[1] = 2; OOPS::Group *sub1 = allProcs->subGroup(n, IDs); IDs[0] = 1; IDs[1] = 3; OOPS::Group *sub2 = allProcs->subGroup(n, IDs); delete IDs;

InterTopologyPipe *it = new InterTopologyPipe(allProcs); OOPS::Execute<foo>(sub1, it); OOPS::Execute<bar>(sub2, it); }}

Page 33: Eloiza Helena Sonoda

Desempenho

Programa para o cálculo do fractal de Mandelbrot.

Cluster Beowulf com 8 nós de processamento.

Testes realizados com matrizes 5000x5000.

Page 34: Eloiza Helena Sonoda

int compute_mandel(const double x, const double y) { // retorna o valor de mandelbrot para o complexo (x + iy)}

void OOPS::Main::executeOn(const OOPS::Group *allProcs) { try{ OOPS::TopologyGrid grid(allProcs); OOPS::DistributionCyclic cyclic; int n_real, n_imag; double br, ur, bi, ui; readArgs(br, ur, bi, ui, n_real, n_imag); double rdelta = (ur - br) / n_real; double idelta = (ui - bi) / n_imag;

OOPS::Matrix<int> mandel(n_imag, n_real, cyclic, cyclic, grid); for (int i = 0; i < mandel.localRowSize(); i++) for (int j = 0; j < mandel.localColSize(); j++) {

OOPS::Matrix<int>::Index gi = mandel.localToGlobal(i,j);mandel.local(i,j) = compute_mandel(br+(gi.col()*rdelta)+rdelta/2,

ui-(gi.row()*idelta)-idelta/2); } std::ofstream outFile("result.dat"); outFile << mandel; }}

Page 35: Eloiza Helena Sonoda

int compute_mandel(const double x, const double y) {/* retorna o valor de mandelbrot para o complexo (x + iy)*/}

int main(int argc, char *argv[]) { double lr, ur, li, ui, dx, dy; int rr, ir; FILE *arq; int **result; int i, j; double x, y; int ix, iy; int NP, p, NPr, NPi, pr, pi, lrr, lir;

MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &NP); MPI_Comm_rank(MPI_COMM_WORLD, &p);

dx = (ur - lr) / rr; dy = (ui - li) / ir; /* Compute process grid dimensions */ NPr = (int)sqrt(NP); while (NP % NPr != 0) NPr--; NPi = NP/NPr; /* Compute position of the process on the grid */ pi = p / NPr; pr = p % NPr;

Page 36: Eloiza Helena Sonoda

/* Compute local sizes */ lir = ir/NPi + (pi < (ir % NPi)); lrr = rr/NPr + (pr < (rr % NPr)); /* Allocate local pixels */ result = (int**)malloc(lir * sizeof(int*)); for (i = 0; i < lir; i++) result[i] = (int*)malloc(lrr*sizeof(int));

/* Compute distributed mandelbrot (cyclic distribution) */ for (iy = 0; iy < lir; iy++) { y = ui - (iy*NPi+pi) * dy; for (ix = 0; ix < lrr; ix++) { x = lr + (ix*NPr+pr) * dx; result[iy][ix] = compute_mandel(x + dx/2, y - dy/2); } }

if (p > 0) { MPI_Request rq[lir]; MPI_Status st; /* Send result to process 0 */ for (iy = 0; iy < lir; iy++) MPI_Isend(result[iy], lrr, MPI_INT, 0, 0, MPI_COMM_WORLD, &rq[iy]); for (iy = 0; iy < lir; iy++) MPI_Wait(&rq[iy], &st); }

Page 37: Eloiza Helena Sonoda

else { /* Process 0: collect and write results */ int **finalresult; int partner; MPI_Status st; finalresult = (int**)malloc(ir * sizeof(int*)); for (i = 0; i < ir; i++) finalresult[i] = (int*)malloc(rr*sizeof(int)); for (iy = 0; iy < lir; iy++) for (ix = 0; ix < lrr; ix++) finalresult[iy*NPi][ix*NPr] = result[iy][ix]; for (partner = 1; partner < NP; partner++) { int ppi = partner / NPr; int ppr = partner % NPr; int plir = ir/NPi + (ppi < (ir % NPi)); int plrr = rr/NPr + (ppr < (rr % NPr)); for (iy = 0; iy < plir; iy++) MPI_Recv(result[iy], plrr, MPI_INT, partner, 0, MPI_COMM_WORLD, &st); for (iy = 0; iy < plir; iy++) for (ix = 0; ix < plrr; ix++) finalresult[iy*NPi+ppi][ix*NPr+ppr] = result[iy][ix]; } /* Create output file */ }

MPI_Finalize(); return 0;}

Page 38: Eloiza Helena Sonoda

Sobrecarga adicionada pelo OOPS

Page 39: Eloiza Helena Sonoda

Sugestões de trabalhos futuros

Extensão das classes desenvolvidas.

Entrada e saída paralela.

Balanceamento de cargas e criação dinâmica de tarefas.

Estruturas de dados irregulares.