Skip to content
Commits on Source (37)
......@@ -7,6 +7,36 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
## [Unreleased][]
## [v35r3][] - 2021-04-20
Another minor bugfix release with more fixes for ROOT 6.22 and improvements to the CMake configuration.
Here is a summary of the changes (see the [full list of changes](https://gitlab.cern.ch/gaudi/Gaudi/compare/v35r2...v35r3)).
### Changed
- Change how optional dependencies are handled in downstream projects (gaudi/Gaudi!1194)
- Remove serial task queue (gaudi/Gaudi!1195)
- Switch to latest ATLAS task precedence scenario in a test (gaudi/Gaudi!1190)
- Change `DevBuildType` to also enable `-Wsuggest-override` on clang if version >= 11 (gaudi/Gaudi!1191)
### Added
- Test algorithm with internal multithreading (gaudi/Gaudi!1196)
- Added a cardinality setting for `AtlasMCRecoScenario` (gaudi/Gaudi!1201)
- Extend the task precedence tracer for dumping dynamic graphs (gaudi/Gaudi!1189)
- Allow use of local targets instead of imported ones (gaudi/Gaudi!1186)
### Fixed
- Allow returning void in a `MergingTransformer` (gaudi/Gaudi!1199)
- Add small test and fix for GaudiPython.Bindings.iDataSvc traversal (gaudi/Gaudi!1178)
- Fix handling of properties for tuples and arrays of size 1 (gaudi/Gaudi#21, gaudi/Gaudi!1197)
- Add dynamic dependencies scan for `genreflex` dictionaries (gaudi/Gaudi#152 gaudi/Gaudi!1183)
- Improvements on Monitoring::Hub::Entity and accumulators (gaudi/Gaudi!1185)
- Suppress warnings about `nodiscard` in dictionary generation with ROOT 6.22 (gaudi/Gaudi!1182)
- Add custom pythonization callback to SmartRefVector (gaudi/Gaudi!1180)
- Fixed bug in Histogram filling (gaudi/Gaudi!1176)
- Improve support for new style CMake projects (gaudi/Gaudi!1177)
## [v35r2][] - 2021-03-10
Just a minor bugfix release with changes required for
- ROOT 6.22 (updated PyROOT/cppyy)
......@@ -655,7 +685,8 @@ Details about old versions of the project can be found in the
[GaudiRelease/doc](GaudiRelease/doc).
[Unreleased]: https://gitlab.cern.ch/gaudi/Gaudi/compare/v35r2...master
[Unreleased]: https://gitlab.cern.ch/gaudi/Gaudi/compare/v35r3...master
[v35r3]: https://gitlab.cern.ch/gaudi/Gaudi/-/releases/v35r3
[v35r2]: https://gitlab.cern.ch/gaudi/Gaudi/-/releases/v35r2
[v35r1]: https://gitlab.cern.ch/gaudi/Gaudi/-/releases/v35r1
[v35r0]: https://gitlab.cern.ch/gaudi/Gaudi/-/releases/v35r0
......
#####################################################################################
# (c) Copyright 1998-2020 CERN for the benefit of the LHCb and ATLAS collaborations #
# (c) Copyright 1998-2021 CERN for the benefit of the LHCb and ATLAS collaborations #
# #
# This software is distributed under the terms of the Apache version 2 licence, #
# copied verbatim in the file "LICENSE". #
......@@ -80,7 +80,7 @@ Maintainer's guide: `<https://twiki.cern.ch/twiki/bin/view/LHCb/MaintainGaudiCMa
cmake_minimum_required(VERSION 3.15)
project(Gaudi VERSION 35.2
project(Gaudi VERSION 35.3
LANGUAGES CXX
DESCRIPTION "Gaudi Software Framework"
HOMEPAGE_URL "https://cern.ch/gaudi")
......@@ -97,24 +97,11 @@ include(cmake/GaudiToolbox.cmake)
# Export the list of compile commands
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE BOOL "Enable/Disable output of compile_commands.json" FORCE)
# Options to choose dependencies that are not required to build Gaudi
foreach(optional_dependency IN ITEMS AIDA XERCESC CLHEP HEPPDT CPPUNIT UNWIND
GPERFTOOLS DOXYGEN JEMALLOC)
option(GAUDI_USE_${optional_dependency} "Enable the dependency ${optional_dependency}" ON)
set(GAUDI_OPTIONAL_DEPENDENCIES "${GAUDI_OPTIONAL_DEPENDENCIES}set(GAUDI_USE_${optional_dependency} ${GAUDI_USE_${optional_dependency}})\n")
endforeach()
# By default VTune is OFF
option(GAUDI_USE_INTELAMPLIFIER "Enable the dependency INTELAMPLIFIER" OFF)
set(GAUDI_OPTIONAL_DEPENDENCIES "${GAUDI_OPTIONAL_DEPENDENCIES}set(GAUDI_USE_INTELAMPLIFIER ${GAUDI_USE_INTELAMPLIFIER})\n")
set(GAUDI_USE_PYTHON_MAJOR 3 CACHE STRING "Major version of Python to use")
set(GAUDI_OPTIONAL_DEPENDENCIES "${GAUDI_OPTIONAL_DEPENDENCIES}set(GAUDI_USE_PYTHON_MAJOR ${GAUDI_USE_PYTHON_MAJOR})\n")
# Find all the dependencies of the project
list(PREPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules") # (Find*.cmake)
if(DEFINED CACHE{ROOT_DIR}) # Not to have the output displayed each time
set(GAUDI_DEPENDENCIES_FIND_QUIETLY TRUE)
endif()
include(cmake/GaudiDependencies.cmake)
# The C++ standard used must be the same as ROOT's
......
......@@ -536,6 +536,8 @@ namespace Gaudi::Functional::details {
static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
public:
using KeyValue = std::pair<std::string, std::string>;
using KeyValues = std::pair<std::string, std::vector<std::string>>;
DataHandleMixin( std::string name, ISvcLocator* pSvcLocator )
: BaseClass_t<Traits_>( std::move( name ), pSvcLocator ) {
// make sure this algorithm is seen as reentrant by Gaudi
......@@ -590,6 +592,13 @@ namespace Gaudi::Functional::details {
std::tuple<details::InputHandle_t<Traits_, In>...> m_inputs;
};
template <typename Traits_>
class DataHandleMixin<std::tuple<void>, std::tuple<>, Traits_>
: public DataHandleMixin<std::tuple<>, std::tuple<>, Traits_> {
public:
using DataHandleMixin<std::tuple<>, std::tuple<>, Traits_>::DataHandleMixin;
};
template <typename... Out, typename Traits_>
class DataHandleMixin<std::tuple<Out...>, std::tuple<>, Traits_> : public BaseClass_t<Traits_> {
static_assert( std::is_base_of_v<Algorithm, BaseClass_t<Traits_>>, "BaseClass must inherit from Algorithm" );
......
......@@ -26,10 +26,17 @@ namespace Gaudi::Functional {
namespace details {
template <typename Sig>
struct is_void_fun : std::false_type {};
template <typename... Args>
struct is_void_fun<void( Args... )> : std::true_type {};
template <typename Sig>
inline constexpr bool is_void_fun_v = is_void_fun<Sig>::value;
template <typename Signature, typename Traits_, bool isLegacy>
struct MergingTransformer;
////// Many of the same -> 1
////// Many of the same -> 1 or 0
template <typename Out, typename In, typename Traits_>
struct MergingTransformer<Out( const vector_of_const_<In>& ), Traits_, true>
: DataHandleMixin<std::tuple<Out>, std::tuple<>, Traits_> {
......@@ -40,6 +47,23 @@ namespace Gaudi::Functional {
using KeyValue = typename base_class::KeyValue;
using KeyValues = typename base_class::KeyValues;
MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs )
: base_class( std::move( name ), locator )
, m_inputLocations{this, inputs.first, inputs.second,
[=]( Gaudi::Details::PropertyBase& ) {
this->m_inputs =
make_vector_of_handles<decltype( this->m_inputs )>( this, m_inputLocations );
if ( std::is_pointer_v<In> ) { // handle constructor does not (yet) allow to set
// optional flag... so do it
// explicitly here...
std::for_each( this->m_inputs.begin(), this->m_inputs.end(),
[]( auto& h ) { h.setOptional( true ); } );
}
},
Gaudi::Details::Property::ImmediatelyInvokeHandler{true}} {
static_assert( std::is_void_v<Out> );
}
MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs, const KeyValue& output )
: base_class( std::move( name ), locator, output )
, m_inputLocations{this, inputs.first, inputs.second,
......@@ -53,7 +77,9 @@ namespace Gaudi::Functional {
[]( auto& h ) { h.setOptional( true ); } );
}
},
Gaudi::Details::Property::ImmediatelyInvokeHandler{true}} {}
Gaudi::Details::Property::ImmediatelyInvokeHandler{true}} {
static_assert( !std::is_void_v<Out> );
}
// accessor to input Locations
const std::string& inputLocation( unsigned int n ) const { return m_inputLocations.value()[n]; }
......@@ -65,7 +91,11 @@ namespace Gaudi::Functional {
ins.reserve( m_inputs.size() );
std::transform( m_inputs.begin(), m_inputs.end(), std::back_inserter( ins ), details2::get_from_handle<In>{} );
try {
put( std::get<0>( this->m_outputs ), std::as_const( *this )( std::as_const( ins ) ) );
if constexpr ( std::is_void_v<Out> ) {
std::as_const ( *this )( std::as_const( ins ) );
} else {
put( std::get<0>( this->m_outputs ), std::as_const( *this )( std::as_const( ins ) ) );
}
return FilterDecision::PASSED;
} catch ( GaudiException& e ) {
( e.code() ? this->warning() : this->error() ) << e.message() << endmsg;
......@@ -95,6 +125,23 @@ namespace Gaudi::Functional {
using KeyValue = typename base_class::KeyValue;
using KeyValues = typename base_class::KeyValues;
MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs )
: base_class( std::move( name ), locator )
, m_inputLocations{this, inputs.first, inputs.second,
[=]( Gaudi::Details::PropertyBase& ) {
this->m_inputs =
make_vector_of_handles<decltype( this->m_inputs )>( this, m_inputLocations );
if ( std::is_pointer_v<In> ) { // handle constructor does not (yet) allow to set
// optional flag... so do it
// explicitly here...
std::for_each( this->m_inputs.begin(), this->m_inputs.end(),
[]( auto& h ) { h.setOptional( true ); } );
}
},
Gaudi::Details::Property::ImmediatelyInvokeHandler{true}} {
static_assert( std::is_void_v<Out> );
}
MergingTransformer( std::string name, ISvcLocator* locator, const KeyValues& inputs, const KeyValue& output )
: base_class( std::move( name ), locator, output )
, m_inputLocations{this, inputs.first, inputs.second,
......@@ -108,7 +155,9 @@ namespace Gaudi::Functional {
[]( auto& h ) { h.setOptional( true ); } );
}
},
Gaudi::Details::Property::ImmediatelyInvokeHandler{true}} {}
Gaudi::Details::Property::ImmediatelyInvokeHandler{true}} {
static_assert( !std::is_void_v<Out> );
}
// accessor to input Locations
const std::string& inputLocation( unsigned int n ) const { return m_inputLocations.value()[n]; }
......@@ -120,7 +169,11 @@ namespace Gaudi::Functional {
ins.reserve( m_inputs.size() );
std::transform( m_inputs.begin(), m_inputs.end(), std::back_inserter( ins ), details2::get_from_handle<In>{} );
try {
put( std::get<0>( this->m_outputs ), ( *this )( std::as_const( ins ) ) );
if constexpr ( std::is_void_v<Out> ) {
( *this )( std::as_const( ins ) );
} else {
put( std::get<0>( this->m_outputs ), ( *this )( std::as_const( ins ) ) );
}
return FilterDecision::PASSED;
} catch ( GaudiException& e ) {
( e.code() ? this->warning() : this->error() ) << e.message() << endmsg;
......@@ -145,6 +198,11 @@ namespace Gaudi::Functional {
template <typename Signature, typename Traits_ = Traits::useDefaults>
using MergingTransformer = details::MergingTransformer<Signature, Traits_, details::isLegacy<Traits_>>;
// more meaningful alias for cases where the return type in Signature is void
template <typename Signature, typename Traits_ = Traits::useDefaults,
typename = std::enable_if_t<details::is_void_fun_v<Signature>>>
using MergingConsumer = details::MergingTransformer<Signature, Traits_, details::isLegacy<Traits_>>;
// Many of the same -> N
template <typename Signature, typename Traits_ = Traits::BaseClass_t<Gaudi::Algorithm>>
struct MergingMultiTransformer;
......
......@@ -46,7 +46,6 @@ gaudi_add_module(GaudiCoreSvc
src/MessageSvc/InertMessageSvc.cpp
src/MessageSvc/MessageSvc.cpp
src/MessageSvc/MessageSvcSink.cpp
src/MessageSvc/TBBMessageSvc.cpp
LINK
GaudiKernel
Python::Python
......
/***********************************************************************************\
* (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
* *
* This software is distributed under the terms of the Apache version 2 licence, *
* copied verbatim in the file "LICENSE". *
* *
* In applying this licence, CERN does not waive the privileges and immunities *
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\***********************************************************************************/
#include "TBBMessageSvc.h"
// ----------------------------------------------------------------------------
// Implementation file for class: TBBMessageSvc
//
// 22/06/2012: Marco Clemencic
// ----------------------------------------------------------------------------
DECLARE_COMPONENT( TBBMessageSvc )
void TBBMessageSvc::reportMessage( const Message& msg, int outputLevel ) {
m_messageQueue.add( new MessageWithLevel( *this, msg, outputLevel ) );
}
void TBBMessageSvc::reportMessage( const Message& msg ) { m_messageQueue.add( new MessageWithoutLevel( *this, msg ) ); }
void TBBMessageSvc::reportMessage( const StatusCode& code, const std::string& source ) {
m_messageQueue.add( new StatusCodeMessage( *this, code, source ) );
}
// ============================================================================
/***********************************************************************************\
* (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
* *
* This software is distributed under the terms of the Apache version 2 licence, *
* copied verbatim in the file "LICENSE". *
* *
* In applying this licence, CERN does not waive the privileges and immunities *
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\***********************************************************************************/
#ifndef MESSAGESVC_TBBMESSAGESVC_H
#define MESSAGESVC_TBBMESSAGESVC_H 1
// Include files
#include "MessageSvc.h"
#include "GaudiKernel/SerialTaskQueue.h"
// just needed for the thread id
#include <thread>
#include <thread>
/** @class TBMessageSvc TBMessageSvc.h MessageSvc/TBMessageSvc.h
*
* Extension to the standard MessageSvc that
*
* @author Marco Clemencic
* @date 22/06/2012
*/
class TBBMessageSvc : public MessageSvc {
public:
using MessageSvc::MessageSvc;
using MessageSvc::reportMessage;
/// Implementation of IMessageSvc::reportMessage()
void reportMessage( const Message& msg ) override;
/// Implementation of IMessageSvc::reportMessage()
void reportMessage( const Message& msg, int outputLevel ) override;
/// Implementation of IMessageSvc::reportMessage()
void reportMessage( const StatusCode& code, const std::string& source = "" ) override;
private:
// ============================================================================
// Helper tasks for message reporting.
// ============================================================================
/// Common base class for the different reportMessage cases.
class MessageTaskCommon : public Gaudi::SerialTaskQueue::WorkItem {
public:
MessageTaskCommon( TBBMessageSvc& svc ) : m_svc( svc ), m_sender( std::this_thread::get_id() ) {}
protected:
TBBMessageSvc& m_svc;
std::thread::id m_sender;
};
/// Specialized class to report a message with explicit output level.
class MessageWithLevel : public MessageTaskCommon {
public:
MessageWithLevel( TBBMessageSvc& svc, Message msg, int level )
: MessageTaskCommon( svc ), m_msg( msg ), m_level( level ) {}
void run() override { m_svc.i_reportMessage( m_msg, m_level ); }
private:
Message m_msg;
int m_level;
};
/// Specialized class to report a message with implicit output level.
class MessageWithoutLevel : public MessageTaskCommon {
public:
MessageWithoutLevel( TBBMessageSvc& svc, Message msg ) : MessageTaskCommon( svc ), m_msg( msg ) {}
void run() override {
const int level = m_svc.outputLevel( m_msg.getSource() );
m_svc.i_reportMessage( m_msg, level );
}
private:
Message m_msg;
};
/// Specialized class to report a StatusCode message.
class StatusCodeMessage : public MessageTaskCommon {
public:
StatusCodeMessage( TBBMessageSvc& svc, const StatusCode& sc, const std::string& source )
: MessageTaskCommon( svc ), m_sc( sc ), m_source( source ) {}
void run() override { m_svc.i_reportMessage( m_sc, m_source ); }
private:
StatusCode m_sc;
std::string m_source;
};
Gaudi::SerialTaskQueue m_messageQueue;
};
#endif // MESSAGESVC_TBBMESSAGESVC_H
......@@ -113,7 +113,9 @@ xProps.EmptyMap = {};
xProps.EmptyVector = [];
xProps.TupleStringIntDouble = ("hello", 10, 0.001);
xProps.TupleString = ("hello");
xProps.StdArrayDouble3 = (3.3, 2.2, 1.1);
xProps.StdArrayInt1 = (42);
xProps.GaudiMapSS = {"a": "1", "b": "2"};
......
......@@ -87,7 +87,9 @@ xProps.EmptyMap = {}
xProps.EmptyVector = []
xProps.TupleStringIntDouble = ("hello", 10, 0.001)
xProps.TupleString = ("hello", )
xProps.StdArrayDouble3 = (3.3, 2.2, 1.1)
xProps.StdArrayInt1 = (42, )
xProps.GaudiMapSS = {'a': '1', 'b': '2'}
......
......@@ -21,6 +21,8 @@ from Configurables import Gaudi__Examples__IntToFloatData as IntToFloatData
from Configurables import Gaudi__Examples__IntIntToFloatFloatData as IntIntToFloatFloatData
from Configurables import Gaudi__Examples__IntVectorsToIntVector as IntVectorsToIntVector
from Configurables import Gaudi__Examples__SRangesToIntVector as SRangesToIntVector
from Configurables import Gaudi__Examples__IntVectorsMerger as IntVectorsMerger
from Configurables import Gaudi__Examples__IntVectorsMergingConsumer as IntVectorsMergingConsumer
from Configurables import Gaudi__Examples__ContextConsumer as ContextConsumer
from Configurables import Gaudi__Examples__ContextIntConsumer as ContextIntConsumer
from Configurables import Gaudi__Examples__VectorDoubleProducer as VectorDoubleProducer
......@@ -98,6 +100,18 @@ app.TopAlg = [
str(SDataProducer1.OutputLocation),
str(SDataProducer2.OutputLocation)
]),
IntVectorsMerger(
"IntVectorsMerger",
InputLocations=[
str(VectorDataProducer1.OutputLocation),
str(VectorDataProducer2.OutputLocation)
]),
IntVectorsMergingConsumer(
"IntVectorsMergingConsumer",
InputLocations=[
str(VectorDataProducer1.OutputLocation),
str(VectorDataProducer2.OutputLocation)
]),
]
# - Events
app.EvtMax = 2
......
......@@ -93,8 +93,10 @@ private:
Gaudi::Property<std::vector<int>> m_21{this, "EmptyVector"};
Gaudi::Property<std::tuple<std::string, int, double>> m_22{this, "TupleStringIntDouble"};
Gaudi::Property<std::tuple<std::string>> m_25{this, "TupleString"};
// std::array must be explicitly initialized
Gaudi::Property<std::array<double, 3>> m_23{this, "StdArrayDouble3", {0}};
Gaudi::Property<std::array<int, 1>> m_26{this, "StdArrayInt1", {0}};
Gaudi::Property<GaudiUtils::Map<std::string, std::string>> m_24{this, "GaudiMapSS"};
};
......@@ -188,7 +190,9 @@ StatusCode ExtendedProperties::execute() {
always() << " \t" << m_21 << endmsg;
always() << " \t" << m_22 << endmsg;
always() << " \t" << m_25 << endmsg;
always() << " \t" << m_23 << endmsg;
always() << " \t" << m_26 << endmsg;
always() << " \t" << m_24 << endmsg;
......
......@@ -386,7 +386,47 @@ namespace Gaudi::Examples {
return out;
}
};
DECLARE_COMPONENT( SRangesToIntVector )
struct IntVectorsMerger final
: public Gaudi::Functional::MergingTransformer<
void( const Gaudi::Functional::vector_of_const_<std::vector<int>>& ), BaseClass_t> {
IntVectorsMerger( const std::string& name, ISvcLocator* svcLoc )
: MergingTransformer( name, svcLoc, {"InputLocations", {}} ) {}
void operator()( const Gaudi::Functional::vector_of_const_<std::vector<int>>& intVectors ) const override {
// Create a vector and pre-allocate enough space for the number of integers we have
auto nelements = std::accumulate( intVectors.begin(), intVectors.end(), 0,
[]( const auto a, const auto b ) { return a + b.size(); } );
info() << "sum of input sizes: " << nelements << endmsg;
// Concatenate the input vectors to form the output
for ( const auto& intVector : intVectors ) { info() << "Consuming vector " << intVector << endmsg; }
}
};
DECLARE_COMPONENT( IntVectorsMerger )
struct IntVectorsMergingConsumer final
: public Gaudi::Functional::MergingConsumer<void( Gaudi::Functional::vector_of_const_<std::vector<int>> const& ),
BaseClass_t> {
using Base =
Gaudi::Functional::MergingConsumer<void( Gaudi::Functional::vector_of_const_<std::vector<int>> const& ),
BaseClass_t>;
IntVectorsMergingConsumer( const std::string& name, ISvcLocator* svcLoc )
: Base( name, svcLoc, {"InputLocations", {}} ) {}
void operator()( Gaudi::Functional::vector_of_const_<std::vector<int>> const& intVectors ) const override {
// Create a vector and pre-allocate enough space for the number of integers we have
auto nelements = std::accumulate( intVectors.begin(), intVectors.end(), 0,
[]( const auto a, const auto b ) { return a + b.size(); } );
info() << "sum of input sizes: " << nelements << endmsg;
// Concatenate the input vectors to form the output
for ( const auto& intVector : intVectors ) { info() << "Consuming vector " << intVector << endmsg; }
}
};
DECLARE_COMPONENT( IntVectorsMergingConsumer )
} // namespace Gaudi::Examples
......@@ -70,7 +70,9 @@ def validate(stdout, stderr, result, causes):
'EmptyMap': {},
'EmptyVector': [],
'TupleStringIntDouble': ("hello", 10, 0.001),
'TupleString': ("hello", ),
'StdArrayDouble3': (3.3, 2.2, 1.1),
'StdArrayInt1': (42, ),
'GaudiMapSS': {
'a': '1',
'b': '2'
......
# --> Including file '/home/nnolte/lb-stack-setup/stack2/Gaudi/GaudiExamples/options/FunctionalAlgorithms/ProduceConsume.py'
# setting LC_ALL to "C"
# --> Including file '/home/sponce/dev4/Gaudi/GaudiExamples/options/FunctionalAlgorithms/ProduceConsume.py'
---
# List of input and output types by class
"Gaudi::Examples::ContextConsumer":
......@@ -42,11 +43,11 @@
"Gaudi::Examples::VectorDoubleProducer":
OutputLocation: "std::vector<double,std::allocator<double> >"
---
# <-- End of file '/home/nnolte/lb-stack-setup/stack2/Gaudi/GaudiExamples/options/FunctionalAlgorithms/ProduceConsume.py'
# <-- End of file '/home/sponce/dev4/Gaudi/GaudiExamples/options/FunctionalAlgorithms/ProduceConsume.py'
ApplicationMgr SUCCESS
====================================================================================================================================
Welcome to ApplicationMgr (GaudiCoreSvc v33r0)
running on lbquantaperf01 on Thu Mar 19 13:47:12 2020
Welcome to ApplicationMgr (GaudiCoreSvc v35r2)
running on lblhcbpr11.cern.ch on Thu Apr 15 10:03:11 2021
====================================================================================================================================
ApplicationMgr INFO Application Manager Configured successfully
EventLoopMgr WARNING Unable to locate service "EventSelector"
......@@ -102,6 +103,12 @@ SDataProducer2 INFO storing KeyedContainer of size 10 into /Event/S2
SRangesToIntVector INFO Concatening range of size 3
SRangesToIntVector INFO Concatening range of size 10
SRangesToIntVector INFO Storing output vector [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] to /Event/MyConcatenatedIntFromSVector
IntVectorsMerger INFO sum of input sizes: 8
IntVectorsMerger INFO Consuming vector [3, 3, 3, 3]
IntVectorsMerger INFO Consuming vector [3, 3, 3, 3]
IntVectorsMergi... INFO sum of input sizes: 8
IntVectorsMergi... INFO Consuming vector [3, 3, 3, 3]
IntVectorsMergi... INFO Consuming vector [3, 3, 3, 3]
IntDataProducer INFO executing IntDataProducer, storing 7 into /Event/MyInt
OtherIntDataPro... INFO executing IntDataProducer, storing 7 into /Event/MyOtherInt
IntDataConsumer INFO executing IntDataConsumer, consuming 7 from /Event/MyInt
......@@ -147,6 +154,12 @@ SDataProducer2 INFO storing KeyedContainer of size 10 into /Event/S2
SRangesToIntVector INFO Concatening range of size 3
SRangesToIntVector INFO Concatening range of size 10
SRangesToIntVector INFO Storing output vector [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] to /Event/MyConcatenatedIntFromSVector
IntVectorsMerger INFO sum of input sizes: 8
IntVectorsMerger INFO Consuming vector [3, 3, 3, 3]
IntVectorsMerger INFO Consuming vector [3, 3, 3, 3]
IntVectorsMergi... INFO sum of input sizes: 8
IntVectorsMergi... INFO Consuming vector [3, 3, 3, 3]
IntVectorsMergi... INFO Consuming vector [3, 3, 3, 3]
CountingConsumer INFO Number of counters : 3
| Counter | # | sum | mean/eff^* | rms/err^* | min | max |
| "This is not a warning..." | 4 |
......
......@@ -19,9 +19,9 @@ from Configurables import (HiveWhiteBoard, HiveSlimEventLoopMgr,
from GaudiHive import precedence
# metaconfig
evtslots = 1
evtMax = 1
algosInFlight = 1
evtslots = 2
evtMax = 4
algosInFlight = 2
enableTimeline = True
InertMessageSvc(OutputLevel=INFO)
......@@ -44,15 +44,15 @@ scheduler = AvalancheSchedulerSvc(
ThreadPoolSize=algosInFlight, OutputLevel=DEBUG)
timeValue = precedence.RealTimeValue(
path="atlas/mcreco/averageTiming.mcreco.TriggerOff.json", defaultTime=0.0)
path="atlas/q431/time.r2a.json", defaultTime=0.1)
ifIObound = precedence.UniformBooleanValue(False)
sequencer = precedence.CruncherSequence(
timeValue,
ifIObound,
sleepFraction=0.0,
cfgPath="atlas/mcreco/cf.mcreco.TriggerOff.graphml",
dfgPath="atlas/mcreco/df.mcreco.TriggerOff.3rdEvent.graphml",
cfgPath="atlas/q431/cf.r2a.graphml",
dfgPath="atlas/q431/df.r2a.graphml",
topSequencer='AthSequencer/AthMasterSeq',
timeline=enableTimeline).get()
......
......@@ -20,6 +20,7 @@ from GaudiHive import precedence
evtslots = 1
evtMax = 1
algosInFlight = 4
threads = 4
InertMessageSvc(OutputLevel=INFO)
......@@ -29,8 +30,7 @@ whiteboard = HiveWhiteBoard(
slimeventloopmgr = HiveSlimEventLoopMgr(
SchedulerName="AvalancheSchedulerSvc", OutputLevel=DEBUG)
scheduler = AvalancheSchedulerSvc(
ThreadPoolSize=algosInFlight, OutputLevel=DEBUG)
scheduler = AvalancheSchedulerSvc(ThreadPoolSize=threads, OutputLevel=DEBUG)
AlgResourcePool(OutputLevel=DEBUG)
......@@ -47,7 +47,8 @@ sequencer = precedence.CruncherSequence(
sleepFraction=0.0,
cfgPath="atlas/mcreco/cf.mcreco.TriggerOff.graphml",
dfgPath="atlas/mcreco/df.mcreco.TriggerOff.3rdEvent.graphml",
topSequencer='AthSequencer/AthMasterSeq').get()
topSequencer='AthSequencer/AthMasterSeq',
cardinality=algosInFlight).get()
ApplicationMgr(
EvtMax=evtMax,
......
#!/usr/bin/env gaudirun.py
#####################################################################################
# (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations #
# #
# This software is distributed under the terms of the Apache version 2 licence, #
# copied verbatim in the file "LICENSE". #
# #
# In applying this licence, CERN does not waive the privileges and immunities #
# granted to it by virtue of its status as an Intergovernmental Organization #
# or submit itself to any jurisdiction. #
#####################################################################################
"""
A test for a single algorithm with internal multithreading
"""
from Gaudi.Configuration import *
from Configurables import (HiveWhiteBoard, HiveSlimEventLoopMgr, CPUCrunchSvc,
AvalancheSchedulerSvc, AlgResourcePool, CPUCruncher)
evtslots = 1
evtMax = 1
cardinality = 1
threads = 5 # Threading within alg is still limited by total thread pool
whiteboard = HiveWhiteBoard("EventDataSvc", EventSlots=evtslots)
slimeventloopmgr = HiveSlimEventLoopMgr(
SchedulerName="AvalancheSchedulerSvc", OutputLevel=DEBUG)
scheduler = AvalancheSchedulerSvc(ThreadPoolSize=threads, OutputLevel=VERBOSE)
AlgResourcePool(OutputLevel=DEBUG)
CPUCrunchSvc(shortCalib=True)
# Set up of CPU crunchers -------------------------------------------------------
a1 = CPUCruncher("A1")
a1.Cardinality = cardinality
a1.avgRuntime = 5.0
a1.NParallel = 5
a1.OutputLevel = DEBUG
# Application Manager ----------------------------------------------------------
ApplicationMgr(
EvtMax=evtMax,
EvtSel='NONE',
ExtSvc=[whiteboard],
EventLoop=slimeventloopmgr,
TopAlg=[a1],
MessageSvcType="InertMessageSvc",
OutputLevel=INFO)
......@@ -174,7 +174,8 @@ class CruncherSequence(object):
topSequencer,
showStat=False,
timeline=False,
outputLevel=INFO):
outputLevel=INFO,
cardinality=1):
"""
Keyword arguments:
timeValue -- timeValue object to set algorithm execution time
......@@ -184,6 +185,7 @@ class CruncherSequence(object):
showStat -- print out statistics on precedence graph
"""
self.cardinality = cardinality
self.timeValue = timeValue
self.BlockingBoolValue = BlockingBoolValue
self.sleepFraction = sleepFraction
......@@ -311,6 +313,7 @@ class CruncherSequence(object):
algo_daughter = CPUCruncher(
algo_name,
Cardinality=self.cardinality,
OutputLevel=self.outputLevel,
varRuntime=varRuntime,
avgRuntime=avgRuntime,
......
......@@ -15,6 +15,8 @@
#include <sys/resource.h>
#include <sys/times.h>
#include <tbb/blocked_range.h>
#include <tbb/parallel_for.h>
#include <tbb/tick_count.h>
#include <thread>
......@@ -198,7 +200,14 @@ StatusCode CPUCruncher::execute() // the execution of the algorithm
if ( obj == nullptr ) error() << "A read object was a null pointer." << endmsg;
}
m_crunchSvc->crunch_for( std::chrono::milliseconds( crunchtime_ms ) );
if ( m_nParallel > 1 ) {
tbb::parallel_for( tbb::blocked_range<size_t>( 0, m_nParallel ), [&]( tbb::blocked_range<size_t> r ) {
m_crunchSvc->crunch_for( std::chrono::milliseconds( crunchtime_ms ) );
debug() << "CPUCrunch complete in TBB parallel for block " << r.begin() << " to " << r.end() << endmsg;
} );
} else {
m_crunchSvc->crunch_for( std::chrono::milliseconds( crunchtime_ms ) );
}
// Return error on fraction of events if configured
if ( m_failNEvents > 0 && context.evt() > 0 && ( context.evt() % m_failNEvents ) == 0 ) {
......