#include "mult.hh" #include "random.hh" // start a multiplier on every host but the one, I'm running on. void StartMultTasks (Pvm::TaskSet &Tasks) { Pvm::HostSet Hosts; Pvm::Pvm ().Hosts (Hosts); // get list of all hosts Hosts.erase (Pvm::Pvm ().I ().Host ()); // remove my host from this list if (Hosts.empty ()) { std::cerr << "Need at least 2 hosts in the PVM for this program." << std::endl; exit (1); } Pvm::HostSet::iterator Current; for (Current = Hosts.begin (); Current != Hosts.end (); ++Current) // iterate through all hosts and start a multiplier on them Tasks.insert ((*Current).Spawn (PROGNAME)); } // generate 2 matrices to be multiplied. Size denotes the maximal size // in one dimension of the matrices. void InitMatrices (TransmitMatrices &Matrices, DoubleMatrix &Result, unsigned int Size) { int MinSize = (Size * 7) / 10; Matrices.RowsA = Random (MinSize, Size); Matrices.ColumnsA_RowsB = Random (MinSize, Size); Matrices.ColumnsB = Random (MinSize, Size); Matrices.MatrixA.insert (Matrices.MatrixA.begin (), Matrices.RowsA, DoubleVector (Matrices.ColumnsA_RowsB)); for (int Row = 0; Row < Matrices.RowsA; ++Row) for (int Column = 0; Column < Matrices.ColumnsA_RowsB; ++Column) Matrices.MatrixA[Row][Column] = Random (MaxValueOfElements); Matrices.MatrixB.insert (Matrices.MatrixB.begin (), Matrices.ColumnsA_RowsB, DoubleVector (Matrices.ColumnsB)); for (int Row = 0; Row < Matrices.ColumnsA_RowsB; ++Row) for (int Column = 0; Column < Matrices.ColumnsB; ++Column) Matrices.MatrixB[Row][Column] = Random (MaxValueOfElements); Result.insert (Result.begin (), Matrices.RowsA, DoubleVector ()); } // receives a result and returns, which task sent it. Pvm::Task ReceiveResult (DoubleMatrix &Result) { Pvm::Task From; TransmitResult Received; Received.Receive (From); Result[Received.Row] = Received.Result; return (From); } // the parameter to this program is the maximal size of the matrices int main (int argc, char **argv) { unsigned int MatrixSize = MaxNumOfRowsColumns; if (argc > 1) MatrixSize = atoi (argv[1]); Pvm::TaskSet MultTasks; StartMultTasks (MultTasks); unsigned int NumOfTasks = MultTasks.size (); TransmitMatrices Matrices; DoubleMatrix Result; InitMatrices (Matrices, Result, MatrixSize); std::cout << "Multiplying two matrices ( " << Matrices.RowsA << ", " << Matrices.ColumnsA_RowsB << " ) and ( " << Matrices.ColumnsA_RowsB << ", " << Matrices.ColumnsB << " ) " << std::endl << " resulting in a matrix ( " << Matrices.RowsA << ", " << Matrices.ColumnsB << " )." << std::endl; Matrices.Send (MultTasks); // here the number of processed rows per task (equivalent rows per // host here) is stored std::map< Pvm::Task, int > ProcessedRows; for (Pvm::TaskSet::iterator i = MultTasks.begin (); i != MultTasks.end (); ++i) ProcessedRows[(*i)] = 0; std::cout << "Processing Row "; TransmitCoords Coords; for (Coords.Row = 0; Coords.Row < Matrices.RowsA; ++Coords.Row) { // iterate through all rows and schedule them std::cout << (Coords.Row != 0 ? ", " : "") << Coords.Row + 1 << std::flush; if (MultTasks.empty ()) // wait for results and mark the task as ready MultTasks.insert (ReceiveResult (Result)); // send current job to a multiplier task Coords.Send (*MultTasks.begin ()); // add it to its account ProcessedRows[*MultTasks.begin ()]++; // and remove it from the set of ready tasks MultTasks.erase (MultTasks.begin ()); } while (MultTasks.size () != NumOfTasks) // wait until all tasks are ready MultTasks.insert (ReceiveResult (Result)); JobCompleted.Send (MultTasks); std::cout << std::endl << "Ready" << std::endl; // output a short statistic on who has done the work for (Pvm::TaskSet::iterator i = MultTasks.begin (); i != MultTasks.end (); ++i) std::cout << "Host " << (*i).Host ().Name () << " processed " << ProcessedRows[(*i)] << " Rows." << std::endl; }