From 47085c0cefdabfc94d7c2b6f167e2064356b198e Mon Sep 17 00:00:00 2001 From: Markus Frank <Markus.Frank@cern.ch> Date: Mon, 17 Oct 2022 18:43:56 +0200 Subject: [PATCH] Improve parallelization. No event dependent variables in actors --- DDDigi/CMakeLists.txt | 4 +- DDDigi/include/DDDigi/DigiData.h | 40 +++-- DDDigi/include/DDDigi/DigiKernel.h | 41 ++--- .../DDDigi/DigiMultiContainerProcessor.h | 70 ++------ DDDigi/include/DDDigi/DigiParallelWorker.h | 81 ++++++++++ DDDigi/include/DDDigi/DigiSegmentAction.h | 24 +-- ...tationSplitter.h => DigiSegmentSplitter.h} | 63 +++++--- DDDigi/include/DDDigi/DigiSynchronize.h | 16 +- DDDigi/plugins/Components.cpp | 4 +- DDDigi/plugins/DigiSegmentDepositPrint.cpp | 10 +- DDDigi/python/dddigi.py | 1 + DDDigi/src/DigiData.cpp | 18 +++ DDDigi/src/DigiHandle.cpp | 2 +- DDDigi/src/DigiKernel.cpp | 30 ++-- DDDigi/src/DigiMultiContainerProcessor.cpp | 52 +++--- DDDigi/src/DigiSegmentAction.cpp | 37 +++++ DDDigi/src/DigiSegmentSplitter.cpp | 138 ++++++++++++++++ DDDigi/src/DigiSegmentationSplitter.cpp | 149 ------------------ DDDigi/src/DigiSynchronize.cpp | 26 ++- examples/DDDigi/scripts/DigiTest.py | 16 +- .../scripts/TestMultiContainerParallel.py | 19 +-- .../DDDigi/scripts/TestSegmentationSplit.py | 10 +- 22 files changed, 473 insertions(+), 378 deletions(-) create mode 100644 DDDigi/include/DDDigi/DigiParallelWorker.h rename DDDigi/include/DDDigi/{DigiSegmentationSplitter.h => DigiSegmentSplitter.h} (57%) create mode 100644 DDDigi/src/DigiSegmentAction.cpp create mode 100644 DDDigi/src/DigiSegmentSplitter.cpp delete mode 100644 DDDigi/src/DigiSegmentationSplitter.cpp diff --git a/DDDigi/CMakeLists.txt b/DDDigi/CMakeLists.txt index 8026b13af..e7a4e3803 100644 --- a/DDDigi/CMakeLists.txt +++ b/DDDigi/CMakeLists.txt @@ -51,13 +51,13 @@ if (DD4HEP_USE_GEANT4) dd4hep_add_dictionary(G__DDDigi_DDG4_IO SOURCES ../DDCore/include/ROOT/Warnings.h ddg4/IO.cpp LINKDEF ../DDCore/include/ROOT/LinkDef.h - USES DD4hep::DDG4 + USES DD4hep::DDG4 DD4hep::DDCore ) dd4hep_add_plugin(DDDigi_DDG4_IO SOURCES ddg4/*.cpp GENERATED G__DDDigi_DDG4_IO.cxx - USES DD4hep::DDDigi + USES DD4hep::DDDigi DD4hep::DDG4 DD4hep::DDCore ) else() dd4hep_print( "|++> Geant4 not used. DDDigi will not be able to read DDG4 output.") diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h index 72d63000f..55d30ca12 100644 --- a/DDDigi/include/DDDigi/DigiData.h +++ b/DDDigi/include/DDDigi/DigiData.h @@ -84,37 +84,47 @@ namespace dd4hep { /// Operator greator bool operator > (const Key&) const; + /// Generate key using hash algorithm + void set(const std::string& name, int mask); + /// Conversion to uint64 key_type toLong() const { return key; } - /// Project the mask part of the key - itemkey_type item() { - return this->values.item; - } + /// Project the item part of the key mask_type mask() { return this->values.mask; } - /// Generate key using hash algorithm - void set(const std::string& name, int mask); - - /// Project the mask part of the key - static itemkey_type item(key_type k) { - return Key(k).values.item; + /// Set key mask + void set_mask(Key k) { + this->values.mask = k.values.mask; + } + /// Set key mask + void set_mask(mask_type m) { + this->values.mask = m; } /// Project the item part of the key static mask_type mask(key_type k) { return Key(k).values.mask; } - /// Project the mask part of the key - static itemkey_type item(Key k) { - return k.values.item; - } /// Project the item part of the key static mask_type mask(Key k) { return k.values.mask; } + + /// Project the mask part of the key + itemkey_type item() { + return this->values.item; + } + /// Project the mask part of the key + static itemkey_type item(key_type k) { + return Key(k).values.item; + } + /// Project the mask part of the key + static itemkey_type item(Key k) { + return k.values.item; + } /// Access key name (if registered properly) static std::string key_name(const Key& key); }; @@ -350,6 +360,8 @@ namespace dd4hep { DepositMapping& operator=(const DepositMapping& copy) = default; /// Merge new deposit map onto existing map (not thread safe!) std::size_t merge(DepositMapping&& updates); + /// Merge new deposit map onto existing map (not thread safe!) + std::size_t merge(DepositVector&& updates); }; /// Initializing constructor diff --git a/DDDigi/include/DDDigi/DigiKernel.h b/DDDigi/include/DDDigi/DigiKernel.h index 0bd549d99..6cc5b9129 100644 --- a/DDDigi/include/DDDigi/DigiKernel.h +++ b/DDDigi/include/DDDigi/DigiKernel.h @@ -27,6 +27,7 @@ namespace dd4hep { namespace digi { /// Forward declarations + class DigiAction; class DigiActionSequence; /// Class, which allows all DigiAction derivatives to access the DDG4 kernel structures. @@ -42,24 +43,22 @@ namespace dd4hep { typedef std::map<std::string,int> ClientOutputLevels; typedef std::pair<void*, const std::type_info*> UserFramework; - class CallWrapper { + class ParallelCall { public: - CallWrapper* worker { nullptr }; - public: - CallWrapper(CallWrapper* worker); - CallWrapper() = default; - CallWrapper(CallWrapper&& copy) = default; - CallWrapper(const CallWrapper& copy) = default; - CallWrapper& operator=(CallWrapper&& copy) = delete; - CallWrapper& operator=(const CallWrapper& copy) = delete; - virtual ~CallWrapper() = default; - virtual void operator()() const; + ParallelCall(ParallelCall* p, void* a); + ParallelCall() = default; + ParallelCall(ParallelCall&& copy) = default; + ParallelCall(const ParallelCall& copy) = default; + ParallelCall& operator=(ParallelCall&& copy) = default; + ParallelCall& operator=(const ParallelCall& copy) = default; + virtual ~ParallelCall() = default; + virtual void execute(void* args) const = 0; }; private: class Internals; class Processor; - class Wrapper; + template <typename ACTION, typename ARGUMENT> class Wrapper; /// Internal only data structures; Internals* internals { nullptr }; @@ -164,29 +163,19 @@ namespace dd4hep { DigiActionSequence& outputAction() const; /// Submit a bunch of actions to be executed in parallel - virtual void submit (const std::vector<CallWrapper*>& algorithms) const; + virtual void submit (const std::vector<ParallelCall*>& algorithms, void* data) const; /// Submit a bunch of actions to be executed serially - virtual void execute(const std::vector<CallWrapper*>& algorithms) const; - + virtual void execute(const std::vector<ParallelCall*>& algorithms, void* data) const; +#if 0 /// Submit a bunch of actions to be executed in parallel virtual void submit (const DigiAction::Actors<DigiEventAction>& algorithms, DigiContext& context) const; /// Submit a bunch of actions to be executed serially virtual void execute(const DigiAction::Actors<DigiEventAction>& algorithms, DigiContext& context) const; +#endif /// If running multithreaded: wait until the thread-group finished execution virtual void wait(DigiContext& context) const; }; - - inline DigiKernel::CallWrapper::CallWrapper(CallWrapper* w) - : worker(w) - { - } - - inline void DigiKernel::CallWrapper::operator()() const { - if ( this->worker ) { - (*this->worker)(); - } - } /// Declare property template <typename T> inline DigiKernel& DigiKernel::declareProperty(const std::string& nam, T& val) { diff --git a/DDDigi/include/DDDigi/DigiMultiContainerProcessor.h b/DDDigi/include/DDDigi/DigiMultiContainerProcessor.h index 1b0c7c0ed..4784853e5 100644 --- a/DDDigi/include/DDDigi/DigiMultiContainerProcessor.h +++ b/DDDigi/include/DDDigi/DigiMultiContainerProcessor.h @@ -15,8 +15,8 @@ // Framework include files #include <DDDigi/DigiData.h> -#include <DDDigi/DigiKernel.h> -#include <DDDigi/DigiActionSequence.h> +#include <DDDigi/DigiEventAction.h> +#include <DDDigi/DigiParallelWorker.h> /// C/C++ include files #include <set> @@ -27,47 +27,6 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { - /// Wrapper class to submit bulk actions - /** - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_SIMULATION - */ - template <typename ACTION_TYPE, typename OPTIONS> - class DigiParallelWorker : public DigiKernel::CallWrapper { - ACTION_TYPE* processor { nullptr }; - public: - OPTIONS options; - - public: - DigiParallelWorker(ACTION_TYPE* p, const OPTIONS& opts); - DigiParallelWorker() = default; - DigiParallelWorker(DigiParallelWorker&& copy) = default; - DigiParallelWorker(const DigiParallelWorker& copy) = delete; - DigiParallelWorker& operator=(DigiParallelWorker&& copy) = delete; - DigiParallelWorker& operator=(const DigiParallelWorker& copy) = delete; - virtual ~DigiParallelWorker(); - const char* name() const { return processor->name().c_str(); } - virtual void operator()() const override final; - }; - - template <typename ACTION_TYPE, typename OPTIONS> - DigiParallelWorker<ACTION_TYPE, OPTIONS>::DigiParallelWorker(ACTION_TYPE* p, const OPTIONS& opts) - : processor(p), options(opts) - { - processor->addRef(); - } - - template <typename ACTION_TYPE, typename OPTIONS> - DigiParallelWorker<ACTION_TYPE, OPTIONS>::~DigiParallelWorker() { - if ( processor ) { - processor->release(); - processor = nullptr; - } - } - - /// Worker base class to analyse containers from the input segment in parallel class DigiContainerProcessor : public DigiAction { @@ -76,20 +35,21 @@ namespace dd4hep { public: /// Property: Input data segment name - std::string m_input_segment { "inputs" }; + std::string m_input_segment { "inputs" }; /// Property: event masks to be handled - std::vector<int> m_input_masks { }; + std::vector<int> m_input_masks { }; /// Item keys required by this worker - std::vector<Key> m_work_keys; + std::vector<Key> m_container_keys { }; public: /// Standard constructor DigiContainerProcessor(const DigiKernel& kernel, const std::string& name); /// Main functional callback if specific work is known virtual void execute(DigiContext& context, WorkItems& work) const; + /// Check if the work item is for us + bool use_container(Key key) const; }; - /// Sequencer class to analyse containers from the input segment in parallel /** * @@ -100,26 +60,22 @@ namespace dd4hep { class DigiMultiContainerProcessor : public DigiEventAction { public: using WorkItems = DigiContainerProcessor::WorkItems; - struct ProcessorOptions { - DigiContext* context { nullptr }; - WorkItems* work { nullptr }; - std::vector<Key> keys { }; + struct CallData { + DigiContext& context; + WorkItems& work; }; - using Worker = DigiParallelWorker<DigiContainerProcessor,ProcessorOptions>; - using Workers = std::vector<std::unique_ptr<Worker> >; - using Callers = std::vector<DigiKernel::CallWrapper*>; + using Worker = DigiParallelWorker<DigiContainerProcessor,CallData,int>; + using Workers = std::vector<DigiKernel::ParallelCall*>; protected: /// Property: Input data segment name std::string m_input_segment { "inputs" }; /// Property: event masks to be handled std::vector<int> m_input_masks { }; - /// Property: Allow for multiple workers accessing same container - bool m_allow_duplicates { true }; std::set<Key> m_work_items; + /// Array of sub-workers Workers m_workers; - Callers m_callers; protected: /// Define standard assignments and constructors diff --git a/DDDigi/include/DDDigi/DigiParallelWorker.h b/DDDigi/include/DDDigi/DigiParallelWorker.h new file mode 100644 index 000000000..5319335be --- /dev/null +++ b/DDDigi/include/DDDigi/DigiParallelWorker.h @@ -0,0 +1,81 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +#ifndef DDDIGI_DIGIPARALLELWORKER_H +#define DDDIGI_DIGIPARALLELWORKER_H + +/// Framework include files +#include <DDDigi/DigiKernel.h> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Wrapper class to submit bulk actions + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + template <typename ACTION_TYPE, typename CALLDATA, typename OPTIONS> + class DigiParallelWorker : public DigiKernel::ParallelCall { + public: + using action_t = ACTION_TYPE; + using options_t = OPTIONS; + using calldata_t = CALLDATA; + + action_t* action; + options_t options; + + public: + /// Initializing constructor + DigiParallelWorker(ACTION_TYPE* p, const OPTIONS& opts); + /// Default constructor + DigiParallelWorker() = delete; + /// Move constructor + DigiParallelWorker(DigiParallelWorker&& copy) = default; + /// Inhibit copy constructor + DigiParallelWorker(const DigiParallelWorker& copy) = default; + /// Inhibit move assignment + DigiParallelWorker& operator=(DigiParallelWorker&& copy) = delete; + /// Inhibit copy assignment + DigiParallelWorker& operator=(const DigiParallelWorker& copy) = delete; + /// Default destructor + virtual ~DigiParallelWorker(); + /// Access to processor name + const char* name() const { return action->name().c_str(); } + /// Callback on data + virtual void execute(void* data) const override; + }; + + /// Initializing constructor + template <typename ACTION_TYPE, typename CALLDATA, typename OPTIONS> + DigiParallelWorker<ACTION_TYPE, CALLDATA, OPTIONS>::DigiParallelWorker(ACTION_TYPE* proc, const OPTIONS& opts) + : ParallelCall(), action(proc), options(opts) + { + action->addRef(); + } + + /// Default destructor + template <typename ACTION_TYPE, typename CALLDATA, typename OPTIONS> + DigiParallelWorker<ACTION_TYPE, CALLDATA, OPTIONS>::~DigiParallelWorker() { + if ( action ) { + action->release(); + action = nullptr; + } + } + } // End namespace digi +} // End namespace dd4hep +#endif // DDDIGI_DIGIPARALLELWORKER_H diff --git a/DDDigi/include/DDDigi/DigiSegmentAction.h b/DDDigi/include/DDDigi/DigiSegmentAction.h index ab265c784..95bf318cf 100644 --- a/DDDigi/include/DDDigi/DigiSegmentAction.h +++ b/DDDigi/include/DDDigi/DigiSegmentAction.h @@ -16,6 +16,7 @@ // Framework include files #include <DDDigi/DigiData.h> #include <DDDigi/DigiEventAction.h> +#include <DDDigi/DigiSegmentationTool.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -26,7 +27,7 @@ namespace dd4hep { /// Forward declarations class DigiSegmentAction; class DigiSegmentContext; - class DigiSegmentationSplitter; + class DigiSegmentSplitter; /// Default base class for all Digitizer actions and derivates thereof. /** @@ -37,19 +38,13 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_SIMULATION */ - class DigiSegmentAction : public DigiEventAction { - private: - friend class DigiSegmentationSplitter; - - /// Implementation declaration -#if defined(G__ROOT) || defined(__CLING__) || defined(__ROOTCLING__) - typedef long internals_t; -#else - class internals_t; -#endif - /// Reference to the implementation - std::unique_ptr<internals_t> internals; + class DigiSegmentAction : virtual public DigiAction { + protected: + friend class DigiSegmentSplitter; + /// Segmentation split context + DigiSegmentContext segment { }; + /// Define standard assignments and constructors DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiSegmentAction); @@ -58,11 +53,8 @@ namespace dd4hep { DigiSegmentAction(const DigiKernel& kernel, const std::string& name); /// Default destructor virtual ~DigiSegmentAction(); - /// Main functional callback - virtual void execute(DigiContext& context) const final; /// Main functional callback. Default implementnation is noop. virtual DepositVector handleSegment(DigiContext& context, - const DigiSegmentContext& segment, const DepositMapping& deposits) const; }; } // End namespace digi diff --git a/DDDigi/include/DDDigi/DigiSegmentationSplitter.h b/DDDigi/include/DDDigi/DigiSegmentSplitter.h similarity index 57% rename from DDDigi/include/DDDigi/DigiSegmentationSplitter.h rename to DDDigi/include/DDDigi/DigiSegmentSplitter.h index f380de57e..54afcd398 100644 --- a/DDDigi/include/DDDigi/DigiSegmentationSplitter.h +++ b/DDDigi/include/DDDigi/DigiSegmentSplitter.h @@ -10,13 +10,14 @@ // Author : M.Frank // //========================================================================== -#ifndef DDDIGI_DIGISEGMENTATIONSPLITTER_H -#define DDDIGI_DIGISEGMENTATIONSPLITTER_H +#ifndef DDDIGI_DIGISEGMENTSPLITTER_H +#define DDDIGI_DIGISEGMENTSPLITTER_H // Framework include files +#include <DDDigi/DigiEventAction.h> #include <DDDigi/DigiSegmentAction.h> -#include <DDDigi/DigiActionSequence.h> #include <DDDigi/DigiSegmentationTool.h> +#include <DDDigi/DigiParallelWorker.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -33,51 +34,73 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_SIMULATION */ - class DigiSegmentationSplitter : public DigiActionSequence { + class DigiSegmentSplitter : public DigiEventAction { + public: + + struct CallData { + DigiContext& context; + DepositMapping& input; + DepositMapping* output; + const DigiSegmentSplitter* parent; + }; + using Worker = DigiParallelWorker<DigiSegmentAction,CallData,int>; + using Workers = std::vector<DigiKernel::ParallelCall*>; + using Splits = std::map<VolumeID, std::pair<DetElement, VolumeID> >; + protected: /// Implementation declaration class internals_t; /// Reference to the implementation std::unique_ptr<internals_t> internals; - /// Property: Identifier of the input repository - std::string m_input_id; /// Property: Split element of the ID descriptor - std::string m_processor_type; + std::string m_processor_type; /// Name of the subdetector to be handed - std::string m_detector_name; + std::string m_detector_name; /// Splitter field in the segmentation description - std::string m_split_by; + std::string m_split_by; /// Property: Flag if processors should be shared - bool m_share_processor { true }; + bool m_share_processor { true }; + + /// Property: Identifier of the input repository + std::string m_input_id; /// Property: Input mask in the repository - int m_input_mask; + int m_input_mask; + /// Property: Identifier of the input repository + std::string m_output_id; + /// Property: Input mask in the repository + int m_output_mask; /// Segmentation too instance - DigiSegmentationTool m_split_tool; + DigiSegmentationTool m_split_tool; /// Segmentation split context - DigiSegmentContext m_split_context; + DigiSegmentContext m_split_context; /// Split elements used to parallelize the processing - std::map<VolumeID, std::pair<DetElement, VolumeID> > m_splits; + Splits m_splits; /// Input data keys: depend on dd4hep::Readout and the input mask(s) - std::vector<Key> m_data_keys; + std::vector<Key> m_data_keys; + + /// Array of sub-workers + Workers m_workers; + + mutable std::mutex m_output_lock; protected: /// Default destructor - virtual ~DigiSegmentationSplitter(); - + virtual ~DigiSegmentSplitter(); /// Initialization function void initialize(); public: /// Standard constructor - DigiSegmentationSplitter(const DigiKernel& kernel, const std::string& name); - + DigiSegmentSplitter(const DigiKernel& kernel, const std::string& name); + /// Handle result from segment callbacks + void register_output(DepositMapping& result, DepositVector&& output) const; /// Main functional callback virtual void execute(DigiContext& context) const; }; } // End namespace digi } // End namespace dd4hep -#endif // DDDIGI_DIGISEGMENTATIONSPLITTER_H +#endif // DDDIGI_DIGISEGMENTSPLITTER_H diff --git a/DDDigi/include/DDDigi/DigiSynchronize.h b/DDDigi/include/DDDigi/DigiSynchronize.h index 9b69a0a05..8b3f4827d 100644 --- a/DDDigi/include/DDDigi/DigiSynchronize.h +++ b/DDDigi/include/DDDigi/DigiSynchronize.h @@ -15,6 +15,7 @@ /// Framework incloude files #include <DDDigi/DigiEventAction.h> +#include <DDDigi/DigiParallelWorker.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -34,7 +35,10 @@ namespace dd4hep { class DigiSynchronize : public DigiEventAction { protected: /// The list of action objects to be called - Actors<DigiEventAction> m_actors; + //Actors<DigiEventAction> m_actors; + using Worker = DigiParallelWorker<DigiEventAction,DigiContext,int>; + using Workers = std::vector<DigiKernel::ParallelCall*>; + Workers m_actors; protected: /// Define standard assignments and constructors @@ -45,21 +49,11 @@ namespace dd4hep { DigiSynchronize(const DigiKernel& kernel, const std::string& nam); /// Default destructor virtual ~DigiSynchronize(); - /// Get an action member by name - DigiEventAction* get(const std::string& name) const; - /// Access the children - const Actors<DigiEventAction>& children() const { - return m_actors; - } /// Adopt a new action as part of the sequence. Sequence takes ownership. virtual void adopt(DigiEventAction* action); /// Begin-of-event callback virtual void execute(DigiContext& context) const override; - /// - void analyze(); }; - } // End namespace digi } // End namespace dd4hep - #endif // DDDIGI_DIGISYNCHRONIZE_H diff --git a/DDDigi/plugins/Components.cpp b/DDDigi/plugins/Components.cpp index 9d998f509..f982f9cfa 100644 --- a/DDDigi/plugins/Components.cpp +++ b/DDDigi/plugins/Components.cpp @@ -53,9 +53,9 @@ DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiHitAttenuatorExp) #include <DDDigi/DigiContainerCombine.h> DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiContainerCombine) -#include <DDDigi/DigiSegmentationSplitter.h> +#include <DDDigi/DigiSegmentSplitter.h> DECLARE_DIGISEGMENTACTION_NS(dd4hep::digi,DigiSegmentAction) -DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiSegmentationSplitter) +DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiSegmentSplitter) #include <DDDigi/DigiMultiContainerProcessor.h> DECLARE_DIGIEVENTACTION_NS(dd4hep::digi,DigiMultiContainerProcessor) diff --git a/DDDigi/plugins/DigiSegmentDepositPrint.cpp b/DDDigi/plugins/DigiSegmentDepositPrint.cpp index c247267e0..9c4d7313b 100644 --- a/DDDigi/plugins/DigiSegmentDepositPrint.cpp +++ b/DDDigi/plugins/DigiSegmentDepositPrint.cpp @@ -13,7 +13,7 @@ // Framework include files #include <DDDigi/DigiContext.h> -#include <DDDigi/DigiSegmentationSplitter.h> +#include <DDDigi/DigiSegmentSplitter.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -28,15 +28,15 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_SIMULATION */ - class DigiSegmentDepositPrint : public DigiSegmentAction { + class DigiSegmentDepositPrint : virtual public DigiSegmentAction { public: - /// Constructors used of base class - using DigiSegmentAction::DigiSegmentAction; + /// Standard constructor + DigiSegmentDepositPrint(const DigiKernel& kernel, const std::string& nam) + : DigiAction(kernel, nam), DigiSegmentAction(kernel, nam) {} /// Main functional callback virtual DepositVector handleSegment(DigiContext& context, - const DigiSegmentContext& segment, const DepositMapping& deposits) const override final { char format[256]; ::snprintf(format, sizeof(format), diff --git a/DDDigi/python/dddigi.py b/DDDigi/python/dddigi.py index dfd1b041c..e055c4e2a 100644 --- a/DDDigi/python/dddigi.py +++ b/DDDigi/python/dddigi.py @@ -217,6 +217,7 @@ def Synchronize(kernel, nam, parallel=False): def _default_adopt(self, action): getattr(self, '__adopt')(action.get()) + def _setup(obj, call='adopt', py_call=_default_adopt): _import_class('digi', obj) cls = getattr(current, obj) diff --git a/DDDigi/src/DigiData.cpp b/DDDigi/src/DigiData.cpp index 68b7a933f..4c65d7b5d 100644 --- a/DDDigi/src/DigiData.cpp +++ b/DDDigi/src/DigiData.cpp @@ -71,6 +71,24 @@ std::size_t DepositVector::merge(DepositVector&& updates) { return update_size; } +/// Merge new deposit map onto existing map +std::size_t DepositMapping::merge(DepositVector&& updates) { + std::size_t update_size = updates.size(); + for( auto& c : updates ) { + CellID cell = c.first; + EnergyDeposit& depo = c.second; + auto iter = this->find(cell); + if ( iter == this->end() ) { + this->emplace(cell, std::move(depo)); + continue; + } + auto& to_update = iter->second; + to_update.deposit += depo.deposit; + to_update.history.insert(to_update.history.end(), depo.history.begin(), depo.history.end()); + } + return update_size; +} + /// Merge new deposit map onto existing map std::size_t DepositMapping::merge(DepositMapping&& updates) { std::size_t update_size = updates.size(); diff --git a/DDDigi/src/DigiHandle.cpp b/DDDigi/src/DigiHandle.cpp index 45f7e8e1d..25159394c 100644 --- a/DDDigi/src/DigiHandle.cpp +++ b/DDDigi/src/DigiHandle.cpp @@ -20,8 +20,8 @@ #include <DDDigi/DigiKernel.h> #include <DDDigi/DigiInputAction.h> #include <DDDigi/DigiEventAction.h> +#include <DDDigi/DigiSegmentAction.h> #include <DDDigi/DigiSignalProcessor.h> -#include <DDDigi/DigiSegmentationSplitter.h> // C/C++ include files #include <stdexcept> diff --git a/DDDigi/src/DigiKernel.cpp b/DDDigi/src/DigiKernel.cpp index 32c5f044e..979865d50 100644 --- a/DDDigi/src/DigiKernel.cpp +++ b/DDDigi/src/DigiKernel.cpp @@ -100,12 +100,11 @@ public: * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ -class DigiKernel::Wrapper : public CallWrapper { +template<typename ACTION, typename ARG> class DigiKernel::Wrapper { public: - DigiContext& context; - DigiEventAction* action = 0; - Wrapper(DigiContext& c, DigiEventAction* a) - : context(c), action(a) {} + ACTION* action = 0; + ARG context; + Wrapper(ACTION* a, ARG c) : action(a), context(c) {} Wrapper(Wrapper&& copy) = default; Wrapper(const Wrapper& copy) = default; Wrapper& operator=(Wrapper&& copy) = delete; @@ -147,7 +146,6 @@ public: } }; - /// Standard constructor DigiKernel::DigiKernel(Detector& description_ref) : m_detDesc(&description_ref) @@ -318,27 +316,28 @@ DigiActionSequence& DigiKernel::outputAction() const { } /// Submit a bunch of actions to be executed in parallel -void DigiKernel::submit (const std::vector<CallWrapper*>& actions) const { +void DigiKernel::submit (const std::vector<ParallelCall*>& algorithms, void* context) const { #ifdef DD4HEP_USE_TBB bool parallel = 0 != internals->tbbInit && internals->numThreads>0; if ( parallel ) { tbb::task_group que; - for ( auto* algo : actions ) - que.run( *algo ); + for( auto* algo : algorithms ) + que.run( Wrapper<ParallelCall,void*>(algo, context) ); que.wait(); return; } #endif - for ( auto* algo : actions ) - (*algo)(); + for( auto* algo : algorithms ) + algo->execute(context); } /// Submit a bunch of actions to be executed serially -void DigiKernel::execute(const std::vector<CallWrapper*>& actions) const { - for ( auto* algo : actions ) - (*algo)(); +void DigiKernel::execute(const std::vector<ParallelCall*>& algorithms, void* context) const { + for( auto* algo : algorithms ) + algo->execute(context); } +#if 0 void DigiKernel::submit(const DigiAction::Actors<DigiEventAction>& actions, DigiContext& context) const { std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); bool parallel = 0 != internals->tbbInit && internals->numThreads>0; @@ -346,7 +345,7 @@ void DigiKernel::submit(const DigiAction::Actors<DigiEventAction>& actions, Digi if ( parallel ) { tbb::task_group que; for ( auto* i : actions ) - que.run( Wrapper(context, i) ); + que.run( Wrapper<DigiEventAction,DigiContext&>(i, context) ); que.wait(); goto print_stamp; } @@ -364,6 +363,7 @@ void DigiKernel::submit(const DigiAction::Actors<DigiEventAction>& actions, Digi void DigiKernel::execute(const DigiAction::Actors<DigiEventAction>& actions, DigiContext& context) const { actions(&DigiEventAction::execute,context); } +#endif void DigiKernel::wait(DigiContext& context) const { if ( context.event ) {} diff --git a/DDDigi/src/DigiMultiContainerProcessor.cpp b/DDDigi/src/DigiMultiContainerProcessor.cpp index 006802179..36747442b 100644 --- a/DDDigi/src/DigiMultiContainerProcessor.cpp +++ b/DDDigi/src/DigiMultiContainerProcessor.cpp @@ -24,8 +24,11 @@ using namespace dd4hep::digi; -template <> void DigiParallelWorker<DigiContainerProcessor, DigiMultiContainerProcessor::ProcessorOptions>::operator()() const { - processor->execute(*options.context, *options.work); +template <> void DigiParallelWorker<DigiContainerProcessor, + DigiMultiContainerProcessor::CallData, + int>::execute(void* data) const { + calldata_t* args = reinterpret_cast<calldata_t*>(data); + action->execute(args->context, args->work); } /// Standard constructor @@ -34,12 +37,13 @@ DigiMultiContainerProcessor::DigiMultiContainerProcessor(const DigiKernel& krnl, { this->declareProperty("input_masks", m_input_masks); this->declareProperty("input_segment", m_input_segment); - this->declareProperty("allow_duplicates", m_allow_duplicates); InstanceCount::increment(this); } /// Default destructor DigiMultiContainerProcessor::~DigiMultiContainerProcessor() { + for(auto* w : m_workers ) detail::deletePtr(w); + m_workers.clear(); InstanceCount::decrement(this); } @@ -55,23 +59,12 @@ void DigiMultiContainerProcessor::adopt_processor(DigiContainerProcessor* action std::vector<Key> keys; for(const auto& c : containers) { Key key(0x0, c); - if ( !m_allow_duplicates ) { - for(const auto& w : m_workers) { - if ( std::find(m_work_items.begin(), m_work_items.end(), key.item()) != m_work_items.end() ) { - error("+++ Container %s has already a worker action attached: %s", - c.c_str(), w->name()); - except("+++ Need to set property allow_duplicates=True to allow such behavior."); - } - } - } keys.push_back(key); m_work_items.insert(key.item()); str << c << " "; } - action->m_work_keys = keys; - Worker* w = new Worker(action, {nullptr, nullptr, keys}); - m_callers.emplace_back(new DigiKernel::CallWrapper(w)); - m_workers.emplace_back(std::unique_ptr<Worker>(w)); + action->m_container_keys = keys; + m_workers.emplace_back(new Worker(action, 0)); info("+++ Use processor: %-32s for processing: %s", aname, str.str().c_str()); } @@ -94,11 +87,8 @@ void DigiMultiContainerProcessor::execute(DigiContext& context) const { } } if ( !work_items.empty() ) { - for(std::size_t i=0; i < m_workers.size(); ++i) { - m_workers[i]->options.context = &context; - m_workers[i]->options.work = &work_items; - } - m_kernel.submit(m_callers); + CallData data { context, work_items }; + m_kernel.submit(m_workers, &data); } } @@ -110,7 +100,23 @@ DigiContainerProcessor::DigiContainerProcessor(const DigiKernel& kernel, const s this->declareProperty("input_segment", m_input_segment); } +/// Check if the work item is for us +bool DigiContainerProcessor::use_container(Key key) const { + auto key_iter = std::find(m_container_keys.begin(), m_container_keys.end(), Key(key.item())); + if ( m_container_keys.empty() || key_iter != m_container_keys.end() ) { + auto mask_iter = std::find(m_input_masks.begin(), m_input_masks.end(), key.mask()); + return m_input_masks.empty() || mask_iter != m_input_masks.end(); + } + return false; +} + /// Main functional callback if specific work is known -void DigiContainerProcessor::execute(DigiContext& context, WorkItems& data) const { - info("Hello there [Context:%p] %p", (void*)&context, (void*)&data); +void DigiContainerProcessor::execute(DigiContext& context, WorkItems& work) const { + for( const auto& item : work ) { + if ( use_container(item.first) ) { + Key key = item.first; + info("%s+++ %p Using container: %016lX --> %04X %08X %s", + context.event->id(), (void*)this, key.key, key.mask(), key.item(), Key::key_name(key).c_str()); + } + } } diff --git a/DDDigi/src/DigiSegmentAction.cpp b/DDDigi/src/DigiSegmentAction.cpp new file mode 100644 index 000000000..66e1b7230 --- /dev/null +++ b/DDDigi/src/DigiSegmentAction.cpp @@ -0,0 +1,37 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include <DD4hep/InstanceCount.h> +#include <DDDigi/DigiSegmentAction.h> + +using namespace dd4hep::digi; + +/// Standard constructor +DigiSegmentAction::DigiSegmentAction(const DigiKernel& krnl, const std::string& nam) + : DigiAction(krnl, nam) +{ + InstanceCount::increment(this); +} + +/// Default destructor +DigiSegmentAction::~DigiSegmentAction() { + InstanceCount::decrement(this); +} + +/// Main functional callback +DepositVector +DigiSegmentAction::handleSegment(DigiContext& /* context */, + const DepositMapping& /* depos */) const { + return {}; +} diff --git a/DDDigi/src/DigiSegmentSplitter.cpp b/DDDigi/src/DigiSegmentSplitter.cpp new file mode 100644 index 000000000..d6578d6a9 --- /dev/null +++ b/DDDigi/src/DigiSegmentSplitter.cpp @@ -0,0 +1,138 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include <DD4hep/Plugins.h> +#include <DD4hep/InstanceCount.h> + +#include <DDDigi/DigiKernel.h> +#include <DDDigi/DigiContext.h> +#include <DDDigi/DigiSegmentSplitter.h> + +using namespace dd4hep::digi; + +class DigiSegmentSplitter::internals_t { +public: + /// Reference to master + DigiSegmentSplitter* split { nullptr }; + /// Flag to check the initialization + bool inited { false }; + /// Default constructor + internals_t(DigiSegmentSplitter* s) : split(s) {} + /// Initializing function: compute values which depend on properties + void initialize(DigiContext& context) { + if ( !this->inited ) { + std::lock_guard<std::mutex> lock(context.initializer_lock()); + if ( !this->inited ) { + this->split->initialize(); + this->inited = true; + } + } + } +}; + +template <> void DigiParallelWorker<DigiSegmentAction, + DigiSegmentSplitter::CallData, + int>::execute(void* data) const { + calldata_t* args = reinterpret_cast<calldata_t*>(data); + auto res = action->handleSegment(args->context, args->input); + if ( args->output && !res.empty() ) { + args->parent->register_output(*args->output, std::move(res)); + } +} + +/// Standard constructor +DigiSegmentSplitter::DigiSegmentSplitter(const DigiKernel& kernel, const std::string& nam) + : DigiEventAction(kernel, nam), + m_split_tool(kernel.detectorDescription()) +{ + this->internals = std::make_unique<internals_t>(this); + declareProperty("detector", m_detector_name); + declareProperty("split_by", m_split_by); + declareProperty("processor_type", m_processor_type); + declareProperty("share_processor", m_share_processor = false); + + declareProperty("input_segment", m_input_id = "deposits"); + declareProperty("input_mask", m_input_mask); + declareProperty("output_segment", m_output_id); + declareProperty("output_mask", m_output_mask); + InstanceCount::increment(this); +} + +/// Default destructor +DigiSegmentSplitter::~DigiSegmentSplitter() { + for(auto* w : m_workers ) detail::deletePtr(w); + m_workers.clear(); + InstanceCount::decrement(this); +} + + +/// Initialization function +void DigiSegmentSplitter::initialize() { + char text[256]; + std::size_t count = 0; + + m_split_tool.set_detector(m_detector_name); + m_split_context = m_split_tool.split_context(m_split_by); + m_data_keys = m_split_tool.collection_keys(m_input_mask); + m_splits = m_split_tool.split_segmentation(m_split_by); + + /// Create the processors: + for( auto& p : m_splits ) { + ::snprintf(text, sizeof(text), "_%05X", m_split_context.split_id(p.first)); + std::string nam = this->name() + text; + auto* proc = PluginService::Create<DigiSegmentAction*>(m_processor_type, &m_kernel, nam); + if ( !proc ) { + except("+++ Failed to create split worker: %s/%s", m_processor_type.c_str(), nam.c_str()); + } + proc->segment = m_split_context; + proc->segment.detector = p.second.first; + proc->segment.id = p.second.second; + m_workers.emplace_back(new Worker(proc, 0)); + ++count; + } + info("+++ Detector splitter is now fully initialized!"); +} + +/// Main functional callback +void DigiSegmentSplitter::execute(DigiContext& context) const { + auto& input = context.event->get_segment(m_input_id); + this->internals->initialize(context); + for( auto k : m_data_keys ) { + auto* hits = input.pointer<DepositMapping>(k); + if ( hits ) { + /// prepare processors for execution + info("+++ Got hit collection %04X %08X. Prepare processors.", Key::mask(k), Key::item(k)); + /// Now submit them + if ( m_output_id.empty() ) { + CallData data { context, *hits, nullptr, this }; + m_kernel.submit(m_workers, &data); + } + else { + DepositMapping result (m_name+"."+hits->name, m_output_mask); + CallData data { context, *hits, &result, this }; + m_kernel.submit(m_workers, &data); + auto& output = context.event->get_segment(m_output_id); + output.emplace(result.key, std::move(result)); + } + } + } +} + +/// Handle result from segment callbacks +void DigiSegmentSplitter::register_output(DepositMapping& result, + DepositVector&& output) const { + std::lock_guard<std::mutex> lock(m_output_lock); + result.merge(std::move(output)); +} + diff --git a/DDDigi/src/DigiSegmentationSplitter.cpp b/DDDigi/src/DigiSegmentationSplitter.cpp deleted file mode 100644 index 28d860af7..000000000 --- a/DDDigi/src/DigiSegmentationSplitter.cpp +++ /dev/null @@ -1,149 +0,0 @@ -//========================================================================== -// AIDA Detector description implementation -//-------------------------------------------------------------------------- -// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) -// All rights reserved. -// -// For the licensing terms see $DD4hepINSTALL/LICENSE. -// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. -// -// Author : M.Frank -// -//========================================================================== - -// Framework include files -#include <DD4hep/Plugins.h> -#include <DD4hep/InstanceCount.h> - -#include <DDDigi/DigiKernel.h> -#include <DDDigi/DigiContext.h> -#include <DDDigi/DigiSegmentationSplitter.h> - -using namespace dd4hep::digi; - -class DigiSegmentAction::internals_t { -public: - DigiSegmentContext split { }; - DepositVector output { }; - const DepositMapping* input { nullptr }; -}; - -class DigiSegmentationSplitter::internals_t { -public: - /// Reference to master - DigiSegmentationSplitter* split { nullptr }; - /// Flag to check the initialization - bool inited { false }; - /// Default constructor - internals_t(DigiSegmentationSplitter* s) : split(s) {} - /// Initializing function: compute values which depend on properties - void initialize(DigiContext& context) { - if ( !this->inited ) { - std::lock_guard<std::mutex> lock(context.initializer_lock()); - if ( !this->inited ) { - this->split->initialize(); - this->inited = true; - } - } - } -}; - -/// Standard constructor -DigiSegmentationSplitter::DigiSegmentationSplitter(const DigiKernel& kernel, const std::string& nam) - : DigiActionSequence(kernel, nam), - m_split_tool(kernel.detectorDescription()) -{ - this->internals = std::make_unique<internals_t>(this); - declareProperty("detector", this->m_detector_name); - declareProperty("split_by", this->m_split_by); - declareProperty("input", this->m_input_id = "deposits"); - declareProperty("mask", this->m_input_mask); - declareProperty("processor_type", this->m_processor_type); - declareProperty("share_processor", this->m_share_processor = false); - InstanceCount::increment(this); -} - -/// Default destructor -DigiSegmentationSplitter::~DigiSegmentationSplitter() { - InstanceCount::decrement(this); -} - - -/// Initialization function -void DigiSegmentationSplitter::initialize() { - char text[256]; - std::size_t count = 0; - - this->m_split_tool.set_detector(this->m_detector_name); - this->m_split_context = this->m_split_tool.split_context(this->m_split_by); - this->m_data_keys = this->m_split_tool.collection_keys(this->m_input_mask); - this->m_splits = this->m_split_tool.split_segmentation(this->m_split_by); - - /// Create the processors: - for( auto& p : this->m_splits ) { - ::snprintf(text, sizeof(text), "_%05X", m_split_context.split_id(p.first)); - std::string nam = this->name() + text; - auto* eproc = PluginService::Create<DigiEventAction*>(m_processor_type, &m_kernel, nam); - if ( !eproc ) { - except("+++ Failed to create split worker: %s/%s", m_processor_type.c_str(), nam.c_str()); - } - auto* proc = dynamic_cast<DigiSegmentAction*>(eproc); - if ( !proc ) { - except("+++ Split worker: %s/%s is not of type DigiSegmentAction!", - m_processor_type.c_str(), nam.c_str()); - } - proc->internals = std::make_unique<DigiSegmentAction::internals_t>(); - proc->internals->split = this->m_split_context; - proc->internals->split.detector = p.second.first; - proc->internals->split.id = p.second.second; - this->DigiActionSequence::adopt(proc); - ++count; - } - info("+++ Detector splitter is now fully initialized!"); -} - -/// Main functional callback -void DigiSegmentationSplitter::execute(DigiContext& context) const { - auto& input = context.event->get_segment(this->m_input_id); - this->internals->initialize(context); - for( auto k : this->m_data_keys ) { - auto* hits = input.pointer<DepositMapping>(k); - if ( hits ) { - /// prepare processors for execution - info("+++ Got hit collection %04X %08X. Prepare processors.", - Key::mask(k), Key::item(k)); - for ( auto* a : this->m_actors ) { - auto* proc = (DigiSegmentAction*)a; - proc->internals->input = hits; - } - /// Now submit them - this->DigiActionSequence::execute(context); - } - } -} - -/// Standard constructor -DigiSegmentAction::DigiSegmentAction(const DigiKernel& krnl, const std::string& nam) - : DigiEventAction(krnl, nam) -{ - this->internals = std::make_unique<internals_t>(); - InstanceCount::increment(this); -} - -/// Default destructor -DigiSegmentAction::~DigiSegmentAction() { - InstanceCount::decrement(this); -} - -void DigiSegmentAction::execute(DigiContext& context) const { - auto& imp = *this->internals; - imp.output = this->handleSegment(context, imp.split, *imp.input); -} - -/// Main functional callback -DepositVector -DigiSegmentAction::handleSegment(DigiContext& /* context */, - const DigiSegmentContext& /* segment */, - const DepositMapping& /* depos */) const { - return {}; -} diff --git a/DDDigi/src/DigiSynchronize.cpp b/DDDigi/src/DigiSynchronize.cpp index 8f5a54fd6..bf01a5283 100644 --- a/DDDigi/src/DigiSynchronize.cpp +++ b/DDDigi/src/DigiSynchronize.cpp @@ -23,6 +23,13 @@ using namespace std; using namespace dd4hep::digi; + +template <> void +DigiParallelWorker<DigiEventAction, DigiContext, int>::execute(void* data) const { + calldata_t* args = reinterpret_cast<calldata_t*>(data); + action->execute(*args); +} + /// Standard constructor DigiSynchronize::DigiSynchronize(const DigiKernel& kernel, const string& nam) : DigiEventAction(kernel, nam) @@ -32,23 +39,18 @@ DigiSynchronize::DigiSynchronize(const DigiKernel& kernel, const string& nam) /// Default destructor DigiSynchronize::~DigiSynchronize() { - m_actors(&DigiEventAction::release); + for(auto* w : m_actors ) detail::deletePtr(w); m_actors.clear(); InstanceCount::decrement(this); } -/// Get an action sequence member by name -DigiEventAction* DigiSynchronize::get(const string& nam) const { - return m_actors.get(FindByName(TypeName::split(nam).second)); -} - /// Pre-track action callback void DigiSynchronize::execute(DigiContext& context) const { auto start = chrono::high_resolution_clock::now(); if ( m_parallel ) - m_kernel.submit(m_actors, context); + m_kernel.submit(m_actors, &context); else - m_kernel.execute(m_actors, context); + m_kernel.execute(m_actors, &context); chrono::duration<double> secs = chrono::high_resolution_clock::now() - start; debug("+++ Event: %8d (DigiSynchronize) Parallel: %-4s %3ld actions [%8.3g sec]", context.event->eventNumber, yes_no(m_parallel), m_actors.size(), @@ -58,14 +60,8 @@ void DigiSynchronize::execute(DigiContext& context) const { /// Add an actor responding to all callbacks. Sequence takes ownership. void DigiSynchronize::adopt(DigiEventAction* action) { if (action) { - action->addRef(); - m_actors.add(action); + m_actors.emplace_back(new Worker(action, 0)); return; } except("DigiSynchronize","++ Attempt to add invalid actor!"); } - -/// Add an actor responding to all callbacks. Sequence takes ownership. -void DigiSynchronize::analyze() { - info("+++ Analyzing the algorithm sequence. Parallel: %s",yes_no(m_parallel)); -} diff --git a/examples/DDDigi/scripts/DigiTest.py b/examples/DDDigi/scripts/DigiTest.py index f47175518..371608fda 100644 --- a/examples/DDDigi/scripts/DigiTest.py +++ b/examples/DDDigi/scripts/DigiTest.py @@ -83,17 +83,15 @@ class Test(dddigi.Digitize): return list(self.attenuation.keys()) def containers(self, count): - keys = list(self.attenuation.keys()) conts = [] result = [] - cnt = 0 - for i in range(count): - if cnt > count: - result.append(cont) - cont = [] - cnt = 0 - cont.append(keys[i]) - cnt = cnt + 1 + for key in list(self.attenuation.keys()): + conts.append(key) + if len(conts) == count: + result.append(conts) + conts = [] + if len(conts) > 0: + result.append(conts) return result def check_creation(self, objs): diff --git a/examples/DDDigi/scripts/TestMultiContainerParallel.py b/examples/DDDigi/scripts/TestMultiContainerParallel.py index c491555b0..33ded1c59 100644 --- a/examples/DDDigi/scripts/TestMultiContainerParallel.py +++ b/examples/DDDigi/scripts/TestMultiContainerParallel.py @@ -11,29 +11,30 @@ from __future__ import absolute_import import dddigi + def run(): import DigiTest digi = DigiTest.Test(geometry=None) - #digi.load_geo() + # digi.load_geo() input = digi.input_action('DigiParallelActionSequence/READER') # ======================================================================== digi.info('Created SIGNAL input') - signal = input.adopt_action('DigiROOTInput/SignalReader', mask=0x0, input=[digi.next_input()]) + signal = input.adopt_action('DigiROOTInput/SignalReader', mask=0xFEED, input=[digi.next_input()]) digi.check_creation([signal]) # ======================================================================== event = digi.event_action('DigiSequentialActionSequence/EventAction') proc = event.adopt_action('DigiMultiContainerProcessor/ContainerProc', - input_masks=[0x0, 0x1, 0x2, 0x3]) - conts = digi.containers(3) + input_masks=[0x0, 0x1, 0x2, 0x3, 0xFEED]) + conts = digi.containers(2) for i in range(len(conts)): - merge = dddigi.Action(digi.kernel(), 'DigiContainerProcessor/SegmentPrint_%03d'%(i,)); + merge = dddigi.Action(digi.kernel(), 'DigiContainerProcessor/SegmentPrint_%03d' % (i,)) proc.adopt_processor(merge, conts[i]) - #dump = event.adopt_action('DigiStoreDump/StoreDump') - #digi.check_creation([combine, dump, splitter]) - #digi.info('Created event.dump') + # dump = event.adopt_action('DigiStoreDump/StoreDump') + # digi.check_creation([combine, dump, splitter]) + # digi.info('Created event.dump') # ======================================================================== - digi.run_checked(num_events=1, num_threads=5, parallel=3) + digi.run_checked(num_events=5, num_threads=15, parallel=3) if __name__ == '__main__': diff --git a/examples/DDDigi/scripts/TestSegmentationSplit.py b/examples/DDDigi/scripts/TestSegmentationSplit.py index 2707b1769..bbe09bc19 100644 --- a/examples/DDDigi/scripts/TestSegmentationSplit.py +++ b/examples/DDDigi/scripts/TestSegmentationSplit.py @@ -22,11 +22,13 @@ def run(): digi.check_creation([signal]) # ======================================================================== event = digi.event_action('DigiSequentialActionSequence/EventAction') - combine = event.adopt_action('DigiContainerCombine/Combine', input_masks=[0x0, 0x1, 0x2, 0x3], deposit_mask=0xFEED) + combine = event.adopt_action('DigiContainerCombine/Combine', input_masks=[0x0], deposit_mask=0xFEED) combine.erase_combined = True # Not thread-safe! only do in SequentialActionSequence - splitter = event.adopt_action('DigiSegmentationSplitter/Splitter', - input='deposits', - mask=0xFEED, + splitter = event.adopt_action('DigiSegmentSplitter/Splitter', + input_segment='deposits', + input_mask=0xFEED, + output_segment='', + output_mask=0xBABE, detector='SiTrackerBarrel', split_by='layer', processor_type='DigiSegmentDepositPrint') -- GitLab