Exercício 4 - Uso de paralelismo para aumentar o desempenho

Informações Gerais

Motivação

Objetivos

Contextualização

Para fazer paralelização nessa atividade, será usada a biblioteca OpenMP que utliza #pragma dos compiladores C para gerar código paralelo utilizando threads. Serão utilizadas 3 opções de pragmas. A primeira opção é o #pragma omp parallel, que paraleliza um bloco de código. Veja o exemplo abaixo:

#include <stdio.h>

main()
{
#pragma omp parallel
{
puts("Hello World");
}
}

Esse código pode ser compilado corretamente em qualquer compilador C mas, quando for compilado com um compilador com suporte a OpenMP, o código gerado utlizará threads para executar em paralelo. O gcc não supota OpenMP, nesse exercício o compilador C da Intel (icc) terá que ser utlizado. Para utilizar o icc, inclua no PATH o diretório /home/staff/rodolfo/intel/cc/9.0/bin e declare a variável de ambiente LD_LIBRARY_PATH com valor /home/staff/rodolfo/intel/cc/9.0/lib. Grave o código acima no arquivo hello.c e compile-o duas vezes, sem e com OpenMP:

icc hello.c -o hello
icc hello.c -o hello_openmp -openmp

Ao executar os dois programas, você verá que a versão com OpenMP imprime uma mensagem para cada processador (real ou virtual) existente no computador. O número de threads que será gerado depende do número de processadores disponíveis, mas também pode ser especificado através da variável de ambiente OMP_NUM_THREADS. Faça um teste com algumas opções para essa variável e veja as diferentes respostas. Só que, em geral, não se quer replicar apenas o código, o ideal é dividir a carga de trabalho entre as várias threads geradas. A forma simples de fazer isso é paralelizar um laço for com #pragma omp for, colocado imediatamente antes do for (há um exemplo logo abaixo na atividade). O último pragma é #pragma omp critical(variavel), que define como região crítica todo acesso à variável especificada. Também há um exemplo nessa atividade dessa construção.

Atividade

As atividades devem ser realizadas individualmente na sua totalidade. Usando o programa abaixo, compile-o e execute em um computador das salas 302 ou 303, usando o compilador da Intel.

#include <stdio.h>

#define MAXIMO 500
#define REPETICOES 10000
float A[MAXIMO][MAXIMO], B[MAXIMO][MAXIMO], C[MAXIMO][MAXIMO];

main()
{
int i, j, k;

for (i = 0; i < MAXIMO; i++)
for (j = 0; j < MAXIMO; j++) {
A[i][j] = i + j;
B[i][j] = i - j;
C[i][j] = 0;
}

#pragma omp parallel
{
#pragma omp for
for (k = 0; k < REPETICOES; k++)
for (i = 0; i < MAXIMO; i ++)
for (j = 0; j < MAXIMO; j++) {
A[i][j] += 1;
C[i][j] += A[i][j] + B[i][j];
}
}
}

Compile uma vez com cada um dos conjuntos de opções de compilação:

  1. -O0
  2. -O1
  3. -O2
  4. -O3
  5. -O3 -xN
  6. -O3 -openmp
  7. -O3 -parallel
  8. -O3 -xN -openmp
  9. -O3 -xN -parallel

A opção -xN gera código exclusivo para Pentium 4, a opção -openmp utiliza os pragmas do OpenMP para gera código paralelo e a opção -parallel tenta paralelizar automaticamente o código (sem usar os pragmas do OpenMP). Execute os programas gerados, anote o tempo e comente no relatório, indicando quais foram as influências na execução em cada caso.

#include <stdio.h>
#include <math.h>

#define LIMITE 5000000

int primo(int numero)
{
int raiz, fator;

raiz = (int) sqrt((double) numero);

for(fator = 2; fator <= raiz; fator++)
if (numero % fator == 0)
return 0;

return 1;
}


int main()
{

int quantidade = 0, numero;

#pragma omp parallel for schedule(static, 8)
for(numero = 2; numero < LIMITE; numero ++) {
int p = primo(numero);
#pragma omp critical(quantidade)
quantidade += p;
}

printf("Total de numeros primos ate %d: %d\n", LIMITE, quantidade);
}

Meça o desempenho compilando com e sem a opção -openmp. Faça uma variação do código removendo a parte schedule(static, 8) e compare o desempenho das 3 execuções. O que schedule(static, 8) faz? Consulte o manual do OpenMP.

Dica geral: Se achar que os tempos execução estiverem muito próximos, varie as constantes de configuração para alterar os tempos de execução. Indique isso no seu relatório e justifique suas escolhas.

Entrega

Enviar um relatório de, no máximo, 2 páginas, descrevendo a atividade realizada e os resultados obtidos. Analisar e comentar o resultado.