1
0
mirror of https://github.com/paboyle/Grid.git synced 2024-11-13 01:05:36 +00:00

Hadrons: better organisation of the VM

This commit is contained in:
Antonin Portelli 2017-12-13 13:44:23 +00:00
parent a9c8d7dad0
commit 61fc50d616
5 changed files with 236 additions and 244 deletions

View File

@ -94,8 +94,6 @@ void Application::run(void)
} }
vm().printContent(); vm().printContent();
env().printContent(); env().printContent();
//vm().checkGraph();
vm().memoryProfile();
if (!scheduled_) if (!scheduled_)
{ {
schedule(); schedule();
@ -185,11 +183,11 @@ GeneticScheduler<unsigned int>::ObjFunc memPeak = \
void Application::schedule(void) void Application::schedule(void)
{ {
DEFINE_MEMPEAK; //DEFINE_MEMPEAK;
// build module dependency graph // build module dependency graph
LOG(Message) << "Building module graph..." << std::endl; LOG(Message) << "Building module graph..." << std::endl;
auto graph = vm().makeModuleGraph(); auto graph = vm().getModuleGraph();
LOG(Debug) << "Module graph:" << std::endl; LOG(Debug) << "Module graph:" << std::endl;
LOG(Debug) << graph << std::endl; LOG(Debug) << graph << std::endl;
auto con = graph.getConnectedComponents(); auto con = graph.getConnectedComponents();
@ -276,7 +274,7 @@ void Application::saveSchedule(const std::string filename)
void Application::loadSchedule(const std::string filename) void Application::loadSchedule(const std::string filename)
{ {
DEFINE_MEMPEAK; //DEFINE_MEMPEAK;
TextReader reader(filename); TextReader reader(filename);
std::vector<std::string> program; std::vector<std::string> program;
@ -290,7 +288,7 @@ void Application::loadSchedule(const std::string filename)
program_.push_back(vm().getModuleAddress(name)); program_.push_back(vm().getModuleAddress(name));
} }
scheduled_ = true; scheduled_ = true;
memPeak_ = memPeak(program_); //memPeak_ = memPeak(program_);
} }
void Application::printSchedule(void) void Application::printSchedule(void)
@ -323,16 +321,3 @@ void Application::configLoop(void)
LOG(Message) << BIG_SEP << " End of measurement " << BIG_SEP << std::endl; LOG(Message) << BIG_SEP << " End of measurement " << BIG_SEP << std::endl;
env().freeAll(); env().freeAll();
} }
// memory profile //////////////////////////////////////////////////////////////
void Application::memoryProfile(void)
{
auto graph = vm().makeModuleGraph();
auto program = graph.topoSort();
bool msg;
msg = HadronsLogMessage.isActive();
HadronsLogMessage.Active(false);
HadronsLogMessage.Active(msg);
}

View File

@ -102,8 +102,6 @@ private:
DEFINE_ENV_ALIAS; DEFINE_ENV_ALIAS;
// virtual machine shortcut // virtual machine shortcut
DEFINE_VM_ALIAS; DEFINE_VM_ALIAS;
// memory profile
void memoryProfile(void);
private: private:
long unsigned int locVol_; long unsigned int locVol_;
std::string parameterFileName_{""}; std::string parameterFileName_{""};

View File

@ -58,8 +58,5 @@ std::string ModuleBase::getRegisteredName(void)
void ModuleBase::operator()(void) void ModuleBase::operator()(void)
{ {
setup(); setup();
if (!vm().isDryRun()) execute();
{
execute();
}
} }

View File

@ -36,27 +36,6 @@ using namespace Hadrons;
/****************************************************************************** /******************************************************************************
* VirtualMachine implementation * * VirtualMachine implementation *
******************************************************************************/ ******************************************************************************/
// dry run /////////////////////////////////////////////////////////////////////
void VirtualMachine::dryRun(const bool isDry)
{
dryRun_ = isDry;
}
bool VirtualMachine::isDryRun(void) const
{
return dryRun_;
}
void VirtualMachine::memoryProfile(const bool doMemoryProfile)
{
memoryProfile_ = doMemoryProfile;
}
bool VirtualMachine::doMemoryProfile(void) const
{
return memoryProfile_;
}
// trajectory counter ////////////////////////////////////////////////////////// // trajectory counter //////////////////////////////////////////////////////////
void VirtualMachine::setTrajectory(const unsigned int traj) void VirtualMachine::setTrajectory(const unsigned int traj)
{ {
@ -259,40 +238,192 @@ bool VirtualMachine::hasModule(const std::string name) const
return (moduleAddress_.find(name) != moduleAddress_.end()); return (moduleAddress_.find(name) != moduleAddress_.end());
} }
Graph<unsigned int> VirtualMachine::makeModuleGraph(void) const // print VM content ////////////////////////////////////////////////////////////
void VirtualMachine::printContent(void) const
{ {
Graph<unsigned int> moduleGraph; LOG(Debug) << "Modules: " << std::endl;
for (unsigned int i = 0; i < module_.size(); ++i)
{
LOG(Debug) << std::setw(4) << i << ": "
<< getModuleName(i) << std::endl;
}
}
// module graph ////////////////////////////////////////////////////////////////
Graph<unsigned int> VirtualMachine::getModuleGraph(void)
{
if (graphOutdated_)
{
makeModuleGraph();
graphOutdated_ = false;
}
return graph_;
}
void VirtualMachine::makeModuleGraph(void)
{
Graph<unsigned int> graph;
// create vertices // create vertices
for (unsigned int m = 0; m < module_.size(); ++m) for (unsigned int m = 0; m < module_.size(); ++m)
{ {
moduleGraph.addVertex(m); graph.addVertex(m);
} }
// create edges // create edges
for (unsigned int m = 0; m < module_.size(); ++m) for (unsigned int m = 0; m < module_.size(); ++m)
{ {
for (auto &in: module_[m].input) for (auto &in: module_[m].input)
{ {
moduleGraph.addEdge(env().getObjectModule(in), m); graph.addEdge(env().getObjectModule(in), m);
} }
} }
graph_ = graph;
return moduleGraph;
} }
// general execution /////////////////////////////////////////////////////////// // memory profile //////////////////////////////////////////////////////////////
#define BIG_SEP "===============" const VirtualMachine::MemoryProfile & VirtualMachine::getMemoryProfile(void)
#define SEP "---------------"
#define MEM_MSG(size) sizeString(size)
VirtualMachine::Size
VirtualMachine::executeProgram(const std::vector<unsigned int> &p)
{ {
Size memPeak = 0, sizeBefore, sizeAfter; if (memoryProfileOutdated_)
std::vector<std::set<unsigned int>> freeProg; {
makeMemoryProfile();
memoryProfileOutdated_ = false;
}
return profile_;
}
void VirtualMachine::makeMemoryProfile(void)
{
bool protect = env().objectsProtected();
bool hmsg = HadronsLogMessage.isActive();
bool gmsg = GridLogMessage.isActive();
bool err = HadronsLogError.isActive();
auto program = getModuleGraph().topoSort();
resetProfile();
profile_.module.resize(getNModule());
env().protectObjects(false);
GridLogMessage.Active(false);
HadronsLogMessage.Active(false);
HadronsLogError.Active(false);
for (auto it = program.rbegin(); it != program.rend(); ++it)
{
auto a = *it;
if (profile_.module[a].empty())
{
LOG(Debug) << "Profiling memory for module '" << module_[a].name
<< "' (" << a << ")..." << std::endl;
memoryProfile(a);
env().freeAll();
}
}
env().protectObjects(protect);
GridLogMessage.Active(gmsg);
HadronsLogMessage.Active(hmsg);
HadronsLogError.Active(err);
LOG(Debug) << "Memory profile:" << std::endl;
LOG(Debug) << "----------------" << std::endl;
for (unsigned int a = 0; a < profile_.module.size(); ++a)
{
LOG(Debug) << getModuleName(a) << " (" << a << ")" << std::endl;
for (auto &o: profile_.module[a])
{
LOG(Debug) << "|__ " << env().getObjectName(o.first) << " ("
<< sizeString(o.second) << ")" << std::endl;
}
LOG(Debug) << std::endl;
}
LOG(Debug) << "----------------" << std::endl;
}
void VirtualMachine::resetProfile(void)
{
profile_.module.clear();
profile_.object.clear();
}
void VirtualMachine::resizeProfile(void)
{
if (env().getMaxAddress() > profile_.object.size())
{
MemoryPrint empty;
empty.size = 0;
empty.module = -1;
profile_.object.resize(env().getMaxAddress(), empty);
}
}
void VirtualMachine::updateProfile(const unsigned int address)
{
resizeProfile();
for (unsigned int a = 0; a < env().getMaxAddress(); ++a)
{
if (env().hasCreatedObject(a) and (profile_.object[a].module == -1))
{
profile_.object[a].size = env().getObjectSize(a);
profile_.object[a].module = address;
profile_.module[address][a] = profile_.object[a].size;
if (env().getObjectModule(a) < 0)
{
env().setObjectModule(a, address);
}
}
}
}
void VirtualMachine::cleanEnvironment(void)
{
resizeProfile();
for (unsigned int a = 0; a < env().getMaxAddress(); ++a)
{
if (env().hasCreatedObject(a) and (profile_.object[a].module == -1))
{
env().freeObject(a);
}
}
}
void VirtualMachine::memoryProfile(const unsigned int address)
{
auto m = getModule(address);
LOG(Debug) << "Setting up module '" << m->getName()
<< "' (" << address << ")..." << std::endl;
try
{
m->setup();
updateProfile(address);
}
catch (Exceptions::Definition &)
{
cleanEnvironment();
for (auto &in: m->getInput())
{
memoryProfile(env().getObjectModule(in));
}
for (auto &ref: m->getReference())
{
memoryProfile(env().getObjectModule(ref));
}
m->setup();
updateProfile(address);
}
}
void VirtualMachine::memoryProfile(const std::string name)
{
memoryProfile(getModuleAddress(name));
}
// garbage collector ///////////////////////////////////////////////////////////
VirtualMachine::GarbageSchedule
VirtualMachine::makeGarbageSchedule(const std::vector<unsigned int> &p) const
{
GarbageSchedule freeProg;
// build garbage collection schedule
LOG(Debug) << "Building garbage collection schedule..." << std::endl;
freeProg.resize(p.size()); freeProg.resize(p.size());
for (unsigned int i = 0; i < env().getMaxAddress(); ++i) for (unsigned int i = 0; i < env().getMaxAddress(); ++i)
{ {
@ -310,34 +441,42 @@ VirtualMachine::executeProgram(const std::vector<unsigned int> &p)
} }
} }
return freeProg;
}
// general execution ///////////////////////////////////////////////////////////
#define BIG_SEP "==============="
#define SEP "---------------"
#define MEM_MSG(size) sizeString(size)
void VirtualMachine::executeProgram(const std::vector<unsigned int> &p) const
{
Size memPeak = 0, sizeBefore, sizeAfter;
GarbageSchedule freeProg;
// build garbage collection schedule
LOG(Debug) << "Building garbage collection schedule..." << std::endl;
freeProg = makeGarbageSchedule(p);
// program execution // program execution
LOG(Debug) << "Executing program..." << std::endl; LOG(Debug) << "Executing program..." << std::endl;
for (unsigned int i = 0; i < p.size(); ++i) for (unsigned int i = 0; i < p.size(); ++i)
{ {
// execute module // execute module
if (!isDryRun()) LOG(Message) << SEP << " Measurement step " << i + 1 << "/"
{ << p.size() << " (module '" << module_[p[i]].name
LOG(Message) << SEP << " Measurement step " << i+1 << "/" << "') " << SEP << std::endl;
<< p.size() << " (module '" << module_[p[i]].name
<< "') " << SEP << std::endl;
}
(*module_[p[i]].data)(); (*module_[p[i]].data)();
sizeBefore = env().getTotalSize(); sizeBefore = env().getTotalSize();
// print used memory after execution // print used memory after execution
if (!isDryRun()) LOG(Message) << "Allocated objects: " << MEM_MSG(sizeBefore)
{ << std::endl;
LOG(Message) << "Allocated objects: " << MEM_MSG(sizeBefore)
<< std::endl;
}
if (sizeBefore > memPeak) if (sizeBefore > memPeak)
{ {
memPeak = sizeBefore; memPeak = sizeBefore;
} }
// garbage collection for step i // garbage collection for step i
if (!isDryRun()) LOG(Message) << "Garbage collection..." << std::endl;
{
LOG(Message) << "Garbage collection..." << std::endl;
}
for (auto &j: freeProg[i]) for (auto &j: freeProg[i])
{ {
env().freeObject(j); env().freeObject(j);
@ -352,25 +491,20 @@ VirtualMachine::executeProgram(const std::vector<unsigned int> &p)
} }
} }
// print used memory after garbage collection if necessary // print used memory after garbage collection if necessary
if (!isDryRun()) sizeAfter = env().getTotalSize();
if (sizeBefore != sizeAfter)
{ {
sizeAfter = env().getTotalSize(); LOG(Message) << "Allocated objects: " << MEM_MSG(sizeAfter)
if (sizeBefore != sizeAfter) << std::endl;
{ }
LOG(Message) << "Allocated objects: " << MEM_MSG(sizeAfter) else
<< std::endl; {
} LOG(Message) << "Nothing to free" << std::endl;
else
{
LOG(Message) << "Nothing to free" << std::endl;
}
} }
} }
return memPeak;
} }
VirtualMachine::Size VirtualMachine::executeProgram(const std::vector<std::string> &p) void VirtualMachine::executeProgram(const std::vector<std::string> &p) const
{ {
std::vector<unsigned int> pAddress; std::vector<unsigned int> pAddress;
@ -378,138 +512,5 @@ VirtualMachine::Size VirtualMachine::executeProgram(const std::vector<std::strin
{ {
pAddress.push_back(getModuleAddress(n)); pAddress.push_back(getModuleAddress(n));
} }
executeProgram(pAddress);
return executeProgram(pAddress);
}
// print VM content ////////////////////////////////////////////////////////////
void VirtualMachine::printContent(void) const
{
LOG(Debug) << "Modules: " << std::endl;
for (unsigned int i = 0; i < module_.size(); ++i)
{
LOG(Debug) << std::setw(4) << i << ": "
<< getModuleName(i) << std::endl;
}
}
// memory profile //////////////////////////////////////////////////////////////
VirtualMachine::MemoryProfile VirtualMachine::memoryProfile(void) const
{
bool protect = env().objectsProtected();
bool hmsg = HadronsLogMessage.isActive();
bool gmsg = GridLogMessage.isActive();
bool err = HadronsLogError.isActive();
MemoryProfile profile;
auto program = makeModuleGraph().topoSort();
profile.module.resize(getNModule());
env().protectObjects(false);
GridLogMessage.Active(false);
HadronsLogMessage.Active(false);
HadronsLogError.Active(false);
for (auto it = program.rbegin(); it != program.rend(); ++it)
{
auto a = *it;
if (profile.module[a].empty())
{
LOG(Debug) << "Profiling memory for module '" << module_[a].name
<< "' (" << a << ")..." << std::endl;
memoryProfile(profile, a);
env().freeAll();
}
}
env().protectObjects(protect);
GridLogMessage.Active(gmsg);
HadronsLogMessage.Active(hmsg);
HadronsLogError.Active(err);
LOG(Debug) << "Memory profile:" << std::endl;
LOG(Debug) << "----------------" << std::endl;
for (unsigned int a = 0; a < profile.module.size(); ++a)
{
LOG(Debug) << getModuleName(a) << " (" << a << ")" << std::endl;
for (auto &o: profile.module[a])
{
LOG(Debug) << "|__ " << env().getObjectName(o.first) << " ("
<< sizeString(o.second) << ")" << std::endl;
}
LOG(Debug) << std::endl;
}
LOG(Debug) << "----------------" << std::endl;
return profile;
}
void VirtualMachine::resizeProfile(MemoryProfile &profile) const
{
if (env().getMaxAddress() > profile.object.size())
{
MemoryPrint empty;
empty.size = 0;
empty.module = -1;
profile.object.resize(env().getMaxAddress(), empty);
}
}
void VirtualMachine::updateProfile(MemoryProfile &profile,
const unsigned int address) const
{
resizeProfile(profile);
for (unsigned int a = 0; a < env().getMaxAddress(); ++a)
{
if (env().hasCreatedObject(a) and (profile.object[a].module == -1))
{
profile.object[a].size = env().getObjectSize(a);
profile.object[a].module = address;
profile.module[address][a] = profile.object[a].size;
}
}
}
void VirtualMachine::cleanEnvironment(MemoryProfile &profile) const
{
resizeProfile(profile);
for (unsigned int a = 0; a < env().getMaxAddress(); ++a)
{
if (env().hasCreatedObject(a) and (profile.object[a].module == -1))
{
env().freeObject(a);
}
}
}
void VirtualMachine::memoryProfile(MemoryProfile &profile,
const unsigned int address) const
{
auto m = getModule(address);
LOG(Debug) << "Setting up module '" << m->getName() << "' (" << address << ")..." << std::endl;
try
{
m->setup();
updateProfile(profile, address);
}
catch (Exceptions::Definition &)
{
cleanEnvironment(profile);
for (auto &in: m->getInput())
{
memoryProfile(profile, env().getObjectModule(in));
}
for (auto &ref: m->getReference())
{
memoryProfile(profile, env().getObjectModule(ref));
}
m->setup();
updateProfile(profile, address);
}
}
void VirtualMachine::memoryProfile(MemoryProfile &profile,
const std::string name) const
{
memoryProfile(profile, getModuleAddress(name));
} }

View File

@ -51,8 +51,9 @@ class VirtualMachine
{ {
SINGLETON_DEFCTOR(VirtualMachine); SINGLETON_DEFCTOR(VirtualMachine);
public: public:
typedef SITE_SIZE_TYPE Size; typedef SITE_SIZE_TYPE Size;
typedef std::unique_ptr<ModuleBase> ModPt; typedef std::unique_ptr<ModuleBase> ModPt;
typedef std::vector<std::set<unsigned int>> GarbageSchedule;
struct MemoryPrint struct MemoryPrint
{ {
Size size; Size size;
@ -73,11 +74,6 @@ private:
size_t maxAllocated; size_t maxAllocated;
}; };
public: public:
// dry run
void dryRun(const bool isDry);
bool isDryRun(void) const;
void memoryProfile(const bool doMemoryProfile);
bool doMemoryProfile(void) const;
// trajectory counter // trajectory counter
void setTrajectory(const unsigned int traj); void setTrajectory(const unsigned int traj);
unsigned int getTrajectory(void) const; unsigned int getTrajectory(void) const;
@ -106,32 +102,47 @@ public:
std::string getModuleNamespace(const std::string name) const; std::string getModuleNamespace(const std::string name) const;
bool hasModule(const unsigned int address) const; bool hasModule(const unsigned int address) const;
bool hasModule(const std::string name) const; bool hasModule(const std::string name) const;
Graph<unsigned int> makeModuleGraph(void) const;
void checkGraph(void) const;
// print VM content // print VM content
void printContent(void) const; void printContent(void) const;
// module graph (could be a const reference if topoSort was const)
Graph<unsigned int> getModuleGraph(void);
// memory profile // memory profile
MemoryProfile memoryProfile(void) const; const MemoryProfile &getMemoryProfile(void);
// garbage collector
GarbageSchedule makeGarbageSchedule(const std::vector<unsigned int> &p) const;
// high-water memory function
Size memoryNeeded(const std::vector<unsigned int> &p,
const GarbageSchedule &g);
Size memoryNeeded(const std::vector<unsigned int> &p);
// general execution // general execution
Size executeProgram(const std::vector<unsigned int> &p); void executeProgram(const std::vector<unsigned int> &p) const;
Size executeProgram(const std::vector<std::string> &p); void executeProgram(const std::vector<std::string> &p) const;
private: private:
// environment shortcut // environment shortcut
DEFINE_ENV_ALIAS; DEFINE_ENV_ALIAS;
// module graph
void makeModuleGraph(void);
// memory profile // memory profile
void resizeProfile(MemoryProfile &profile) const; void makeMemoryProfile(void);
void updateProfile(MemoryProfile &profile, const unsigned int address) const; void resetProfile(void);
void cleanEnvironment(MemoryProfile &profile) const; void resizeProfile(void);
void memoryProfile(MemoryProfile &profile, const std::string name) const; void updateProfile(const unsigned int address);
void memoryProfile(MemoryProfile &profile, const unsigned int address) const; void cleanEnvironment(void);
void memoryProfile(const std::string name);
void memoryProfile(const unsigned int address);
private: private:
// general // general
bool dryRun_{false}, memoryProfile_{false};
unsigned int traj_; unsigned int traj_;
// module and related maps // module and related maps
std::vector<ModuleInfo> module_; std::vector<ModuleInfo> module_;
std::map<std::string, unsigned int> moduleAddress_; std::map<std::string, unsigned int> moduleAddress_;
std::string currentModule_{""}; std::string currentModule_{""};
// module graph
bool graphOutdated_{true};
Graph<unsigned int> graph_;
// memory profile
bool memoryProfileOutdated_{true};
MemoryProfile profile_;
}; };
/****************************************************************************** /******************************************************************************