Você está na página 1de 6

Universidade Federal do Maranhão

Algoritmos Genéticos de Memória Compartilhada


Aluno: Lucas Rodrigues Ferreira

São Luís
2019
1. Proposta de Algoritmo

O algoritmo proposto buscou paralelizar o código com as seguintes alterações, como


primeira, foi substituído o laço while por um laço for conforme exposto abaixo:

while (numGeracoes -- && Aval < MAXAVA && erro > (double) 0.0F){
numCruza=NUMCRU;
while (numCruza --){
pa1=Selecao(&P);
pa2=Selecao(&P);
if (pa1 != pa2)
CruzaBlend(&P, pa1, pa2, P.pior, xalfa);
else
P.iguais++;
if (pMuta > rand()%100){
nu_mutate (P.indiv[P.pior].var, P.tamInd, P.tamPop,
MAXGER - numGeracoes, MNUNI);
P.numMuta ++;
}
fit = funccod[funcao](P.indiv[P.pior].var, P.tamInd);
AtualizaPop(&P, P.pior, fit, MAXGER - numGeracoes);
}

#pragma omp parallel for num_threads(NUM_TH) private(pa1,pa2,fit)


shared(P)
for (numGeracoes = 0; numGeracoes < MAXGER; numGeracoes++){
if (Aval < MAXAVA && erro > (double) 0.0F){
numCruza=NUMCRU;
for(i=0; i<P.tamPop; i++) {
pa1=Selecao(&P);
pa2=Selecao(&P);
if (pa1 != pa2)
CruzaBlend(&P, pa1, pa2, P.pior, xalfa);
else
P.iguais++;
if (pMuta > rand()%100){
nu_mutate (P.indiv[P.pior].var, P.tamInd, P.tamPop,
MAXGER - numGeracoes, MNUNI);
P.numMuta ++;
}
fit = funccod[funcao](P.indiv[P.pior].var, P.tamInd);
#pragma omp critical
{
AtualizaPop(&P, P.pior, fit, MAXGER - numGeracoes);
}
}
erro= (double) P.indiv[P.melhor].fit - SOLUCAO;
}}
Outra alteração foi a utilização do for paralelo nas funções objetivo que serão
utilizadas.

double rastringin (double x[], int n)


{
register int i;
double sum = 3*n;
#pragma omp parallel for num_threads(NUM_TH) reduction(+:sum)
for (i=0; i< n; i++)
{
sum= sum + pow(x[i],2) - 3*cos(2*PI*x[i]);
}
Aval++;

return sum;
}

double rosenbrock(double x[], int n)


{
register int i;
double sum=0;
#pragma omp parallel for num_threads(NUM_TH) reduction(+:sum)
for (i=1; i< n-1; i++)
{
sum += 100*pow(x[i+1]- pow(x[i],2),2) + pow(x[i] - 1,2);
}
Aval++;

return sum;
}

double griewangk(double x[], int n)


{
register int i;
double sum = 0, pro = 1;
#pragma omp parallel for num_threads(NUM_TH) reduction(+:sum)
reduction(*:pro)
for (i=1; i<= n; i++) {
sum = sum + pow(x[i-1],2)/4000;
pro = pro * cos(x[i-1]/sqrt(i));
}
Aval++;

return (1+sum+pro);
}

double schwefel7(double x[], int n)


{
register int i;
double sum=418.2829*n;
#pragma omp parallel for num_threads(NUM_TH) reduction(+:sum)
for (i=0; i< n; i++)
{
sum += -x[i]*sin(sqrt(fabs(x[i])));
}
Aval++;

return sum;
}

double sphere(double x[], int n)


{
register int i;
double sum=0;
#pragma omp parallel for num_threads(NUM_TH) reduction(+:sum)
for (i=0; i< n; i++)
sum += pow(x[i],2);
Aval++;

return sum;
}

2. Resultados

Foram obtidos os resultados mostrados na tabela 1.

Tabela 1 – Resultados obtidos.


Número
Tempo de Tempo de
Instância de Média Melhor Resultado
Execução 1 Execução 2
Threads
Ras 1 0,28 0,28 0,28 0,38
Ras 2 0,735 0,79 0,7625 0,008
Ras 4 0,7975 0,6825 0,74 5,79
Ras 8 0,7238 0,7362 0,73 11,12
Ras 16 0,7281 0,7094 0,71875 9,35
Ros 1 0,28 0,23 0,255 7,54
Ros 2 0,7 0,8 0,75 6,52
Ros 4 0,77 0,7775 0,77375 7,67
Ros 8 0,7538 0,7688 0,7613 7,76
Ros 16 0,7137 0,7175 0,7156 9,32
Gri 1 0,31 0,32 0,315 0,21
Gri 2 0,79 0,715 0,7525 0,09
Gri 4 0,79 0,8425 0,81625 0,53
Gri 8 0,7475 0,725 0,73625 1,1
Gri 16 0,6731 0,7081 0,6906 2,3
Sch 1 0,32 0,31 0,315 377,52
Sch 2 0,65 0,66 0,655 233,53
Sch 4 0,7325 0,885 0,80875 1318,51
Sch 8 0,8425 0,6937 0,7681 1397,38
Sch 16 0,6969 0,6969 0,6969 1396,11
Sph 1 0,25 0,26 0,255 0,006
Sph 2 0,635 0,64 0,6375 0,000014
Sph 4 0,7475 0,86 0,80375 0,0032
Sph 8 0,7225 0,6963 0,7094 0,15
Sph 16 0,9831 1,075 1,02905 0,089

3. Considerações Finais

Conforme observado na Tabela 2, o speed up e a eficiência da paralelização do código


foi muito baixa. Provavelmente isto se deu pelo uso da região crítica dentro do for
paralelo. Entretanto, se não fosse utilizada a região crítica, mesmo que fosse feita a
separação das variáveis em variáveis de leitura e variáveis de escrita conforme foi
sugerido para este trabalho, iriam ocorrer problemas de consistência e de segmentation
fault (core dumped), pois dentro do for paralelo existe uma região que é sequencial, todas
as threads executam esta região simultaneamente, compartilhando variáveis, e como a
flag está setada com o mesmo valor para todas, na primeira execução todas as threads irão
ler e escrever na mesma região de memória, gerando inconsistência.

Tabela 2 – Speed up e Eficiência.


Instância Tempo Médio Speed UP Eficiência
Ras 0,28 1 1
Ras 0,7625 0,367213115 0,183606557
Ras 0,74 0,378378378 0,094594595
Ras 0,73 0,383561644 0,047945205
Ras 0,71875 0,389565217 0,024347826
Ros 0,255 1 1
Ros 0,75 0,34 0,17
Ros 0,77375 0,329563813 0,082390953
Ros 0,7613 0,334953369 0,041869171
Ros 0,7156 0,356344326 0,02227152
Gri 0,315 1 1
Gri 0,7525 0,418604651 0,209302326
Gri 0,81625 0,385911179 0,096477795
Gri 0,73625 0,427843803 0,053480475
Gri 0,6906 0,456125109 0,028507819
Sch 0,315 1 1
Sch 0,655 0,480916031 0,240458015
Sch 0,80875 0,389489954 0,097372488
Sch 0,7681 0,410102851 0,051262856
Sch 0,6969 0,452001722 0,028250108
Sph 0,255 1 1
Sph 0,6375 0,4 0,2
Sph 0,80375 0,31726283 0,079315708
Sph 0,7094 0,359458697 0,044932337
Sph 1,02905 0,24780137 0,015487586

Continuando a análise da execução do código que foi sugerido para este trabalho, a
partir da segunda execução, como há uma região crítica para fazer o switch, e este switch
varia entre 0 ou 1, metade das threads irão tentar ler uma variável que ao mesmo tempo
está sendo escrita pela outra metade das threads. Por isso, quando o código sugerido era
executado, ou ele dava um erro de segmentation fault ou ele dava um resultado incoerente
(figura 1). Por isso não foi feita a separação sugerida.

Figura 1 – Problemas do código sugerido.

Assim, verifica-se que este código, apesar de ser paralelizável, não apresenta
melhoras quando executando paralelamente com OpenMP, em alguns casos até piora.

Você também pode gostar