From 63c21767bafd53bb04397bc73aa53141cdea19ff Mon Sep 17 00:00:00 2001 From: Antonin Portelli Date: Mon, 10 Sep 2018 15:31:39 +0100 Subject: [PATCH] Hadrons: grids stored with hash of SIMD type (for mixed-precision setups) --- Hadrons/Environment.cc | 133 ++-------------------- Hadrons/Environment.hpp | 245 ++++++++++++++++++++++++++++++++++++---- Hadrons/Global.cc | 5 + Hadrons/Global.hpp | 18 ++- 4 files changed, 253 insertions(+), 148 deletions(-) diff --git a/Hadrons/Environment.cc b/Hadrons/Environment.cc index 5ad189ad..ab5b4de9 100644 --- a/Hadrons/Environment.cc +++ b/Hadrons/Environment.cc @@ -43,137 +43,24 @@ HADRONS_ERROR_REF(ObjectDefinition, "no object with address " + std::to_string(a // constructor ///////////////////////////////////////////////////////////////// Environment::Environment(void) { - dim_ = GridDefaultLatt(); - nd_ = dim_.size(); - grid4d_.reset(SpaceTimeGrid::makeFourDimGrid( - dim_, GridDefaultSimd(nd_, vComplex::Nsimd()), - GridDefaultMpi())); - gridRb4d_.reset(SpaceTimeGrid::makeFourDimRedBlackGrid(grid4d_.get())); + dim_ = GridDefaultLatt(); + nd_ = dim_.size(); + defaultGrid_ = {typeHash(), 1}; + grid4d_[defaultGrid_].reset( + SpaceTimeGrid::makeFourDimGrid(dim_, + GridDefaultSimd(nd_, vComplex::Nsimd()), + GridDefaultMpi())); + gridRb4d_[defaultGrid_].reset( + SpaceTimeGrid::makeFourDimRedBlackGrid(grid4d_[defaultGrid_].get())); vol_ = 1.; for (auto d: dim_) { vol_ *= d; } - rng4d_.reset(new GridParallelRNG(grid4d_.get())); + rng4d_.reset(new GridParallelRNG(grid4d_[defaultGrid_].get())); } // grids /////////////////////////////////////////////////////////////////////// -void Environment::createGrid(const unsigned int Ls) -{ - if ((Ls > 1) and (grid5d_.find(Ls) == grid5d_.end())) - { - auto g = getGrid(); - - grid5d_[Ls].reset(SpaceTimeGrid::makeFiveDimGrid(Ls, g)); - gridRb5d_[Ls].reset(SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, g)); - } -} - -void Environment::createCoarseGrid(const std::vector &blockSize, - const unsigned int Ls) -{ - int nd = getNd(); - std::vector fineDim = getDim(), coarseDim; - unsigned int cLs; - auto key4d = blockSize, key5d = blockSize; - - createGrid(Ls); - coarseDim.resize(nd); - for (int d = 0; d < coarseDim.size(); d++) - { - coarseDim[d] = fineDim[d]/blockSize[d]; - if (coarseDim[d]*blockSize[d] != fineDim[d]) - { - HADRONS_ERROR(Size, "Fine dimension " + std::to_string(d) - + " (" + std::to_string(fineDim[d]) - + ") not divisible by coarse dimension (" - + std::to_string(coarseDim[d]) + ")"); - } - } - if (blockSize.size() > nd) - { - cLs = Ls/blockSize[nd]; - if (cLs*blockSize[nd] != Ls) - { - HADRONS_ERROR(Size, "Fine Ls (" + std::to_string(Ls) - + ") not divisible by coarse Ls (" - + std::to_string(cLs) + ")"); - } - key4d.resize(nd); - key5d.push_back(Ls); - } - gridCoarse4d_[key4d].reset( - SpaceTimeGrid::makeFourDimGrid(coarseDim, - GridDefaultSimd(nd, vComplex::Nsimd()), GridDefaultMpi())); - if (Ls > 1) - { - gridCoarse5d_[key5d].reset( - SpaceTimeGrid::makeFiveDimGrid(cLs, gridCoarse4d_[key4d].get())); - } -} - -GridCartesian * Environment::getGrid(const unsigned int Ls) const -{ - try - { - if (Ls == 1) - { - return grid4d_.get(); - } - else - { - return grid5d_.at(Ls).get(); - } - } - catch(std::out_of_range &) - { - HADRONS_ERROR(Definition, "no grid with Ls= " + std::to_string(Ls)); - } -} - -GridRedBlackCartesian * Environment::getRbGrid(const unsigned int Ls) const -{ - try - { - if (Ls == 1) - { - return gridRb4d_.get(); - } - else - { - return gridRb5d_.at(Ls).get(); - } - } - catch(std::out_of_range &) - { - HADRONS_ERROR(Definition, "no red-black grid with Ls= " + std::to_string(Ls)); - } -} - -GridCartesian * Environment::getCoarseGrid( - const std::vector &blockSize, const unsigned int Ls) const -{ - auto key = blockSize; - - try - { - if (Ls == 1) - { - key.resize(getNd()); - return gridCoarse4d_.at(key).get(); - } - else - { - key.push_back(Ls); - return gridCoarse5d_.at(key).get(); - } - } - catch(std::out_of_range &) - { - HADRONS_ERROR(Definition, "no coarse grid with Ls= " + std::to_string(Ls)); - } -} - unsigned int Environment::getNd(void) const { return nd_; diff --git a/Hadrons/Environment.hpp b/Hadrons/Environment.hpp index 8aaac012..24682195 100644 --- a/Hadrons/Environment.hpp +++ b/Hadrons/Environment.hpp @@ -83,15 +83,28 @@ private: int module{-1}; std::unique_ptr data{nullptr}; }; + typedef std::pair FineGridKey; + typedef std::pair> CoarseGridKey; public: // grids + template void createGrid(const unsigned int Ls); + template void createCoarseGrid(const std::vector &blockSize, const unsigned int Ls = 1); - GridCartesian * getGrid(const unsigned int Ls = 1) const; - GridRedBlackCartesian * getRbGrid(const unsigned int Ls = 1) const; + template + GridCartesian * getGrid(void) const; + template + GridRedBlackCartesian * getRbGrid(void) const; + template + GridCartesian * getCoarseGrid(const std::vector &blockSize) const; + template + GridCartesian * getGrid(const unsigned int Ls) const; + template + GridRedBlackCartesian * getRbGrid(const unsigned int Ls) const; + template GridCartesian * getCoarseGrid(const std::vector &blockSize, - const unsigned int Ls = 1) const; + const unsigned int Ls) const; std::vector getDim(void) const; int getDim(const unsigned int mu) const; unsigned int getNd(void) const; @@ -154,22 +167,23 @@ public: void printContent(void) const; private: // general - double vol_; - bool protect_{true}; + double vol_; + bool protect_{true}; // grids - std::vector dim_; - GridPt grid4d_; - std::map grid5d_; - GridRbPt gridRb4d_; - std::map gridRb5d_; - std::map, GridPt> gridCoarse4d_; - std::map, GridPt> gridCoarse5d_; - unsigned int nd_; + std::vector dim_; + FineGridKey defaultGrid_; + std::map grid4d_; + std::map grid5d_; + std::map gridRb4d_; + std::map gridRb5d_; + std::map gridCoarse4d_; + std::map gridCoarse5d_; + unsigned int nd_; // random number generator - RngPt rng4d_; + RngPt rng4d_; // object store - std::vector object_; - std::map objectAddress_; + std::vector object_; + std::map objectAddress_; }; /****************************************************************************** @@ -203,6 +217,191 @@ void Holder::reset(T *pt) /****************************************************************************** * Environment template implementation * ******************************************************************************/ +// grids /////////////////////////////////////////////////////////////////////// +template +void Environment::createGrid(const unsigned int Ls) +{ + size_t hash = typeHash(); + + if (grid4d_.find({hash, 1}) == grid4d_.end()) + { + grid4d_[{hash, 1}].reset( + SpaceTimeGrid::makeFourDimGrid(getDim(), + GridDefaultSimd(getNd(), VType::Nsimd()), + GridDefaultMpi())); + gridRb4d_[{hash, 1}].reset( + SpaceTimeGrid::makeFourDimRedBlackGrid(grid4d_[{hash, 1}].get())); + } + if (grid5d_.find({hash, Ls}) == grid5d_.end()) + { + auto g = grid4d_[{hash, 1}].get(); + + grid5d_[{hash, Ls}].reset(SpaceTimeGrid::makeFiveDimGrid(Ls, g)); + gridRb5d_[{hash, Ls}].reset(SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, g)); + } +} + +template +void Environment::createCoarseGrid(const std::vector &blockSize, + const unsigned int Ls) +{ + int nd = getNd(); + std::vector fineDim = getDim(), coarseDim(nd); + unsigned int cLs; + auto key4d = blockSize, key5d = blockSize; + size_t hash = typeHash(); + + createGrid(Ls); + for (int d = 0; d < coarseDim.size(); d++) + { + coarseDim[d] = fineDim[d]/blockSize[d]; + if (coarseDim[d]*blockSize[d] != fineDim[d]) + { + HADRONS_ERROR(Size, "Fine dimension " + std::to_string(d) + + " (" + std::to_string(fineDim[d]) + + ") not divisible by coarse dimension (" + + std::to_string(coarseDim[d]) + ")"); + } + } + if (blockSize.size() > nd) + { + cLs = Ls/blockSize[nd]; + if (cLs*blockSize[nd] != Ls) + { + HADRONS_ERROR(Size, "Fine Ls (" + std::to_string(Ls) + + ") not divisible by coarse Ls (" + + std::to_string(cLs) + ")"); + } + } + else + { + cLs = Ls; + } + key4d.resize(nd); + key5d.push_back(Ls); + + CoarseGridKey hkey4d = {hash, key4d}, hkey5d = {hash, key5d}; + + if (gridCoarse4d_.find(hkey4d) == gridCoarse4d_.end()) + { + gridCoarse4d_[hkey4d].reset( + SpaceTimeGrid::makeFourDimGrid(coarseDim, + GridDefaultSimd(nd, VType::Nsimd()), GridDefaultMpi())); + } + if (gridCoarse5d_.find(hkey5d) == gridCoarse5d_.end()) + { + gridCoarse5d_[hkey5d].reset( + SpaceTimeGrid::makeFiveDimGrid(cLs, gridCoarse4d_[hkey4d].get())); + } +} + +template +GridCartesian * Environment::getGrid(void) const +{ + auto it = grid4d_.find({typeHash(), 1}); + + if (it != grid4d_.end()) + { + return it->second.get(); + } + else + { + HADRONS_ERROR(Definition, "no 4D grid for SIMD type '" + + typeName() + "'"); + } +} + +template +GridRedBlackCartesian * Environment::getRbGrid(void) const +{ + auto it = gridRb4d_.find({typeHash(), 1}); + + if (it != gridRb4d_.end()) + { + return it->second.get(); + } + else + { + HADRONS_ERROR(Definition, "no 4D red-black grid for SIMD type '" + + typeName() + "'"); + } +} + +template +GridCartesian * Environment::getCoarseGrid(const std::vector &blockSize) const +{ + std::vector s = blockSize; + + s.resize(getNd()); + auto it = gridCoarse4d_.find({typeHash(), s}); + if (it != gridCoarse4d_.end()) + { + return it->second.get(); + } + else + { + HADRONS_ERROR(Definition, "no 4D coarse grid for SIMD type '" + + typeName() + "' and block size " + + vecToStr(blockSize)); + } +} + +template +GridCartesian * Environment::getGrid(const unsigned int Ls) const +{ + auto it = grid5d_.find({typeHash(), Ls}); + + if (it != grid5d_.end()) + { + return it->second.get(); + } + else + { + HADRONS_ERROR(Definition, "no 5D grid for SIMD type '" + + typeName() + "' and Ls = " + + std::to_string(Ls)); + } +} + +template +GridRedBlackCartesian * Environment::getRbGrid(const unsigned int Ls) const +{ + auto it = gridRb5d_.find({typeHash(), Ls}); + + if (it != gridRb5d_.end()) + { + return it->second.get(); + } + else + { + HADRONS_ERROR(Definition, "no 5D red-black grid for SIMD type '" + + typeName() + "' and Ls = " + + std::to_string(Ls)); + } +} + +template +GridCartesian * Environment::getCoarseGrid(const std::vector &blockSize, + const unsigned int Ls) const +{ + std::vector s = blockSize; + + s.push_back(Ls); + auto it = gridCoarse5d_.find({typeHash(), s}); + if (it != gridCoarse5d_.end()) + { + return it->second.get(); + } + else + { + HADRONS_ERROR(Definition, "no 5D coarse grid for SIMD type '" + + typeName() + "', block size " + + vecToStr(blockSize) + + " and Ls = " + std::to_string(Ls)); + } +} + + // general memory management /////////////////////////////////////////////////// template void Environment::createDerivedObject(const std::string name, @@ -230,19 +429,19 @@ void Environment::createDerivedObject(const std::string name, object_[address].Ls = Ls; object_[address].data.reset(new Holder(new T(std::forward(args)...))); object_[address].size = MemoryProfiler::stats->maxAllocated - initMem; - object_[address].type = &typeid(B); - object_[address].derivedType = &typeid(T); + object_[address].type = typeIdPt(); + object_[address].derivedType = typeIdPt(); if (MemoryProfiler::stats == &memStats) { MemoryProfiler::stats = nullptr; } } // object already exists, no error if it is a cache, error otherwise - else if ((object_[address].storage != Storage::cache) or - (object_[address].storage != storage) or - (object_[address].name != name) or - (object_[address].type != &typeid(B)) or - (object_[address].derivedType != &typeid(T))) + else if ((object_[address].storage != Storage::cache) or + (object_[address].storage != storage) or + (object_[address].name != name) or + (typeHash(object_[address].type) != typeHash()) or + (typeHash(object_[address].derivedType) != typeHash())) { HADRONS_ERROR_REF(ObjectDefinition, "object '" + name + "' already allocated", address); } diff --git a/Hadrons/Global.cc b/Hadrons/Global.cc index 516e466f..a83f422f 100644 --- a/Hadrons/Global.cc +++ b/Hadrons/Global.cc @@ -72,6 +72,11 @@ void Hadrons::initLogger(void) } // type utilities ////////////////////////////////////////////////////////////// +size_t Hadrons::typeHash(const std::type_info *info) +{ + return info->hash_code(); +} + constexpr unsigned int maxNameSize = 1024u; std::string Hadrons::typeName(const std::type_info *info) diff --git a/Hadrons/Global.hpp b/Hadrons/Global.hpp index 04c1f54a..808ed2ba 100644 --- a/Hadrons/Global.hpp +++ b/Hadrons/Global.hpp @@ -155,14 +155,28 @@ const std::type_info * typeIdPt(const T &x) return &typeid(x); } -std::string typeName(const std::type_info *info); - template const std::type_info * typeIdPt(void) { return &typeid(T); } +size_t typeHash(const std::type_info *info); + +template +size_t typeHash(const T &x) +{ + return typeHash(typeIdPt(x)); +} + +template +size_t typeHash(void) +{ + return typeHash(typeIdPt()); +} + +std::string typeName(const std::type_info *info); + template std::string typeName(const T &x) {