From 44f24f395eec542dc341d6a6b3b6e945dd2a6fcb Mon Sep 17 00:00:00 2001 From: Peter Boyle Date: Fri, 2 Oct 2026 19:46:15 -0400 Subject: [PATCH] TIming info. Will need to revert in future. --- .../ConjugateGradientMixedPrecBatched.h | 71 ++++++++++++++++--- Grid/lattice/Lattice_transfer.h | 67 +++++++++++++++++ Grid/qcd/action/fermion/FermionOperator.h | 3 + Grid/qcd/action/fermion/WilsonFermion5D.h | 5 ++ 4 files changed, 136 insertions(+), 10 deletions(-) diff --git a/Grid/algorithms/iterative/ConjugateGradientMixedPrecBatched.h b/Grid/algorithms/iterative/ConjugateGradientMixedPrecBatched.h index 27d901e2c..e6b6cc82b 100644 --- a/Grid/algorithms/iterative/ConjugateGradientMixedPrecBatched.h +++ b/Grid/algorithms/iterative/ConjugateGradientMixedPrecBatched.h @@ -98,6 +98,8 @@ public: GridStopWatch InnerCGtimer; GridStopWatch PrecChangeTimer; + GridStopWatch OuterResidualTimer; + GridStopWatch PatchupTimer; int cb = src_d_in[0].Checkerboard(); @@ -138,14 +140,15 @@ public: CG_f.ErrorOnNoConverge = false; //Optionally clone the single precision operator onto split-communicator partitions - GridStopWatch SplitTimer; + GridStopWatch SplitCloneTimer; + SplitTimers splitTimers; SplitOperator *split = nullptr; int partitions; Coordinate layout = BatchedSolverSplitLayout(SinglePrecGrid,BatchedSplit,BatchedSplitNode,NBatch,partitions); if ( partitions > 1 ) { - SplitTimer.Start(); + SplitCloneTimer.Start(); split = Linop_f.SplitClone(layout); - SplitTimer.Stop(); + SplitCloneTimer.Stop(); if ( split == nullptr ) { std::cout << GridLogMessage << "MixedPrecisionConjugateGradientBatched: operator cannot be split; serial inner solves" << std::endl; } @@ -161,8 +164,10 @@ public: for (int i=0; i CG_d(Tolerance, MaxPatchupIterations); CG_d(Linop_d, src_d_in[i], sol_d[i]); TotalFinalStepIterations[i] += CG_d.IterationsToComplete; } + PatchupTimer.Stop(); TotalTimer.Stop(); @@ -232,12 +241,37 @@ public: std::cout< 1 ) { + std::cout< &sol_f, std::vector &TotalInnerIterations, GridStopWatch &InnerCGtimer, - GridStopWatch &SplitTimer) + SplitTimers &timers) { int NBatch = src_f.size(); int P = split.Partitions; @@ -263,6 +297,7 @@ private: for(int g=0;gGlobalSumVector(&iters[0],P); + timers.Reduce.Stop(); + // Includes the host to device copy of group_sol left by Grid_unsplit + timers.Staging.Start(); for(int p=0;p

> & full,Lattice & split) ratio[d] = full_grid->_processors[d]/ split_grid->_processors[d]; } + // Coarse phase timers, reported on GridLogPerformance + double t_start = usecond(); + double t_d2h = 0; + double t_unvec = 0; + double t_a2a = 0; + double t_reorder = 0; + double t_vec = 0; + double t0; + uint64_t lsites = full_grid->lSites(); uint64_t sz = lsites * nvector; std::vector tmpdata(sz); std::vector alldata(sz); std::vector scalardata(lsites); + double t_alloc = usecond() - t_start; for(int v=0;v > & full,Lattice & split) if ( ratio[d] != 1 ) { + t0 = usecond(); full_grid ->AllToAll(d,alldata,tmpdata); if ( split_grid->_processors[d] > 1 ) { alldata=tmpdata; split_grid->AllToAll(d,alldata,tmpdata); } + t_a2a += usecond() - t0; + t0 = usecond(); auto rdims = ldims; auto M = ratio[d]; @@ -1701,12 +1722,25 @@ void Grid_split(std::vector > & full,Lattice & split) } } }); + t_reorder += usecond() - t0; ldims[d]*= ratio[d]; lsites *= ratio[d]; } } + t0 = usecond(); vectorizeFromLexOrdArray(alldata,split); + t_vec = usecond() - t0; + double t_total = usecond() - t_start; + + // Host to device copy of split happens lazily at its first accelerator use; not counted here + std::cout << GridLogPerformance << "Grid_split: " << nvector << " x " << sz/nvector*sizeof(Sobj)/1.0e6 + << " MB/rank total " << t_total/1.0e6 << " s : alloc " << t_alloc/1.0e6 + << " d2h " << t_d2h/1.0e6 + << " unvectorise " << t_unvec/1.0e6 + << " alltoall " << t_a2a/1.0e6 + << " reorder " << t_reorder/1.0e6 + << " vectorise " << t_vec/1.0e6 << std::endl; } template @@ -1763,13 +1797,29 @@ void Grid_unsplit(std::vector > & full,Lattice & split) ratio[d] = full_grid->_processors[d]/ split_grid->_processors[d]; } + // Coarse phase timers, reported on GridLogPerformance + double t_start = usecond(); + double t_a2a = 0; + double t_reorder = 0; + double t_vec = 0; + double t0; + uint64_t lsites = full_grid->lSites(); uint64_t sz = lsites * nvector; std::vector tmpdata(sz); std::vector alldata(sz); std::vector scalardata(lsites); + double t_alloc = usecond() - t_start; + // Open and close a host view first so any device to host copy is timed on its own + t0 = usecond(); + { + autoView(split_v, split, CpuRead); + } + double t_d2h = usecond() - t0; + t0 = usecond(); unvectorizeToLexOrdArray(alldata,split); + double t_unvec = usecond() - t0; ///////////////////////////////////////////////////////////////// // Start from split grid and work towards full grid @@ -1794,6 +1844,7 @@ void Grid_unsplit(std::vector > & full,Lattice & split) int fvol = lsites; int chunk = (nvec*fvol)/sP; GRID_ASSERT(chunk*sP == nvec*fvol); + t0 = usecond(); { // Loop over reordered data post A2A thread_for(c, chunk,{ @@ -1821,17 +1872,22 @@ void Grid_unsplit(std::vector > & full,Lattice & split) }); } + t_reorder += usecond() - t0; + + t0 = usecond(); if ( split_grid->_processors[d] > 1 ) { split_grid->AllToAll(d,tmpdata,alldata); tmpdata=alldata; } full_grid ->AllToAll(d,tmpdata,alldata); + t_a2a += usecond() - t0; rdims[d]/= M; rsites /= M; nvec *= M; // Increase nvec by subdivision factor } } + t0 = usecond(); lsites = full_grid->lSites(); for(int v=0;v > & full,Lattice & split) }); vectorizeFromLexOrdArray(scalardata,full[v]); } + t_vec = usecond() - t0; + double t_total = usecond() - t_start; + + // Host to device copies of full happen lazily at their first accelerator use; not counted here + std::cout << GridLogPerformance << "Grid_unsplit: " << nvector << " x " << sz/nvector*sizeof(Sobj)/1.0e6 + << " MB/rank total " << t_total/1.0e6 << " s : alloc " << t_alloc/1.0e6 + << " d2h " << t_d2h/1.0e6 + << " unvectorise " << t_unvec/1.0e6 + << " alltoall " << t_a2a/1.0e6 + << " reorder " << t_reorder/1.0e6 + << " vectorise " << t_vec/1.0e6 << std::endl; } ////////////////////////////////////////////////////// diff --git a/Grid/qcd/action/fermion/FermionOperator.h b/Grid/qcd/action/fermion/FermionOperator.h index be12d46dc..802f1604b 100644 --- a/Grid/qcd/action/fermion/FermionOperator.h +++ b/Grid/qcd/action/fermion/FermionOperator.h @@ -70,6 +70,8 @@ public: GRID_ASSERT(U != nullptr); GRID_ASSERT(mpi_split.size() == Nd); + double t0 = usecond(); + SplitOperator *split = new SplitOperator(); split->GaugeGrid = new GridCartesian(U->FullDimensions(),U->_simd_layout,mpi_split,*U); @@ -85,6 +87,7 @@ public: split->FermionGrid = split->GaugeGrid; split->FermionRBGrid = split->GaugeRBGrid; } + std::cout << GridLogPerformance << "MakeSplitGrids: " << (usecond()-t0)/1.0e6 << " s" << std::endl; return split; } diff --git a/Grid/qcd/action/fermion/WilsonFermion5D.h b/Grid/qcd/action/fermion/WilsonFermion5D.h index e65d086c8..4d5df4fbb 100644 --- a/Grid/qcd/action/fermion/WilsonFermion5D.h +++ b/Grid/qcd/action/fermion/WilsonFermion5D.h @@ -192,9 +192,14 @@ public: // Redistribute this operator's doubled gauge field onto clone's split grid. Collective. void SplitDoubledGaugeInto(WilsonFermion5D &clone) { + double t0 = usecond(); DoubledGaugeField sUmu(clone.GaugeGrid()); Grid_split(Umu,sUmu); + double t1 = usecond(); clone.ImportDoubledGauge(sUmu); + double t2 = usecond(); + std::cout << GridLogPerformance << "SplitDoubledGaugeInto: Grid_split " << (t1-t0)/1.0e6 + << " s import " << (t2-t1)/1.0e6 << " s" << std::endl; } ///////////////////////////////////////////////////////////////