From ed4f2fc4177a81921b4e2a23939d0a8328891b9b Mon Sep 17 00:00:00 2001 From: Rafal Bielski <rafal.bielski@cern.ch> Date: Wed, 21 Nov 2018 16:13:36 +0100 Subject: [PATCH] add time burning option to MTCalibPebHypoTool also change the tool input from a vector to a single object (no need for multiple inputs) Former-commit-id: 6ec3aabde193a328bef99ecbb9c4e190503cfb90 --- .../TrigExPartialEB/share/MTCalibPeb.py | 4 ++ .../TrigExPartialEB/src/MTCalibPebHypoAlg.cxx | 9 +-- .../src/MTCalibPebHypoTool.cxx | 66 +++++++++++++++---- .../TrigExPartialEB/src/MTCalibPebHypoTool.h | 30 ++++++--- 4 files changed, 84 insertions(+), 25 deletions(-) diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py index dd5a507f2dc..599385c5751 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/share/MTCalibPeb.py @@ -55,9 +55,13 @@ hypo.HypoOutputDecisions = "MTCalibPebDecisions" hypoTool1 = MTCalibPebHypoTool("HLT_MTCalibPeb1") hypoTool1.RandomAcceptRate = 0.75 +hypoTool1.BurnTimePerCycleMillisec = 200 +hypoTool1.NumBurnCycles = 3 hypoTool2 = MTCalibPebHypoTool("HLT_MTCalibPeb2") hypoTool2.RandomAcceptRate = 0.25 +hypoTool2.BurnTimePerCycleMillisec = 1000 +hypoTool2.NumBurnCycles = 10 hypo.HypoTools = [hypoTool1, hypoTool2] diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoAlg.cxx b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoAlg.cxx index b752081e438..9d8a72ff20b 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoAlg.cxx +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoAlg.cxx @@ -28,6 +28,7 @@ MTCalibPebHypoAlg::~MTCalibPebHypoAlg() {} // ============================================================================= StatusCode MTCalibPebHypoAlg::initialize() { ATH_MSG_INFO("Initialising " << name()); + ATH_CHECK(m_hypoTools.retrieve()); return StatusCode::SUCCESS; } @@ -36,6 +37,7 @@ StatusCode MTCalibPebHypoAlg::initialize() { // ============================================================================= StatusCode MTCalibPebHypoAlg::finalize() { ATH_MSG_INFO("Finalising " << name()); + ATH_CHECK(m_hypoTools.release()); return StatusCode::SUCCESS; } @@ -50,12 +52,11 @@ StatusCode MTCalibPebHypoAlg::execute_r(const EventContext& eventContext) const auto aux = std::make_unique<DecisionAuxContainer>(); decisions->setStore(aux.get()); - // Prepare input for hypo tools - std::vector<MTCalibPebHypoTool::Input> toolInput; - // Create new decision Decision* newd = newDecisionIn(decisions.get()); // DecisionContainer decisions owns the pointer - toolInput.emplace_back(newd); + + // Prepare input for hypo tools + MTCalibPebHypoTool::Input toolInput(newd, eventContext); // Call the hypo tools for (const auto& tool: m_hypoTools) { diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx index ecb5371e293..c94abfa7cfe 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.cxx @@ -2,15 +2,37 @@ Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration */ +// Trigger includes #include "MTCalibPebHypoTool.h" + +// Athena includes +#include "AthenaKernel/Timeout.h" + +// System includes #include <random> +#include <thread> // Local implementation-specific helper methods namespace { + /// Returns a reference to static thread-local random number generator + std::mt19937& threadLocalGenerator() { + static thread_local std::random_device rd; // used only to ensure different seeds for mt19937 + static thread_local std::mt19937 generator(rd()); + return generator; + } + /// Basic random real number generation + template<typename T> T randomRealNumber(const T min, const T max) { + std::uniform_real_distribution<T> distribution(min, max); + return distribution(threadLocalGenerator()); + } + /// Basic random integer generation + template<typename T> T randomInteger(const T min, const T max) { + std::uniform_int_distribution<T> distribution(min, max); + return distribution(threadLocalGenerator()); + } + /// Random bool with a given true rate bool randomAccept(const double acceptRate) { - static thread_local std::mt19937 generator; - std::uniform_real_distribution<double> distribution(0.0, 1.0); - return (distribution(generator) < acceptRate); + return (randomRealNumber(0.0, 1.0) < acceptRate); } } @@ -35,17 +57,37 @@ StatusCode MTCalibPebHypoTool::initialize() { } // ============================================================================= -StatusCode MTCalibPebHypoTool::decide(const std::vector<MTCalibPebHypoTool::Input>& inputs) const { +StatusCode MTCalibPebHypoTool::decide(const MTCalibPebHypoTool::Input& input) const { - bool accept = randomAccept(m_acceptRate); - for (auto& in : inputs) { - if (accept) { - ATH_MSG_DEBUG("Decision " << m_decisionId << " is accept"); - TrigCompositeUtils::addDecisionID(m_decisionId, in.decision); - } - else { - ATH_MSG_DEBUG("Decision " << m_decisionId << " is reject"); + // --------------------------------------------------------------------------- + // Burn CPU time + // --------------------------------------------------------------------------- + for (unsigned int iCycle = 0; iCycle < m_numBurnCycles; ++iCycle) { + if (Athena::Timeout::instance(input.eventContext).reached()) { + if (m_failOnTimeout) { + ATH_MSG_ERROR("Timeout reached in CPU time burning cycle # " << iCycle+1 << " and FailOnTimeout is true"); + return StatusCode::FAILURE; + } + ATH_MSG_INFO("Timeout reached in CPU time burning cycle # " << iCycle+1); + break; } + unsigned int burnTime = m_burnTimeRandomly + ? randomInteger<unsigned int>(0, m_burnTimePerCycleMillisec) + : m_burnTimePerCycleMillisec.value(); + ATH_MSG_VERBOSE("CPU time burning cycle # " << iCycle+1 << ", burn time [ms] = " << burnTime); + std::this_thread::sleep_for(std::chrono::milliseconds(burnTime)); + } + + // --------------------------------------------------------------------------- + // Random accept decision + // --------------------------------------------------------------------------- + bool accept = randomAccept(m_acceptRate); + if (accept) { + ATH_MSG_DEBUG("Decision " << m_decisionId << " is accept"); + TrigCompositeUtils::addDecisionID(m_decisionId, input.decision); + } + else { + ATH_MSG_DEBUG("Decision " << m_decisionId << " is reject"); } return StatusCode::SUCCESS; diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h index 2fa92ae5974..d46d97904a8 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/src/MTCalibPebHypoTool.h @@ -15,9 +15,6 @@ // TDAQ includes #include "eformat/StreamTag.h" -// System includes -#include <random> - /** @class MTCalibPebHypoTool * @brief Base class for tools used by MTCalibPebHypoAlg **/ @@ -33,23 +30,38 @@ public: // ------------------------- Public types ------------------------------------ struct Input { - Input(TrigCompositeUtils::Decision* d) - : decision(d) {} + Input(TrigCompositeUtils::Decision* d, const EventContext& ctx) + : decision(d), eventContext(ctx) {} TrigCompositeUtils::Decision* decision; + const EventContext& eventContext; }; // ------------------------- Specific methods of this class ------------------ /// Decides whether to accept the event - StatusCode decide(const std::vector<Input>& inputs) const; + StatusCode decide(const Input& input) const; private: // ------------------------- Properties -------------------------------------- Gaudi::Property<double> m_acceptRate { - this, - "RandomAcceptRate", - -1, + this, "RandomAcceptRate", -1, "Rate of random accepts, <=0 is never, >=1 is always" }; + Gaudi::Property<unsigned int> m_burnTimePerCycleMillisec { + this, "BurnTimePerCycleMillisec", 0, + "Burn time per cycle in milliseconds" + }; + Gaudi::Property<unsigned int> m_numBurnCycles { + this, "NumBurnCycles", 0, + "Number of time burning cycles" + }; + Gaudi::Property<bool> m_burnTimeRandomly { + this, "BurnTimeRandomly", true, + "If true, burn time per cycle is a random value from uniform distribution between 0 and the given value" + }; + Gaudi::Property<bool> m_failOnTimeout { + this, "FailOnTimeout", true, + "If true, the execution will return StatusCode::FAILURE when Athena timeout is detected" + }; // ------------------------- Other private members --------------------------- /// The decision id of the tool instance -- GitLab