/// @file datatypes_mpi.cpp /// @brief Primer rada sa neprekidnim i vektorskim tipom podataka. /// /// Program nema drugi smisao izuzev pokaznog. /// Vredi obratiti pažnju na to kako su upareni pozivi slanja i prijema. /// @warning Program neće imati smisla za bilo koji broj procesa različit od 2. #include #include /// Najveći broj redova const int MAX_ROW_COUNT = 20; /// Najveći broj kolona const int MAX_COLUMN_COUNT = 25; /// Rang za master proces const int MASTER_RANK = 0; /// Rang za jedini radnički proces const int SLAVE_RANK = 1; /// Moguće teme point-to-point komunikacije enum Tags { SIMPLE, ///< Običan niz podataka tipa double CONTIGUOUS, ///< Izvedeni podatak tipa contiguous VECTOR, ///< Izvedeni podatak tipa vector VECTOR_AS_SIMPLE ///< Izvedeni podatak tipa vector poslat kao niz običnih podataka tipa double }; /// Promenljiva za izvedeni tip za nizove i vrste matrice MPI::Datatype rowType; /// Promenljiva za izvedeni tip za kolone matrice MPI::Datatype columnType; int main(int argc, char *argv[]) { // Broj elemenata u vrsti matrice, odnosno nizu unsigned rowElementCount; // Niz za "običan" prijem podataka tipa double double simpleRow[MAX_ROW_COUNT] = { 0 }; // Niz za isprobavanje slanja i prijema izvedenog tipa podatka za niz i vrstu matrice double sampleRow[MAX_ROW_COUNT] = { 0 }; // Niz za isprobavanje prijema izvedenog tipa podatka za kolonu matrice double sampleMatrix[MAX_ROW_COUNT][MAX_COLUMN_COUNT] = { { 0 } }; // inicijalizuj MPI MPI::Init(argc, argv); // odredi svoj poredak unutar MPI sveta (prvi je 0) unsigned rank = MPI::COMM_WORLD.Get_rank(); // odredi veličinu MPI sveta unsigned size = MPI::COMM_WORLD.Get_size(); // ako si "master", učitaj i pošalji svima potrebne podatke if (MASTER_RANK == rank) { std::cout << "Unesite neki niz, prvo broj elemenata (manji od " << MAX_ROW_COUNT << "), pa onda elementi: "; std::cin >> rowElementCount; for (unsigned i = 0; i < rowElementCount; i++) { std::cin >> sampleRow[i]; } } MPI::COMM_WORLD.Bcast(&rowElementCount, 1, MPI::UNSIGNED, MASTER_RANK); // svi učestvuju u pravljenju novih tipova rowType = MPI::DOUBLE.Create_contiguous(rowElementCount); rowType.Commit(); columnType = MPI::DOUBLE.Create_vector(rowElementCount, 1, MAX_COLUMN_COUNT); columnType.Commit(); if (MASTER_RANK == rank) { // pošalji procesu sa rangom isti red 4 puta, 3 puta kao izvedeni tip i jednom kao običan niz MPI::COMM_WORLD.Send(sampleRow, 1, rowType, SLAVE_RANK, SIMPLE); MPI::COMM_WORLD.Send(sampleRow, 1, rowType, SLAVE_RANK, CONTIGUOUS); MPI::COMM_WORLD.Send(sampleRow, 1, rowType, SLAVE_RANK, VECTOR); MPI::COMM_WORLD.Send(sampleRow, rowElementCount, MPI::DOUBLE, SLAVE_RANK, VECTOR_AS_SIMPLE); } else if (SLAVE_RANK == rank) { MPI::Status status; // prijem kao običan niz MPI::COMM_WORLD.Recv(simpleRow, rowElementCount, MPI::DOUBLE, MASTER_RANK, SIMPLE, status); // uparen prijem MPI::COMM_WORLD.Recv(sampleRow, 1, rowType, MASTER_RANK, CONTIGUOUS, status); // prijem kao prva kolona matrice MPI::COMM_WORLD.Recv(sampleMatrix[0], 1, columnType, MASTER_RANK, VECTOR, status); // i još jedan prijem kao treća kolona matrice MPI::COMM_WORLD.Recv(sampleMatrix[0]+2, 1, columnType, MASTER_RANK, VECTOR_AS_SIMPLE, status); } rowType.Free(); columnType.Free(); // odjava iz MPI sveta MPI::Finalize(); return 0; }