diff --git a/GaudiHive/src/AvalancheSchedulerSvc.cpp b/GaudiHive/src/AvalancheSchedulerSvc.cpp index 24e48d6dfff40af80aff1b79fe21d5702a599cfb..7f0737f444ac0ba97d790d2044e6528a7aaa79d3 100644 --- a/GaudiHive/src/AvalancheSchedulerSvc.cpp +++ b/GaudiHive/src/AvalancheSchedulerSvc.cpp @@ -837,45 +837,101 @@ void AvalancheSchedulerSvc::dumpSchedulerState( int iSlot ) { // To have just one big message - std::ostringstream outputMessageStream; + std::ostringstream outputMS; + + outputMS << "Dumping scheduler state (inhale, exhale - everything is gonna be okay!)" << std::endl + << "=========================================================================================" << std::endl + << "++++++++++++++++++++++++++++++++ DUMPING SCHEDULER STATE ++++++++++++++++++++++++++++++++" << std::endl + << "=========================================================================================" << std::endl + << std::endl; + + outputMS << "------------------------- Last schedule: Task/Slot/Thread Mapping -----------------------" << std::endl + << std::endl; + + // Figure if TimelineSvc is available (used below to detect threads IDs) + auto timelineSvc = serviceLocator()->service<ITimelineSvc>( "TimelineSvc", false ); + if ( !timelineSvc.isValid() ) { + outputMS << "Enable TimelineSvc to trace task/slot/thread mapping" << std::endl; + } else if ( !timelineSvc->isEnabled() ) { + outputMS << "Turn on timelining in the TimelineSvc to trace task/slot/thread mapping" << std::endl; + } else { - if ( 0 > iSlot ) - outputMessageStream << "Dumping scheduler state for all slots:" << std::endl; - else - outputMessageStream << "Dumping scheduler state for slot " << iSlot << ":" << std::endl; + // Figure optimal printout layout + size_t indt( 0 ); + for ( auto& slot : m_eventSlots ) + for ( auto it = slot.algsStates.begin( AlgsExecutionStates::State::SCHEDULED ); + it != slot.algsStates.end( AlgsExecutionStates::State::SCHEDULED ); ++it ) + if ( index2algname( (uint)*it ).length() > indt ) indt = index2algname( (uint)*it ).length(); + + // Figure the last running schedule across all slots + for ( auto& slot : m_eventSlots ) { + for ( auto it = slot.algsStates.begin( AlgsExecutionStates::State::SCHEDULED ); + it != slot.algsStates.end( AlgsExecutionStates::State::SCHEDULED ); ++it ) { + + const std::string algoName{index2algname( (uint)*it )}; + + outputMS << " task: " << std::setw( indt ) << algoName << " evt: " << slot.eventContext->evt() + << " slot: " << slot.eventContext->slot(); + + // Try to get POSIX threads IDs the currently running tasks are scheduled to + if ( timelineSvc.isValid() ) { + TimelineEvent te{}; + te.algorithm = algoName; + te.slot = slot.eventContext->slot(); + te.event = slot.eventContext->evt(); + + if ( timelineSvc->getTimelineEvent( te ) ) + outputMS << " thread.id: 0x" << std::hex << te.thread << std::dec; + else + outputMS << " thread.id: [unknown]"; // this means a task has just + // been signed off as SCHEDULED, + // but has not been assigned to a thread yet + // (i.e., not running yet) + } + outputMS << " [" << m_algExecStateSvc->algExecState( algoName, *( slot.eventContext ) ) << "] " << std::endl; + } + } + } - outputMessageStream << "============================== Execution Task States =============================" - << std::endl; - dumpState( outputMessageStream ); + dumpState( outputMS ); - outputMessageStream << std::endl - << "============================== Control Flow and FSM States =====================" - << std::endl; + outputMS << std::endl + << "---------------------------- Task/CF/FSM Mapping " << ( 0 > iSlot ? "[all slots] --" : "[target slot] " ) + << "--------------------------" << std::endl + << std::endl; int slotCount = -1; - for ( auto& thisSlot : m_eventSlots ) { + for ( auto& slot : m_eventSlots ) { slotCount++; - if ( thisSlot.complete ) continue; + if ( slot.complete ) continue; - outputMessageStream << "----------- slot: " << thisSlot.eventContext->slot() - << " event: " << thisSlot.eventContext->evt() << " -----------" << std::endl; + outputMS << "[ slot: " + << ( slot.eventContext->valid() ? std::to_string( slot.eventContext->slot() ) : "[ctx invalid]" ) + << " event: " + << ( slot.eventContext->valid() ? std::to_string( slot.eventContext->evt() ) : "[ctx invalid]" ) + << " ]:" << std::endl + << std::endl; if ( 0 > iSlot or iSlot == slotCount ) { // Snapshot of the Control Flow and FSM states - outputMessageStream << m_precSvc->printState( thisSlot ) << std::endl; + outputMS << m_precSvc->printState( slot ) << std::endl; // Mention sub slots - if ( thisSlot.allSubSlots.size() ) { - outputMessageStream << std::endl << "Number of sub-slots:" << thisSlot.allSubSlots.size() << std::endl; - outputMessageStream << "Sub-slot algorithms ready:" << thisSlot.subSlotAlgsReady.size() << std::endl; + if ( slot.allSubSlots.size() ) { + outputMS << std::endl << "Number of sub-slots:" << slot.allSubSlots.size() << std::endl; + outputMS << "Sub-slot algorithms ready:" << slot.subSlotAlgsReady.size() << std::endl; } } } - outputMessageStream << "=================================== END ======================================" << std::endl; + outputMS << std::endl + << "=========================================================================================" << std::endl + << "++++++++++++++++++++++++++++++++++++++ END OF DUMP ++++++++++++++++++++++++++++++++++++++" << std::endl + << "=========================================================================================" << std::endl + << std::endl; - info() << outputMessageStream.str() << endmsg; + info() << outputMS.str() << endmsg; } //--------------------------------------------------------------------------- @@ -1085,7 +1141,7 @@ StatusCode AvalancheSchedulerSvc::promoteToAsyncExecuted( unsigned int iAlgo, in } //=========================================================================== -void AvalancheSchedulerSvc::addAlg( Algorithm* a, EventContext* e, pthread_t t ) +void AvalancheSchedulerSvc::addAlg( IAlgorithm* a, EventContext* e, pthread_t t ) { std::lock_guard<std::mutex> lock( m_ssMut ); @@ -1093,7 +1149,7 @@ void AvalancheSchedulerSvc::addAlg( Algorithm* a, EventContext* e, pthread_t t ) } //=========================================================================== -bool AvalancheSchedulerSvc::delAlg( Algorithm* a ) +bool AvalancheSchedulerSvc::delAlg( IAlgorithm* a ) { std::lock_guard<std::mutex> lock( m_ssMut ); diff --git a/GaudiHive/src/AvalancheSchedulerSvc.h b/GaudiHive/src/AvalancheSchedulerSvc.h index 6234fc4c28457b6d06920afda196ae1e7878c3b2..6e63c57069fa4ee99bca03a9f157e0d61c762089 100644 --- a/GaudiHive/src/AvalancheSchedulerSvc.h +++ b/GaudiHive/src/AvalancheSchedulerSvc.h @@ -29,7 +29,6 @@ #include "tbb/task.h" class IAlgorithm; -class Algorithm; typedef AlgsExecutionStates::State State; typedef std::function<StatusCode()> action; @@ -274,9 +273,9 @@ private: { public: - SchedulerState( Algorithm* a, EventContext* e, pthread_t t ) : m_a( a ), m_e( *e ), m_t( t ) {} + SchedulerState( IAlgorithm* a, EventContext* e, pthread_t t ) : m_a( a ), m_e( *e ), m_t( t ) {} - Algorithm* alg() const { return m_a; } + IAlgorithm* alg() const { return m_a; } EventContext ctx() const { return m_e; } pthread_t thread() const { return m_t; } @@ -289,12 +288,12 @@ private: bool operator==( const SchedulerState& ss ) const { return ( m_a == ss.alg() ); } - bool operator==( Algorithm* a ) const { return ( m_a == a ); } + bool operator==( IAlgorithm* a ) const { return ( m_a == a ); } bool operator<( const SchedulerState& rhs ) const { return ( m_a < rhs.alg() ); } private: - Algorithm* m_a; + IAlgorithm* m_a; EventContext m_e; pthread_t m_t; }; @@ -303,8 +302,8 @@ private: static std::mutex m_ssMut; public: - void addAlg( Algorithm*, EventContext*, pthread_t ); - bool delAlg( Algorithm* ); + void addAlg( IAlgorithm*, EventContext*, pthread_t ); + bool delAlg( IAlgorithm* ); void dumpState() override; private: diff --git a/GaudiHive/src/TimelineSvc.cpp b/GaudiHive/src/TimelineSvc.cpp index ea7b1ba22afbd31b085e05667526b738ae2f126c..7bddac65ec723065167a9711c01a913195df1b98 100644 --- a/GaudiHive/src/TimelineSvc.cpp +++ b/GaudiHive/src/TimelineSvc.cpp @@ -72,15 +72,16 @@ void TimelineSvc::registerTimelineEvent( const TimelineEvent& e ) } } -void TimelineSvc::getTimelineEvent( TimelineEvent& e ) const +bool TimelineSvc::getTimelineEvent( TimelineEvent& e ) const { for ( const auto& candidate : m_events ) { if ( candidate.algorithm == e.algorithm && candidate.event == e.event && candidate.slot == e.slot ) { e = candidate; - break; + return true; } } + return false; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ diff --git a/GaudiHive/src/TimelineSvc.h b/GaudiHive/src/TimelineSvc.h index 4f9e6ad2ccf25a58b8fcb1c30da9a99b096040a1..b1e6d71b0428221f64d83ce7d5c8ef7d645e8da6 100644 --- a/GaudiHive/src/TimelineSvc.h +++ b/GaudiHive/src/TimelineSvc.h @@ -19,7 +19,7 @@ public: StatusCode finalize() override; void registerTimelineEvent( const TimelineEvent& ) override; - void getTimelineEvent( TimelineEvent& ) const override; + bool getTimelineEvent( TimelineEvent& ) const override; bool isEnabled() const override { return m_isEnabled; } diff --git a/GaudiKernel/GaudiKernel/ITimelineSvc.h b/GaudiKernel/GaudiKernel/ITimelineSvc.h index 15c7f5e30c63dcbc77cb7c991e7d974bc98bc64a..245d09074c3753d9efa5c6efbe7977ff43b448ce 100644 --- a/GaudiKernel/GaudiKernel/ITimelineSvc.h +++ b/GaudiKernel/GaudiKernel/ITimelineSvc.h @@ -30,7 +30,7 @@ public: virtual void registerTimelineEvent( const TimelineEvent& ) = 0; // Augment a partially pre-filled TimelineEvent object with matching info - virtual void getTimelineEvent( TimelineEvent& ) const = 0; + virtual bool getTimelineEvent( TimelineEvent& ) const = 0; virtual bool isEnabled() const = 0; };