Exercício 4 - Compilador e paralelismo

Tive que alterar o código fonte do primeiro programa, olhando a implementação OpenMP, ele ainda continua com problema, só que agora não capota mais. Não é necessário reexecutar os programas, mas é importante destacar o problema no relatório. (terça, 17/04 - 15:02).

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. Nesse exercício serão usados dois compiladores diferentes, o gcc e o compilador C da Intel (icc). 

Para utilizar o icc, inclua no PATH o diretório /home/staff/rodolfo/intel/cc/9.1.046/bin e declare a variável de ambiente LD_LIBRARY_PATH com valor /home/staff/rodolfo/intel/cc/9.1.046/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

O gcc possui suporte a OpenMP a partir da versão 4.2. Houve um backport para a versão 4.1 utilizada no Fedora Core 6

gcc hello.c -o hello
gcc hello.c -o hello_openmp -fopenmp

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(nome), que define como região crítica um bloco de código (que vem logo a seguir no código).

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 e o gcc.

#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 private(i,j,k)
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 (no gcc, troque -openmp por -fopenmp e não use as opções -xN nem -parallel):

  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. Anote também o desempenho compilando com e sem a opção -openmp. Faça uma variação do código incluindo a parte schedule(static, 8) após o for e compare o desempenho das 3 execuções (sem openmp, com openmp e com openmp e schedule). O que schedule(static, 8) faz? Consulte o manual do OpenMP.

Procure por outras opções de compilação, tanto do gcc quanto do icc para testar o programa. Você consegue melhorar o desempenho mais ainda?

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.

No diretório ~rodolfo/mc723/CRC32 está o pacote CRC32 do mibench com alguns parâmetros alterados. Repita o experimento para ele também, indicando os tempos medidos e os ganhos obtidos. Teste também com as novas opções de compilação que você encontrou.

Achou alguma divergência entre os resultados relativos para os mesmos conjuntos de opções entre os compiladores? E entre os programas? Comente sobre isso.

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.