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).
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).
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):
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.