Esta atividade deve ser colocada no repositório, na pasta atividades/atividade12.
Valor: 2,0 Pontos.
Data de Entrega: 14/08/2021.
Nesta atividade, vamos relembrar a multiplicação de matrizes, já apresentada na Atividade 05. Vamos voltar no tempo e trabalhar em versões seriais da multiplicação de matrizes. A primeira etapa consiste em usar a função da da Atividade 05 e criar uma versão serial mtxMult.c que atenda os seguintes requisitos:
Nós usamos o valor 1.0 para facilitar a depuração, pois a matriz resultante fica com todos seus valores iguais a ordem da matriz após a multiplicação. Para medir o tempo de execução, vamos usar a função time, aplicada antes e depois da chamada da função de multiplicação, apenas para variar em relação ao comando que mede o tempo fora do programa.
Após a primeira versão, você deve criar o arquivo mtxMult_linemajor.c e representar a matriz como um vetor linear com ordem de linha. Para entender essa organização, considere o exemplo abaixo:
// Organização de memória inicial
a[0][0]=0;
a[0][1]=1;
a[0][2]=2;
a[1][0]=3;
a[1][1]=4;
a[1][2]=5;
a[2][0]=6;
a[2][1]=7;
a[2][2]=8;
// Organização de memória linear
a[0] = 0; a[1] = 1; a[2] = 2;
a[3] = 3; a[4] = 4; a[5] = 5;
a[6] = 6; a[7] = 7; a[8] = 8;
Em outras palavras, as linhas da matriz são representadas de forma contínua na memória, sendo a posição inicial indicada pelo vetor. O seu programa mtxMult_linemajor.c deve atender os mesmos requisitos da versão anterior, mas agora usando a nova organização de memória. Você obviamente deve adaptar a função de multiplicação e realizar aritmética entre os índices i e j da versão versão inicial para corresponder as posições adequadas do vetor, que tem apenas um índice.
Ao final, faça a comparação (results_serial.txt) entre as duas versões, de acordo com a tabela abaixo, na qual N é o tamanho da matriz.
# Core i5 4440
# N Tempo mtxMult Tempo mtxMult_linemajor
64 ... ...
256 ... ...
1024 ... ...
2048 ... ...
Na próxima atividade, iremos adaptar esse algoritmo para o MPI.
#define TAM_MAX 65536
...
sucessor = (meu_ranque + 1) % num_procs;
predecessor = (meu_ranque - 1 + num_procs) % num_procs;
...
MPI_Send(&a, 1, MPI_FLOAT, sucessor, 1, MPI_COMM_WORLD);
MPI_Send(vetor, TAM_MAX, MPI_FLOAT, sucessor, 1, MPI_COMM_WORLD);
...
MPI_Recv(&a, 1, MPI_FLOAT, predecessor, 1, MPI_COMM_WORLD);
MPI_Recv(vetor, TAM_MAX, MPI_FLOAT, predecessor, 1, MPI_COMM_WORLD);