mirror of
https://github.com/paboyle/Grid.git
synced 2026-10-30 09:13:19 +00:00
Make any split operators have lifetime the lifetime of the BatchedCG object
This commit is contained in:
1 parent
38c6fa78b2
commit
f7c25052f4
4 files changed
+72
-58
No files matched your search
@@ -104,13 +104,11 @@ inline int GridSplitVectorIndex(GridBase *full,GridBase *split)
|
|||||||
// line (--batched-solver-split). Uses the trailing dimensions of grid's processor and shm
|
// line (--batched-solver-split). Uses the trailing dimensions of grid's processor and shm
|
||||||
// layouts, so it works for 4d and 5d grids. Returns grid's own processor layout (one
|
// layouts, so it works for 4d and 5d grids. Returns grid's own processor layout (one
|
||||||
// partition) when no split is requested. Asserts divisibility; warns when partitions
|
// partition) when no split is requested. Asserts divisibility; warns when partitions
|
||||||
// straddle nodes, when node boundaries are not visible, or when there are more partitions
|
// straddle nodes or when node boundaries are not visible.
|
||||||
// than right-hand sides.
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
inline Coordinate BatchedSolverSplitLayout(GridBase *grid,
|
inline Coordinate BatchedSolverSplitLayout(GridBase *grid,
|
||||||
const Coordinate &request,
|
const Coordinate &request,
|
||||||
bool node,
|
bool node,
|
||||||
int nbatch,
|
|
||||||
int &partitions)
|
int &partitions)
|
||||||
{
|
{
|
||||||
int nd = GridDefaultMpi().size();
|
int nd = GridDefaultMpi().size();
|
||||||
@@ -168,10 +166,6 @@ inline Coordinate BatchedSolverSplitLayout(GridBase *grid,
|
|||||||
std::cout << GridLogWarning << "BatchedSolverSplit: partitions " << split
|
std::cout << GridLogWarning << "BatchedSolverSplit: partitions " << split
|
||||||
<< " straddle node boundaries (node layout " << shm << "); inner solves will communicate off node" << std::endl;
|
<< " straddle node boundaries (node layout " << shm << "); inner solves will communicate off node" << std::endl;
|
||||||
}
|
}
|
||||||
if ( partitions > nbatch ) {
|
|
||||||
std::cout << GridLogWarning << "BatchedSolverSplit: " << partitions << " partitions for "
|
|
||||||
<< nbatch << " right-hand sides; the extra partitions only solve zero padding" << std::endl;
|
|
||||||
}
|
|
||||||
return split;
|
return split;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,9 +53,17 @@ public:
|
|||||||
|
|
||||||
// Inner solves on independent partitions of the communicator (--batched-solver-split).
|
// Inner solves on independent partitions of the communicator (--batched-solver-split).
|
||||||
// BatchedSplit is the partition MPI layout, empty for no split; BatchedSplitNode selects
|
// BatchedSplit is the partition MPI layout, empty for no split; BatchedSplitNode selects
|
||||||
// one partition per node. Default from the command line; callers may override.
|
// one partition per node. Fixed at construction, default from the command line.
|
||||||
Coordinate BatchedSplit;
|
const Coordinate BatchedSplit;
|
||||||
bool BatchedSplitNode;
|
const bool BatchedSplitNode;
|
||||||
|
|
||||||
|
// Copy of Linop_f on the partitions, made once at construction and owned; nullptr when
|
||||||
|
// there is no split or the operator cannot be split. It holds the gauge field as it was at
|
||||||
|
// construction: a solver must not outlive a change of the operator's gauge field. The
|
||||||
|
// outer defect correction uses Linop_d, so a stale copy would cost convergence, not
|
||||||
|
// correctness.
|
||||||
|
SplitOperator<FieldF> *split = nullptr;
|
||||||
|
int Partitions = 1;
|
||||||
|
|
||||||
MixedPrecisionConjugateGradientBatched(RealD tol,
|
MixedPrecisionConjugateGradientBatched(RealD tol,
|
||||||
Integer maxinnerit,
|
Integer maxinnerit,
|
||||||
@@ -64,11 +72,37 @@ public:
|
|||||||
GridBase* _sp_grid,
|
GridBase* _sp_grid,
|
||||||
LinearOperatorBase<FieldF> &_Linop_f,
|
LinearOperatorBase<FieldF> &_Linop_f,
|
||||||
LinearOperatorBase<FieldD> &_Linop_d,
|
LinearOperatorBase<FieldD> &_Linop_d,
|
||||||
bool _updateResidual=true) :
|
bool _updateResidual=true,
|
||||||
|
const Coordinate &_split=GridDefaultBatchedSolverSplit(),
|
||||||
|
bool _split_node=GridDefaultBatchedSolverSplitNode()) :
|
||||||
Linop_f(_Linop_f), Linop_d(_Linop_d),
|
Linop_f(_Linop_f), Linop_d(_Linop_d),
|
||||||
Tolerance(tol), InnerTolerance(tol), MaxInnerIterations(maxinnerit), MaxOuterIterations(maxouterit), MaxPatchupIterations(maxpatchit), SinglePrecGrid(_sp_grid),
|
Tolerance(tol), InnerTolerance(tol), MaxInnerIterations(maxinnerit), MaxOuterIterations(maxouterit), MaxPatchupIterations(maxpatchit), SinglePrecGrid(_sp_grid),
|
||||||
OuterLoopNormMult(100.), guesser(NULL), updateResidual(_updateResidual),
|
OuterLoopNormMult(100.), guesser(NULL), updateResidual(_updateResidual),
|
||||||
BatchedSplit(GridDefaultBatchedSolverSplit()), BatchedSplitNode(GridDefaultBatchedSolverSplitNode()) { };
|
BatchedSplit(_split), BatchedSplitNode(_split_node)
|
||||||
|
{
|
||||||
|
Coordinate layout = BatchedSolverSplitLayout(SinglePrecGrid,BatchedSplit,BatchedSplitNode,Partitions);
|
||||||
|
if ( Partitions > 1 ) {
|
||||||
|
double t0 = usecond();
|
||||||
|
split = Linop_f.SplitClone(layout);
|
||||||
|
double t1 = usecond();
|
||||||
|
if ( split == nullptr ) {
|
||||||
|
std::cout << GridLogMessage << "MixedPrecisionConjugateGradientBatched: operator cannot be split; serial inner solves" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << GridLogMessage << "MixedPrecisionConjugateGradientBatched: split clone " << (t1-t0)/1.0e6 << " s" << std::endl;
|
||||||
|
HostMemoryReport(SinglePrecGrid,GridLogMessage,"MixedPrecisionConjugateGradientBatched: after split clone");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Owns split
|
||||||
|
MixedPrecisionConjugateGradientBatched(const MixedPrecisionConjugateGradientBatched &) = delete;
|
||||||
|
|
||||||
|
MixedPrecisionConjugateGradientBatched &operator=(const MixedPrecisionConjugateGradientBatched &) = delete;
|
||||||
|
|
||||||
|
~MixedPrecisionConjugateGradientBatched(void)
|
||||||
|
{
|
||||||
|
delete split;
|
||||||
|
}
|
||||||
|
|
||||||
void useGuesser(LinearFunction<FieldF> &g){
|
void useGuesser(LinearFunction<FieldF> &g){
|
||||||
guesser = &g;
|
guesser = &g;
|
||||||
@@ -139,21 +173,10 @@ public:
|
|||||||
ConjugateGradient<FieldF> CG_f(inner_tol, MaxInnerIterations);
|
ConjugateGradient<FieldF> CG_f(inner_tol, MaxInnerIterations);
|
||||||
CG_f.ErrorOnNoConverge = false;
|
CG_f.ErrorOnNoConverge = false;
|
||||||
|
|
||||||
//Optionally clone the single precision operator onto split-communicator partitions
|
SplitTimers splitTimers;
|
||||||
GridStopWatch SplitCloneTimer;
|
if ( split != nullptr && split->Partitions > NBatch ) {
|
||||||
SplitTimers splitTimers;
|
std::cout << GridLogWarning << "MixedPrecisionConjugateGradientBatched: " << split->Partitions << " partitions for "
|
||||||
SplitOperator<FieldF> *split = nullptr;
|
<< NBatch << " right-hand sides; the extra partitions only solve zero padding" << std::endl;
|
||||||
int partitions;
|
|
||||||
Coordinate layout = BatchedSolverSplitLayout(SinglePrecGrid,BatchedSplit,BatchedSplitNode,NBatch,partitions);
|
|
||||||
if ( partitions > 1 ) {
|
|
||||||
SplitCloneTimer.Start();
|
|
||||||
split = Linop_f.SplitClone(layout);
|
|
||||||
SplitCloneTimer.Stop();
|
|
||||||
if ( split == nullptr ) {
|
|
||||||
std::cout << GridLogMessage << "MixedPrecisionConjugateGradientBatched: operator cannot be split; serial inner solves" << std::endl;
|
|
||||||
} else {
|
|
||||||
HostMemoryReport(DoublePrecGrid,GridLogMessage,"MixedPrecisionConjugateGradientBatched: after split clone");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer &outer_iter = TotalOuterIterations; //so it will be equal to the final iteration count
|
Integer &outer_iter = TotalOuterIterations; //so it will be equal to the final iteration count
|
||||||
@@ -221,10 +244,6 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SplitCloneTimer.Start();
|
|
||||||
delete split;
|
|
||||||
SplitCloneTimer.Stop();
|
|
||||||
|
|
||||||
//Final trial CG
|
//Final trial CG
|
||||||
std::cout << GridLogMessage << std::endl;
|
std::cout << GridLogMessage << std::endl;
|
||||||
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Starting final patch-up double-precision solve"<<std::endl;
|
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Starting final patch-up double-precision solve"<<std::endl;
|
||||||
@@ -246,16 +265,15 @@ public:
|
|||||||
std::cout << GridLogMessage << std::endl;
|
std::cout << GridLogMessage << std::endl;
|
||||||
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Total time " << TotalTimer.Elapsed() << " Precision change " << PrecChangeTimer.Elapsed() << " Inner CG total " << InnerCGtimer.Elapsed() << std::endl;
|
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Total time " << TotalTimer.Elapsed() << " Precision change " << PrecChangeTimer.Elapsed() << " Inner CG total " << InnerCGtimer.Elapsed() << std::endl;
|
||||||
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Outer residual " << OuterResidualTimer.Elapsed() << " Patch-up " << PatchupTimer.Elapsed() << std::endl;
|
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Outer residual " << OuterResidualTimer.Elapsed() << " Patch-up " << PatchupTimer.Elapsed() << std::endl;
|
||||||
if ( partitions > 1 ) {
|
if ( split != nullptr ) {
|
||||||
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Split clone and delete " << SplitCloneTimer.Elapsed()
|
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Grid_split " << splitTimers.Split.Elapsed() << " (" << splitTimers.SplitCalls << " calls)"
|
||||||
<< " Grid_split " << splitTimers.Split.Elapsed() << " (" << splitTimers.SplitCalls << " calls)"
|
|
||||||
<< " Grid_unsplit " << splitTimers.Unsplit.Elapsed() << " (" << splitTimers.UnsplitCalls << " calls)"
|
<< " Grid_unsplit " << splitTimers.Unsplit.Elapsed() << " (" << splitTimers.UnsplitCalls << " calls)"
|
||||||
<< " Staging copies " << splitTimers.Staging.Elapsed()
|
<< " Staging copies " << splitTimers.Staging.Elapsed()
|
||||||
<< " Host to device " << splitTimers.H2D.Elapsed()
|
<< " Host to device " << splitTimers.H2D.Elapsed()
|
||||||
<< " Iteration count sum " << splitTimers.Reduce.Elapsed() << std::endl;
|
<< " Iteration count sum " << splitTimers.Reduce.Elapsed() << std::endl;
|
||||||
}
|
}
|
||||||
double accounted = PrecChangeTimer.useconds() + InnerCGtimer.useconds() + OuterResidualTimer.useconds()
|
double accounted = PrecChangeTimer.useconds() + InnerCGtimer.useconds() + OuterResidualTimer.useconds()
|
||||||
+ PatchupTimer.useconds() + SplitCloneTimer.useconds() + splitTimers.Split.useconds()
|
+ PatchupTimer.useconds() + splitTimers.Split.useconds()
|
||||||
+ splitTimers.Unsplit.useconds() + splitTimers.Staging.useconds() + splitTimers.H2D.useconds()
|
+ splitTimers.Unsplit.useconds() + splitTimers.Staging.useconds() + splitTimers.H2D.useconds()
|
||||||
+ splitTimers.Reduce.useconds();
|
+ splitTimers.Reduce.useconds();
|
||||||
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Unaccounted " << (TotalTimer.useconds()-accounted)/1.0e6 << " s" << std::endl;
|
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Unaccounted " << (TotalTimer.useconds()-accounted)/1.0e6 << " s" << std::endl;
|
||||||
|
|||||||
@@ -145,16 +145,19 @@ void CheckSplitBatched(const std::string &name,
|
|||||||
sol_split[i] = Zero();
|
sol_split[i] = Zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
MixedPrecisionConjugateGradientBatched<FieldD,FieldF> mCG(TOLERANCE,10000,50,1000,grid_f,Linop_f,Linop_d);
|
{
|
||||||
|
std::cout << GridLogMessage << name << ": unsplit batched solve" << std::endl;
|
||||||
std::cout << GridLogMessage << name << ": unsplit batched solve" << std::endl;
|
MixedPrecisionConjugateGradientBatched<FieldD,FieldF> mCG(TOLERANCE,10000,50,1000,grid_f,Linop_f,Linop_d,
|
||||||
mCG.BatchedSplit = Coordinate();
|
true,Coordinate(),false);
|
||||||
mCG.BatchedSplitNode = false;
|
mCG(src,sol_ref);
|
||||||
mCG(src,sol_ref);
|
}
|
||||||
|
{
|
||||||
std::cout << GridLogMessage << name << ": split batched solve, partition layout " << layout << std::endl;
|
std::cout << GridLogMessage << name << ": split batched solve, partition layout " << layout << std::endl;
|
||||||
mCG.BatchedSplit = layout;
|
MixedPrecisionConjugateGradientBatched<FieldD,FieldF> mCG(TOLERANCE,10000,50,1000,grid_f,Linop_f,Linop_d,
|
||||||
mCG(src,sol_split);
|
true,layout,false);
|
||||||
|
GRID_ASSERT( (mCG.Partitions == 1) || (mCG.split != nullptr) );
|
||||||
|
mCG(src,sol_split);
|
||||||
|
}
|
||||||
|
|
||||||
FieldD Msol(src[0].Grid());
|
FieldD Msol(src[0].Grid());
|
||||||
Msol.Checkerboard() = cb;
|
Msol.Checkerboard() = cb;
|
||||||
|
|||||||
@@ -213,25 +213,24 @@ int main (int argc, char ** argv)
|
|||||||
|
|
||||||
ReportMemory(UGrid_d,"operators and sources ready");
|
ReportMemory(UGrid_d,"operators and sources ready");
|
||||||
|
|
||||||
MixedPrecisionConjugateGradientBatched<FieldD,FieldF> mCG(tol,10000,50,10000,FrbGrid_f,Linop_f,Linop_d);
|
|
||||||
|
|
||||||
Coordinate split = mCG.BatchedSplit;
|
|
||||||
bool splitnode = mCG.BatchedSplitNode;
|
|
||||||
|
|
||||||
if ( unsplit ) {
|
if ( unsplit ) {
|
||||||
mCG.BatchedSplit = Coordinate();
|
MixedPrecisionConjugateGradientBatched<FieldD,FieldF> mCG(tol,10000,50,10000,FrbGrid_f,Linop_f,Linop_d,
|
||||||
mCG.BatchedSplitNode = false;
|
true,Coordinate(),false);
|
||||||
SolveAndReport("UNSPLIT",mCG,Linop_d,src,sol);
|
SolveAndReport("UNSPLIT",mCG,Linop_d,src,sol);
|
||||||
ReportMemory(UGrid_d,"after unsplit solve");
|
ReportMemory(UGrid_d,"after unsplit solve");
|
||||||
}
|
}
|
||||||
|
|
||||||
mCG.BatchedSplit = split;
|
if ( repeat > 0 ) {
|
||||||
mCG.BatchedSplitNode = splitnode;
|
// Split layout from the command line; the split operator is cloned here, once
|
||||||
// Repeated split solves expose allocations not released between calls
|
MixedPrecisionConjugateGradientBatched<FieldD,FieldF> mCG(tol,10000,50,10000,FrbGrid_f,Linop_f,Linop_d);
|
||||||
for(int r=0;r<repeat;r++){
|
ReportMemory(UGrid_d,"after split solver construction");
|
||||||
SolveAndReport("SPLIT",mCG,Linop_d,src,sol);
|
// Repeated split solves reuse the clone and expose allocations not released between calls
|
||||||
ReportMemory(UGrid_d,"after split solve "+std::to_string(r));
|
for(int r=0;r<repeat;r++){
|
||||||
|
SolveAndReport("SPLIT",mCG,Linop_d,src,sol);
|
||||||
|
ReportMemory(UGrid_d,"after split solve "+std::to_string(r));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ReportMemory(UGrid_d,"after split solver destruction");
|
||||||
|
|
||||||
Grid_finalize();
|
Grid_finalize();
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user