18#include <nvtx3/nvToolsExt.h>
19#include <tbb/concurrent_hash_map.h>
30 static uint32_t cycle_color( uint64_t i ) {
31 constexpr uint32_t alpha = 0xFFu << 24;
32 constexpr uint8_t cernR = 0;
33 constexpr uint8_t cernG = 51;
34 constexpr uint8_t cernB = 160;
35 auto r =
static_cast<uint8_t
>( ( i * 23 ) + cernR );
36 auto g =
static_cast<uint8_t
>( ( i * 47 ) + cernG );
37 auto b =
static_cast<uint8_t
>( ( i * 71 ) + cernB );
38 return alpha | (
static_cast<uint32_t
>( r ) << 16 ) | (
static_cast<uint32_t
>( g ) << 8 ) |
39 static_cast<uint32_t
>( b );
60 static inline nvtxDomainHandle_t
s_domain{
nullptr };
69 tbb::concurrent_hash_map<std::string, nvtxRangeId_t>
m_ranges;
79 return base_class::initialize()
82 if ( incidentSvc.isValid() ) {
83 incidentSvc->addListener(
this,
"ALL" );
85 info() <<
"No IncidentSvc, NVTXAuditor will not be able to annotate incidents." <<
endmsg;
90 error() <<
"Attempting to initialize NVTX categories more than once." <<
endmsg;
94 s_domain = nvtxDomainCreateA(
"Gaudi" );
97 if ( hiveWhiteBoard.isValid() ) {
102 nvtxDomainNameCategoryA(
s_domain, slot + 1, std::format(
"Slot {}", slot ).c_str() );
107 nvtxDomainNameCategoryA(
s_domain, 1,
"Slot 0" );
122 return base_class::finalize();
135 auto eventAttrib = nvtxEventAttributes_t{};
136 eventAttrib.version = NVTX_VERSION;
137 eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE;
138 eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII;
139 eventAttrib.message.ascii = incident.
type().c_str();
142 nvtxDomainMarkEx(
s_domain, &eventAttrib );
143 debug() << std::format(
"Marked incident {} from {}", incident.
type(), incident.
source() ) <<
endmsg;
147 eventAttrib.colorType = NVTX_COLOR_ARGB;
148 eventAttrib.color = ::cycle_color( incident.
context().
evt() );
149 eventAttrib.category = incident.
context().
slot() + 1;
150 eventAttrib.payloadType = NVTX_PAYLOAD_TYPE_UNSIGNED_INT64;
151 eventAttrib.payload.ullValue = incident.
context().
evt();
153 nvtxDomainMarkEx(
s_domain, &eventAttrib );
154 debug() << std::format(
"Marked incident {} from {} with context {}", incident.
type(), incident.
source(),
167 if ( ctx.valid() ) {
return std::format(
"{}:{}:{}", caller, event, ctx.evt() ); }
168 return std::format(
"{}:{}", caller, event );
174 std::string
make_label( std::string
const& event, std::string
const& caller )
const {
175 return std::format(
"{}:{}", caller, event );
188 auto eventAttrib = nvtxEventAttributes_t{};
189 eventAttrib.version = NVTX_VERSION;
190 eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE;
191 eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII;
192 eventAttrib.message.ascii = label.c_str();
194 if ( !ctx.valid() ) {
195 debug() << std::format(
"Starting range for {}", label ) <<
endmsg;
196 return nvtxDomainRangeStartEx(
s_domain, &eventAttrib );
199 eventAttrib.colorType = NVTX_COLOR_ARGB;
200 eventAttrib.color = ::cycle_color( ctx.evt() );
201 eventAttrib.category = ctx.slot() + 1;
202 eventAttrib.payloadType = NVTX_PAYLOAD_TYPE_UNSIGNED_INT64;
203 eventAttrib.payload.ullValue = ctx.evt();
205 debug() << std::format(
"Starting range for {} with context {}", label, ctx ) <<
endmsg;
206 return nvtxDomainRangeStartEx(
s_domain, &eventAttrib );
219 void before( std::string
const& event, std::string
const& caller,
EventContext const& ctx )
override {
222 if ( IAuditor::Suspension == event ) {
223 auto execute_key =
make_key( IAuditor::Execute, caller, ctx );
224 auto acc =
decltype(
m_ranges )::accessor{};
225 if ( !
m_ranges.find( acc, execute_key ) ) {
226 error() << std::format(
"Execution range for {} does not exist while suspending", execute_key ) <<
endmsg;
228 nvtxDomainRangeEnd(
s_domain, acc->second );
230 debug() << std::format(
"Suspended execution range for {}", execute_key ) <<
endmsg;
235 auto key =
make_key( event, caller, ctx );
238 auto ret =
m_ranges.emplace( key,
id );
240 error() << std::format(
"Range for {} already exists", key ) <<
endmsg;
243 debug() << std::format(
"Started range for {}", key ) <<
endmsg;
262 if ( IAuditor::Suspension == event ) {
263 auto execute_key =
make_key( IAuditor::Execute, caller, ctx );
264 auto label =
make_label( IAuditor::Execute, caller );
266 auto ret =
m_ranges.emplace( execute_key,
id );
268 error() << std::format(
"Execution range for {} already exists while resuming", execute_key ) <<
endmsg;
271 debug() << std::format(
"Resumed execution range for {}", execute_key ) <<
endmsg;
276 auto key =
make_key( event, caller, ctx );
277 auto acc =
decltype(
m_ranges )::accessor{};
279 nvtxDomainRangeEnd(
s_domain, acc->second );
282 error() << std::format(
"Range for {} does not exist", key ) <<
endmsg;
284 debug() << std::format(
"Finished range for {}", key ) <<
endmsg;
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
#define DECLARE_COMPONENT(type)
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
This class represents an entry point to all the event specific data.
SmartIF< T > service(std::string_view name, bool createIf=false) const
Access a service by name, creating it if it doesn't already exist.
Base class for all Incidents (computing events).
const EventContext & context() const
Access to the EventContext of the source of the incident.
const std::string & type() const
Access to the incident type.
const std::string & source() const
Access to the source of the incident.
Auditor that uses NVTX to annotate ranges and incidents for profiling with NVIDIA tools.
std::string make_label(std::string const &event, std::string const &caller) const
Helper to create a label for the audited event.
static nvtxDomainHandle_t s_domain
tbb::concurrent_hash_map< std::string, nvtxRangeId_t > m_ranges
nvtxRangeId_t start_range(std::string const &label, EventContext const &ctx)
Start an NVTX range for the audited event.
void after(std::string const &event, std::string const &caller, EventContext const &ctx, StatusCode const &=StatusCode::SUCCESS) override
Handle 'after' audit for given event by ending the associated NVTX range.
void handle(const Incident &incident) override
Handle an incident by annotating it with an NVTX marker.
static uint32_t s_numCategories
StatusCode initialize() override
Initialize the auditor and register for all available incidents if the Incident service exists.
void before(std::string const &event, std::string const &caller, EventContext const &ctx) override
Handle 'before' audit for given event by starting an associated NVTX range.
std::string make_key(std::string const &event, std::string const &caller, EventContext const &ctx) const
Helper to create an identifier key for storing an associated range in the map.
StatusCode finalize() override
Finalize the auditor, releasing the NVTX domain.
This class is used for returning status codes from appropriate routines.
StatusCode andThen(F &&f, ARGS &&... args) const
Chain code blocks making the execution conditional a success result.
constexpr static const auto SUCCESS
constexpr static const auto FAILURE
Base class used to extend a class implementing other interfaces.
extends base_class
Typedef to this class.