Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 1. Napišite paralelni program za množenje dviju kvadratnih matrica veličine 2000x2000, popunjenih s brojevima s pomičnim zarezom dvostruke preciznosti (double). Pokušajte napisati program tako da ima najveću moguću učinkovitost pri paralelnom korištenju resursa.
- #include <mpi.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- int main(int argc, char *argv[])
- {
- int matrixSize, rank, size;
- double *sendA, *sendB, *finalC, *recA, *recC;
- //definirnje varijabli za mjerenje userCPU i realCPU
- //double t1, t2;
- MPI::Init(argc, argv);
- size = MPI::COMM_WORLD.Get_size();
- rank = MPI::COMM_WORLD.Get_rank();
- if (rank == 0)
- {
- matrixSize = 2000;
- printf("rows is %d \n", matrixSize);
- sendA = new double[matrixSize * matrixSize];
- sendB = new double[matrixSize * matrixSize];
- finalC = new double[matrixSize * matrixSize];
- for (int i = 0; i < matrixSize; i++)
- for (int j = 0; j < matrixSize; j++)
- {
- sendA[i * matrixSize + j] = i + 1;
- }
- for (int i = 0; i < matrixSize; i++)
- for (int j = 0; j < matrixSize; j++)
- {
- sendB[i * matrixSize + j] = j + 1;
- }
- }
- MPI::COMM_WORLD.Barrier();
- MPI::COMM_WORLD.Bcast(&matrixSize, 1, MPI::INT, 0);
- //Start time t1
- //t1 = MPI::Wtime();
- recA = new double[matrixSize / size * matrixSize];
- if (sendB == NULL)
- {
- sendB = new double[matrixSize * matrixSize];
- }
- recC = new double[matrixSize / size * matrixSize];
- MPI::COMM_WORLD.Scatter(sendA, matrixSize * matrixSize / size, MPI::DOUBLE, recA, matrixSize * matrixSize / size, MPI::DOUBLE, 0);
- MPI::COMM_WORLD.Bcast(sendB, matrixSize * matrixSize, MPI::DOUBLE, 0);
- for (int i = 0; i < (matrixSize / size); i++)
- for (int j = 0; j < matrixSize; j++)
- {
- recC[i * matrixSize + j] = 0;
- for (int k = 0; k < matrixSize; k++)
- recC[i * matrixSize + j] += recA[i * matrixSize + k] * sendB[k * matrixSize + j];
- }
- MPI::COMM_WORLD.Barrier();
- MPI::COMM_WORLD.Gather(recC, matrixSize * matrixSize / size, MPI::DOUBLE, finalC, matrixSize * matrixSize / size, MPI::DOUBLE, 0);
- MPI::COMM_WORLD.Barrier();
- //End time t2
- //t2 = MPI::Wtime();
- /*
- IZRACUN realCPU Time
- double totalTime;
- double elapsedTime = t2-t1;
- MPI::COMM_WORLD.Reduce( &elapsedTime, &totalTime, 1, MPI::DOUBLE, MPI::SUM, 0 );
- */
- if (rank == 0)
- {
- /*
- IZRACUN MLFPOS
- int n_flop = 2 * matrixSize * matrixSize * matrixSize;
- double time = t2- t1;
- double mflops = n_flop / (time * 1000000);
- */
- for (int i = 0; i < matrixSize; i++)
- {
- for (int j = 0; j < matrixSize; j++)
- printf(" %.2f ", finalC[i * matrixSize + j]);
- printf("\n");
- }
- printf("Send A: \n");
- for (int i = 0; i < matrixSize; i++)
- {
- for (int j = 0; j < matrixSize; j++)
- printf(" %.2f ", sendA[i * matrixSize + j]);
- printf("\n");
- }
- printf("Send B: \n");
- for (int i = 0; i < matrixSize; i++)
- {
- for (int j = 0; j < matrixSize; j++)
- printf(" %.2f ", sendB[i * matrixSize + j]);
- printf("\n");
- }
- }
- MPI::Finalize();
- return 0;
- }
- 2. Analizirati kako podijeliti posao na dvije arhitekture (računalni splet i stolno računalo s višejezgrenim procesorom) koristeći a. MPI b. OpenMP c. MLP (MPI + OpenMP).
- a) primjer rješenja je u 1. zadatku - retci prve matrice se podijele na sve procese pomoću scattera, a cijela druga matrica se broadcasta svim procesima. Nakon što svaki proces izračuna svoj dio matrice, rezultati se skupe u konačnu matricu koristeći Gather.
- b) Za OpenMP bi se trebala koristiti #pragma omp parallel for direktiva sa dijeljenim i privatnim varijablama, te bi u tom slučaju, različite niti računale različite dijelove matrice
- c) Kod MLP arhitekture kombinirale bi se prethodne dvije metode, gdje bi se različitim procesima Scatterali dijelovi matrice, a zatim bi različite niti pojedinačnih procesa računale određene dijelove matrice.
- 3. Izračunati postignut MFLOPS
- MFLOPS u našem zadatku nismo mogli izračunati zbog problema s Wtime funkcijom (kao što je opisano u komentarima koda), no generalno se MFLOPS za množenje matrica računa kao broj operacija * n^3.
- 4. Odrediti „user CPU time“ i „real CPU time“ programa
- User CPU time je ukupno vrijeme koje korisnik percipira koje je potrebno za izračun matrice. Real CPU time je suma vremena izvođenja svakog pojedinačnog procesa, kojeg smo u kodu izračunali kao totalTime pomoću Reduce funkcije.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement