Skip to content
Snippets Groups Projects
Commit 3e5a5024 authored by Tadej Novak's avatar Tadej Novak
Browse files

Merge branch 'component_factories' into 'main'

allow switching component creation from dictionaries to factory functions

See merge request !68703
parents e411bed5 bc6477a1
No related branches found
No related tags found
No related merge requests found
/*
Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
*/
/// @author Nils Krumnack
#ifndef ASG_TOOLS__ASG_COMPONENT_FACTORIES_H
#define ASG_TOOLS__ASG_COMPONENT_FACTORIES_H
#include <AsgMessaging/StatusCode.h>
#include <functional>
#include <memory>
namespace asg
{
class AsgComponent;
#ifdef XAOD_STANDALONE
/// @brief register a factory for the given tool type
StatusCode registerComponentFactory (const std::string& type, const std::function<std::unique_ptr<AsgComponent>(const std::string& name)>& factory);
/// @brief get the factory for the given tool type (or null if none exists)
const std::function<std::unique_ptr<AsgComponent>(const std::string& name)> *getComponentFactory (const std::string& type);
/// @brief simple helpers to register factories via templates
///
/// There is one for each component type, as they can differ in their constructor.
///
/// @{
template<typename T> StatusCode registerToolFactory (const std::string& type)
{
return registerComponentFactory (type, [] (const std::string& name) -> std::unique_ptr<AsgComponent> { return std::make_unique<T> (name); });
}
template<typename T> StatusCode registerServiceFactory (const std::string& type)
{
return registerComponentFactory (type, [] (const std::string& name) -> std::unique_ptr<AsgComponent> { return std::make_unique<T> (name, nullptr); });
}
template<typename T> StatusCode registerAlgorithmFactory (const std::string& type)
{
return registerComponentFactory (type, [] (const std::string& name) -> std::unique_ptr<AsgComponent> { return std::make_unique<T> (name, nullptr); });
}
/// @}
#endif
}
#endif
......@@ -18,6 +18,7 @@
#ifdef XAOD_STANDALONE
#include <AsgTools/AsgComponent.h>
#include <AsgTools/AsgComponentFactories.h>
#include <AsgTools/AsgTool.h>
#include <AsgTools/AnaToolHandle.h>
#include <TInterpreter.h>
......@@ -260,6 +261,21 @@ namespace asg
{
using namespace msgComponentConfig;
const auto *factory = getComponentFactory (type);
if (factory)
{
ANA_MSG_DEBUG ("using registered factory for type " << type);
component = (*factory) (name);
if (component == nullptr)
{
ANA_MSG_ERROR ("factory for type " << type << " returned a null pointer");
return StatusCode::FAILURE;
}
return StatusCode::SUCCESS;
}
ANA_MSG_DEBUG ("using dictionary as factory for type " << type);
// Load the ROOT dictionary, this is needed to be able to
// instantiate the component below, i.e. the code below won't load
// dictionaries not already loaded
......
/*
Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
*/
/// @author Nils Krumnack
//
// includes
//
#include <AsgTools/AsgComponentFactories.h>
#include <AsgTools/IAsgTool.h>
#include <AsgTools/MessageCheckAsgTools.h>
#include <tbb/concurrent_unordered_map.h>
//
// method implementations
//
namespace asg
{
#ifdef XAOD_STANDALONE
namespace
{
tbb::concurrent_unordered_map<std::string, std::function<std::unique_ptr<AsgComponent>(const std::string& name)>> s_factories;
}
StatusCode registerComponentFactory (const std::string& type, const std::function<std::unique_ptr<AsgComponent>(const std::string& name)>& factory)
{
using namespace msgComponentConfig;
if (!s_factories.emplace (type, factory).second)
{
ATH_MSG_ERROR ("attempt to register a factory for type " << type << " that already has a factory");
return StatusCode::FAILURE;
}
return StatusCode::SUCCESS;
}
const std::function<std::unique_ptr<AsgComponent>(const std::string& name)> *getComponentFactory (const std::string& type)
{
auto iter = s_factories.find (type);
if (iter == s_factories.end())
return nullptr;
return &iter->second;
}
#endif
}
......@@ -35,6 +35,9 @@ parser.add_option( '--algorithm-timer', dest='algorithm_timer',
parser.add_option( '--algorithm-memory', dest='algorithm_memory',
action = 'store_true', default = False,
help = 'Run the job with a memory monitor for each algorithm' )
parser.add_option( '--factory-preload', dest='factory_preload',
action = 'store', type = 'str', default = '',
help = 'Factory preloader(s) to run at the beginning of the job' )
parser.add_option( '--no-systematics', dest='no_systematics',
action = 'store_true', default = False,
help = 'Configure the job to with no systematics' )
......@@ -131,6 +134,8 @@ if options.algorithm_timer :
job.options().setBool( ROOT.EL.Job.optAlgorithmTimer, True )
if options.algorithm_memory :
job.options().setBool( ROOT.EL.Job.optAlgorithmMemoryMonitor, True )
if options.factory_preload != '' :
job.options().setString( ROOT.EL.Job.optFactoryPreload, options.factory_preload )
from AnalysisAlgorithmsConfig.FullCPAlgorithmsTest import makeSequence, printSequenceAlgs
......
/*
Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
*/
/// @author Nils Krumnack
#ifndef EVENT_LOOP__FACTORY_PRELOAD_MODULE_H
#define EVENT_LOOP__FACTORY_PRELOAD_MODULE_H
#include <EventLoop/Global.h>
#include <EventLoop/Module.h>
namespace EL
{
namespace Detail
{
/// \brief a \ref Module preloading all the registered factories
///
/// This is just a temporary module to test whether using factories reduces
/// memory usage.
class FactoryPreloadModule final : public Module
{
/// Public Members
/// ==============
public:
std::string preloader;
FactoryPreloadModule (const std::string& val_preloader);
StatusCode onInitialize (ModuleData& data) override;
};
}
}
#endif
......@@ -210,6 +210,10 @@ namespace EL
static const std::string optAlgorithmMemoryMonitor;
/// \brief a boolean flag for whether to perform a component factory preload
static const std::string optFactoryPreload;
/// description: the name of the option used for setting the
/// maximum number of events to process per sample
/// rationale: this is used for test runs where you don't want to
......
/*
Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
*/
/// @author Nils Krumnack
//
// includes
//
#include <EventLoop/FactoryPreloadModule.h>
#include <AsgTools/MessageCheckAsgTools.h>
#include <EventLoop/MessageCheck.h>
#include <TInterpreter.h>
#include <TSystem.h>
#include <boost/algorithm/string.hpp>
//
// method implementations
//
namespace EL
{
namespace Detail
{
FactoryPreloadModule ::
FactoryPreloadModule (const std::string& val_preloader)
: preloader (val_preloader)
{
}
StatusCode FactoryPreloadModule::onInitialize (ModuleData& /*data*/)
{
using namespace msgEventLoop;
std::vector<std::string> preloaderList;
boost::split (preloaderList, preloader, boost::is_any_of (","));
if (preloaderList.size() % 2 != 0)
{
ANA_MSG_ERROR ("Invalid preloader list");
return StatusCode::FAILURE;
}
for (std::size_t iter = 0; iter < preloaderList.size(); iter += 2)
{
const std::string& libName = preloaderList[iter];
const std::string& funcName = preloaderList[iter + 1];
if (gSystem->Load(libName.c_str()) != 0)
{
ANA_MSG_ERROR ("Failed to load library " << libName);
return StatusCode::FAILURE;
}
if (gInterpreter->Calc((funcName + "()").c_str()) != 1)
{
ANA_MSG_ERROR ("Failed to call function " << funcName << " from library " << libName);
return StatusCode::FAILURE;
}
}
return StatusCode::SUCCESS;
}
}
}
......@@ -37,6 +37,7 @@ namespace EL
const std::string Job::optUniqueDateFormat = "nc_EventLoop_UniqueDateFormat";
const std::string Job::optAlgorithmTimer = "nc_EventLoop_AlgorithmTimer";
const std::string Job::optAlgorithmMemoryMonitor = "nc_EventLoop_AlgorithmMemoryMonitor";
const std::string Job::optFactoryPreload = "nc_EventLoop_FactoryPreload";
const std::string Job::optMaxEvents = "nc_EventLoop_MaxEvents";
const std::string Job::optSkipEvents = "nc_EventLoop_SkipEvents";
const std::string Job::optWorkerConfigFile = "nc_EventLoop_WorkerConfigFile";
......
......@@ -23,6 +23,7 @@
#include <EventLoop/Driver.h>
#include <EventLoop/EventCountModule.h>
#include <EventLoop/EventRange.h>
#include <EventLoop/FactoryPreloadModule.h>
#include <EventLoop/FileExecutedModule.h>
#include <EventLoop/GridReportingModule.h>
#include <EventLoop/Job.h>
......@@ -385,6 +386,9 @@ namespace EL
m_modules.push_back (std::make_unique<Detail::MemoryMonitorModule> ("EarlyMemoryMonitor"));
if (xAODInput)
m_modules.push_back (std::make_unique<Detail::TEventModule> ());
auto factoryPreload = metaData()->castString (Job::optFactoryPreload, "");
if (!factoryPreload.empty())
m_modules.push_back (std::make_unique<Detail::FactoryPreloadModule> (factoryPreload));
m_modules.push_back (std::make_unique<Detail::LeakCheckModule> ());
m_modules.push_back (std::make_unique<Detail::StopwatchModule> ());
if (metaData()->castBool (Job::optGridReporting, false))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment