|
|
- #include <iostream>
- #include <cstdlib>
- #include <cmath>
- #include "Ttiming.h"
- #include <mpi.h>
- #include <stdio.h>
-
- using namespace std;
-
- void array_alloc(long **&arr, long arrsize)
- {
- try
- {
- arr = new long* [arrsize];
-
-
- arr[0] = new long [arrsize*arrsize];
-
- for(long i = 1; i < arrsize; ++i)
- arr[i] = arr[i-1] + arrsize;
-
- }
- catch (bad_alloc& ex)
- {
- cerr << "Could not allocate memory for array" << endl;
- exit(1);
- }
- }
-
- void vect_alloc(long *&arr, long arrsize)
- {
- try
- {
- arr = new long [arrsize];
-
- }
- catch (bad_alloc& ex)
- {
- cerr << "Could not allocate memory for vector" << endl;
- exit(1);
- }
- }
-
- void array_destroy(long **arr)
- {
- delete [] arr[0];
- delete [] arr;
- }
-
- int main(int argc, char *argv[])
- {
- long **A=NULL, **B=NULL, **C=NULL, *B_rot=NULL, *vect=NULL, *vect_c=NULL;
- long rozmiar=0;
- char *endptr;
- TTiming tt;
- long i, j;//,k;
- MPI::Status status;
-
-
-
- if (argc < 2)
- {
- cerr << "Usage: " << argv[0] << " <size>" << endl;
- exit(1);
- }
-
- rozmiar = strtol(argv[1], &endptr, 10);
-
- if (*endptr)
- {
- cerr << "Invalid array size format" << endl;
- exit(1);
- }
-
- if (rozmiar <= 0 || rozmiar > 2000)
- {
- cerr << "The number of matrix dimension must be in range [1,2000]" << endl;
- exit(1);
- }
-
- MPI::Init(argc, argv);
-
- int taskid = MPI::COMM_WORLD.Get_rank();
- int ntasks = MPI::COMM_WORLD.Get_size();
- printf("ntasks= %d : taskid= %d : Hello World!\n",ntasks,taskid);
-
- //alokacja macierzy
- array_alloc(A, rozmiar);
- if (taskid == 0)
- {
- array_alloc(B, rozmiar);
- vect_alloc(B_rot, rozmiar*rozmiar);
- }
-
- int porcja = (rozmiar*rozmiar)/ntasks + (rozmiar*rozmiar)%ntasks;
- array_alloc(C, rozmiar);
- vect_alloc(vect, porcja);
- vect_alloc(vect_c, porcja);
- if (taskid == 0)
- {
- //wypelnienie macierzy A liczbami "losowymi"
- for (long i=0; i<rozmiar; ++i)
- for (long j=0; j<rozmiar; ++j)
- A[i][j] = (long)(sin(i) * i * j) % 10;
-
- //wypelnienie macierzy B liczbami "losowymi"
- for (long i=0; i<rozmiar; ++i)
- for (long j=0; j<rozmiar; ++j)
- B[i][j] = (long)(cos(j) *(i+j)) % 10;
-
- //dokonaj obracania macierzy
- for (long i=0; i<rozmiar; ++i)
- for (long j=0; j<rozmiar; ++j)
- B_rot[i*rozmiar+j] = B[j][i];
- }
-
- //wysyłanie macierzy A do wszystkich
- MPI::COMM_WORLD.Bcast(&A[0][0], rozmiar*rozmiar, MPI::LONG, 0);
- if (taskid == 0)
- {
- cout << endl << "WEKTOR DANYCH: " << endl;
- for (i=0; i<rozmiar*rozmiar; ++i)
- cout << B_rot[i] << " ";
- cout << endl;
- }
- MPI::COMM_WORLD.Barrier();
-
- //MPI::COMM_WORLD.Scatter(&B_rot[0], porcja, MPI::LONG, &vect[0], porcja, MPI::LONG, 0);
-
-
- // każdy proces ma policzyć łącznie "porcja" pól,
- // dlatego dostaje wektory kolumn, w których leżą porcje
- long pos, pocz, kon;
- for (i=0; i<ntasks; ++i)
- {
- porcja = (i == ntasks - 1) ? rozmiar*rozmiar%porcja : porcja;
-
- pos = i*porcja;
- pocz = pos - (pos%rozmiar);
- kon = pos+porcja - ((pos+porcja)%rozmiar) - 1;
- MPI::COMM_WORLD.Isend(&B_rot[pocz], kon-pocz, MPI::LONG, i, 0);
- }
-
- // w przypadku gdy iloraz wielkości macierzy i ilości programów daje resztę
- // wszystkie porcje zostają zwiększone, a ostatnia porcja w ostatnim programie
- // jest mniejsza - należy policzyć tą porcję zawczasu...
-
-
-
- /*
- tt.Begin();
- for (i=0; i<rozmiar; ++i)
- for (j=0; j<rozmiar; ++j)
- {
- C[i][j] = 0;
- for (long k=0; k<rozmiar; ++k)
- C[i][j] += A[i][k]*B[k][j];
- }
-
- long elapsed = tt.End();
-
- cout << "Time: " << elapsed << " ms" << endl;
-
-
- array_destroy(A);
- array_destroy(B);
- array_destroy(C);
- */
-
- /*
- cout << taskid << ": " ;
-
- for (i=0; i<porcja; ++i)
- cout << vect[i] << " ";
- cout << endl;
- */MPI::Finalize();
-
- exit(0);
- }
|