Skip to content

Commit

Permalink
Refs #4980 use reduce in GatherWorkspaces
Browse files Browse the repository at this point in the history
  • Loading branch information
VickieLynch committed Mar 16, 2012
1 parent e5aa854 commit cd334a4
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,44 @@ class GatherWorkspaces : public API::Algorithm
virtual int version() const { return (1); }
/// Algorithm's category for identification
virtual const std::string category() const { return "MPI"; }
/// Sum for boostmpi MantidVec
struct vplus
: public std::binary_function<MantidVec, MantidVec, MantidVec>
{ // functor for operator+
MantidVec operator()(const MantidVec& _Left, const MantidVec& _Right) const
{ // apply operator+ to operands
MantidVec v(_Left.size());
std::transform(_Left.begin(), _Left.end(), _Right.begin(), v.begin(), std::plus<double>());
return (v);
}

};
/// Sum for error for boostmpi MantidVec
struct eplus : public std::binary_function<MantidVec, MantidVec, MantidVec>
{ // functor for operator+
MantidVec operator()(const MantidVec& _Left, const MantidVec& _Right) const
{ // apply operator+ to operands
MantidVec v(_Left.size());
std::transform(_Left.begin(), _Left.end(), _Right.begin(), v.begin(), SumGaussError<double>());
return (v);
}
};


private:
void init();
void exec();
//! Functor used for computing the sum of the square values of a vector, using the accumulate algorithm
template <class T> struct SumGaussError: public std::binary_function<T,T,T>
{
SumGaussError(){}
/// Sums the arguments in quadrature
inline T operator()(const T& l, const T& r) const
{
return std::sqrt(l*l+r*r);
}
};

//void execEvent(); TODO: Make event-aware? (might lead to transmission of too much data)

};
Expand Down
43 changes: 6 additions & 37 deletions Code/Mantid/Framework/MPIAlgorithms/src/GatherWorkspaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,59 +79,28 @@ void GatherWorkspaces::exec()
{
g_log.debug() << "Total number of spectra is " << totalSpec << "\n";
// Create the workspace for the output
outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace,totalSpec,numBins+hist,numBins);
outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace,1,numBins+hist,numBins);
setProperty("OutputWorkspace",outputWorkspace);

// Keep it lean-and-mean and don't bother with the spectra map, etc.
// This line is needed to stop a crash on a subsequent SaveNexus
// outputWorkspace->replaceSpectraMap(new SpectraDetectorMap);
}

// Let's assume 1 spectrum in each workspace for the first try....
// TODO: Generalise

MantidVec out;
if ( world.rank() == 0 )
{
// Copy over data from own input workspace
outputWorkspace->dataX(0) = inputWorkspace->readX(0);
outputWorkspace->dataY(0) = inputWorkspace->readY(0);
outputWorkspace->dataE(0) = inputWorkspace->readE(0);
reduce(included, inputWorkspace->readY(0), outputWorkspace->dataY(0), vplus(), 0);
reduce(included, inputWorkspace->readE(0), outputWorkspace->dataE(0), eplus(), 0);
const ISpectrum * inSpec = inputWorkspace->getSpectrum(0);
ISpectrum * outSpec = outputWorkspace->getSpectrum(0);
outSpec->clearDetectorIDs();
outSpec->addDetectorIDs( inSpec->getDetectorIDs() );

const int numReqs(3*(included.size()-1));
mpi::request reqs[numReqs];
int j(0);

// Receive data from all the other processes
// This works because the process ranks are ordered the same in 'included' as
// they are in 'world', but in general this is not guaranteed. TODO: robustify
for ( int i = 1; i < included.size(); ++i )
{
reqs[j++] = included.irecv(i,0,outputWorkspace->dataX(i));
reqs[j++] = included.irecv(i,1,outputWorkspace->dataY(i));
reqs[j++] = included.irecv(i,2,outputWorkspace->dataE(i));
ISpectrum * outSpec = outputWorkspace->getSpectrum(i);
outSpec->clearDetectorIDs();
outSpec->addDetectorIDs( inSpec->getDetectorIDs() );
}

// Make sure everything's been received before exiting the algorithm
mpi::wait_all(reqs,reqs+numReqs);
}
else
{
mpi::request reqs[3];

// Send the spectrum to the root process
reqs[0] = included.isend(0,0,inputWorkspace->readX(0));
reqs[1] = included.isend(0,1,inputWorkspace->readY(0));
reqs[2] = included.isend(0,2,inputWorkspace->readE(0));

// Make sure the sends have completed before exiting the algorithm
mpi::wait_all(reqs,reqs+3);
reduce(included, inputWorkspace->readY(0), vplus(), 0);
reduce(included, inputWorkspace->readE(0), eplus(), 0);
}

}
Expand Down

0 comments on commit cd334a4

Please sign in to comment.