Computação Embaraçosamente Paralela
Computação embaraçosamente paralela
• Um processamento que pode ser dividido em um
número de partes completamente independentes, cada
uma podendo se executada por um processador
diferente
Dados de
entrada
Processos
Resultados
Criação dinâmica de processos com técnica
mestre-escravo
spawn()
send()
Envio de
dados iniciais
recv()
Escravos
Mestre
send()
recv()
Coleta resultados
Exemplos
(a) Deslocamento: deslocar um objeto de x na dimensão
x e y na dimensão y
x   x  x
y  y  y
(b) Mudança de escala: mudar a escala de um objeto por
um fator Sx na dimensão x e por Sy na dimensão y
x  xSx
y  ySy
(c) Rotação: rotacionar um objeto de um ângulo  em
relação à origem do sistema de coordenadas
x  x cos  y sin 
y   x sin   y cos
Partição em regiões para os processos
individuais
x
Processo
80
y
640
80
480
Mapeia
Partição em regiões para os processos
individuais
Processo
10
640
Mapeia
480
Pseudocódigo para executar deslocamento
de imagem
• Mestre
for (i=0, row=0; i < 48; i++, row = row+10)
send (row, Pi); }
for (i=0; i < 480; i++)
for (j=0; j < 640; j++)
temp_map[i][j]=0;
for (i=0; i < (640*480); i++) {
recv(oldrow, oldcol, newrow, newcol, Pany);
if !((newrow < 0) || (newrow >=480) || (newcol < 0) || newcol >=640))
temp_map[newrow][newcol]=map[oldrow][oldcol]; }
for (i=0; i < 480; i++)
for (j=0; j < 640; j++)
map[i][j]= temp_map[i][j];
Pseudocódigo para executar deslocamento
de imagem
• Escravo
recv(row, Pmestre);
for (oldrow=row; oldrow < (row +10); oldrow++)
for (oldcol=0; oldcol < 640; oldcol++) {
newrow = oldrow + delta_x;
newcol = oldcol + delta_y;
send (oldrow, oldcol,newrow,newcol,Pmestre);
}
Análise de complexidade
• Seqüencial
ts  2n2  O(n2 )
• Paralela
– Comunicação
tcomm  tstartup  mtdata  p(tstartup  tdata )  n2 (tstartup  4tdata )  O( p  n2 )
– Computação
tcomp
 n2 
 2   O n 2 / p
 p

– Tempo total de execução
t p  tcomp  tcomm
Para uma constante p, O(n2)

Conjunto de Mandelbrot
• Conjunto de pontos no plano complexo que são quase
estáveis (diminuem e aumentam, mas não passam de
certo limite) quando calculados pela iteração da função
zk 1  zk2  c
onde z k 1 é a (k+1) iteração do número complexo z=a+bi
e c é um número complexo que dá a posição do ponto
no plano complexo
• Valor inicial de z é 0 e iterações são executadas até que
a magnitude de z (zlength) seja maior que 2 ou número de
iterações alcançou limite máximo
zlength  a 2  b 2
Conjunto de Mandelbrot
• Simplificando o cálculo de zk 1  zk2  c
z 2  a 2  2abi  b 2i 2  a 2  b 2  2abi
Cálculo do valorde z para cada iteração
z real  z real  zimag  creal
2
2
zimag  2 z real zimag  cimag
2
Rotina seqüencial para calcular valor de
um ponto retornando número de iterações
structure complex {
float real;
float imag;
}
int cal_pixel(complex c)
{
int count, max;
complex z;
float temp, lengthsq;
max=256;
z.real=0; z.imag=0;
count=0;
do {
temp=z.real*z.real -z.imag*z.imag +c.real;
z.imag=2*z.real*z.imag + c.imag;
z.real=temp;
lengthsq=z.real*z.real+z.imag*z.imag;
count ++
} while ((lengthsq < 4.0) && (count < max));
return count;
}
Mudança de escala do sistema de
coordenadas
• Para ser eficiente computacionalmente:
scale_real=(real_max - real_min)/disp_width;
scale_imag = (imag_max - imag_min)/disp_height;
• Incluindo a mudança de escala, temos o seguinte código
for (x = 0; x < disp_width; x++)
for (y = 0; y < disp_height; y++) {
c.real = real_min +((float) x * scale_real);
c.imag = imag_min + ((float) y * scale_imag);
color = cal_pixel(c);
display(x, y, color);
}
Paralelizando o cálculo do conjunto de
Mandelbrot com alocação dinâmica de
tarefas
Pool de trabalho
(xa,ya)
(xe,ye)
(xc,yc)
(xb,yb)
Tarefa
Retorna resultados/
pede nova tarefa
(xd,yd)
Código para a técnica de pool de trabalho
• Mestre
count = 0;
row = 0;
for (k=0; k < procno; k++) {
send(&row, Pk, data_tag);
count++;
row++;
}
do {
recv (&slave, &r, color, Pany, result_tag);
count--;
if (row < disp_height) {
send (&row, Pescravo, data_tag);
row ++;
count ++;
} else
send (&row, Pescravo, terminator_tag);
display ( r, color);
} while (count > 0);
Código para a técnica de pool de trabalho
• Escravo
recv(y, Pmestre, ANYTAG, source_tag);
while (source_tag == data_tag) {
c.imag = imag_min + ((float) y * scale_imag);
for (x = 0; x <disp_width; x++) {
c.real = real_min + ((float) x * scale_real);
color[x] = cal_pixel(c);
}
send (&i, &y, color, Pmestre, result_tag);
recv (y, Pmestre, source_tag);
};
Terminação do contador
Linhas tratadas nos escravos (count)
0
Término
Linha enviada
Incremento
disp_height
Linha retornada
Decremento
Análise de complexidade
• Seqüencial
ts  max n  O(n)
• Paralelo
– Fase 1: Comunicação - um número de linha é enviado para cada escravo
tcomm1  s(tstartup  tdata )
– Fase 2: Computação - Escravos executam o cálculo de Mandelbrot em
paralelo
tcomp 
max  n
s
– Fase 3: Comunicação - Resultados são enviados para o mestre por envios
individuais
tcomm 2  u(tstartup  vtdata )
– Complexidade geral
max  n
tp 
 s (t startup  t data )  u (t startup  vt data )
s
Métodos de Monte Carlo
•
A base dos métodos de Monte Carlo é utilizar seleções aleátorias para os
cálculos
•
Exemplo: Cálculo de 
2
Área = 
Área total=4
Área do círculo  (1) 2 


Área do quadrado 2  2 4
2
•
•
Pontos dentro do quadrado são escolhidos aleatoriamente e verifica-se a
fração desses pontos que está dentro do círculo
Dado um número suficiente de amostras aleatórias, essa fração será /4
Calculando uma integral
f(x)
1
1
y  1 x
1
2

0
1  x 2 dx 

4
x
1
Um par de números aleatórios (xr, yr) pode ser gerado entre 0 e 1 e contado
como dentro do círculo se y r  1  xr2 , ou seja, yr2  xr2  1
Calculando uma integral (método
alternativo)
• Gere valores aleatórios para x entre x1 e x2, calcule f(x) e
a soma dos valores de f(x)
Área 
x2

x1
1
f ( x)dx  lim
N  N
• Exemplo: Calcular
x2
N
 f ( x )( x
i 1
r
I   ( x 2  3x)dx
sum = 0;
for (i = 0; i < N; i++) {
xr = rand_v(x1, x2);
sum = sum + xr*xr -3 *xr;
}
area = (sum /N) * ( x2-x1);
x1
2
 x1 )
Implementação paralela
Mestre
Soma
parcial
Pedido
Escravos
Número
aleatório
Processo gerador
de números aleatórios
Pseudocódigo
• Mestre
for (i = 0; i < N/n; i++) {
for (j = 0; j < n; j+=)
xr[j] = rand ();
recv(Pany, req_tag, Pfonte);
send(xr, &n, Pfonte, compute_tag);
}
for (i = 0; i < slave_no; i++) {
recv(Pi, req_tag);
send(Pi, stop_tag);
}
sum=0;
reduce_add(&sum, Pgroup);
Pseudocódigo
• Escravo
sum = 0;
send(Pmaster, req_tag);
recv(xr, &n, Pmestre, source_tag);
while (source_tag == compute_tag) {
for (i = 0; i < n; i++)
sum = sum +xr[i] * xr[i] -3 * xr[i];
send(Pmestre, req_tag);
recv(xr, &n, Pmaster, source_tag);
}
reduce_add(&sum, Pgroup);
Geração de números aleatórios
• Geração de uma seqüência de números pseudo
aleatórios
x1 , x2, x3 ,..., xi 1 , xi , xi 1 ,..., xn 1 , xn
xi 1  (axi  c) modm
Geração paralela de números aleatórios
xi 1  (axi  c) modm
xi  k  ( Axi  C ) modm
onde A  a k modm, C  c(a k 1  a k  2  ...  a1  a 0 ) modm
x1
x2
xk-1
xk
xk+1
xk+2
x2k-1
x2k
Download

c - PUC-Rio