#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;
}
syntax highlighted by Code2HTML, v. 0.9.1