DPC++ Runtime
Runtime libraries for oneAPI DPC++
xpti_registry.hpp
Go to the documentation of this file.
1 //==---------- xpti_registry.hpp ----- XPTI Stream Registry ----------------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #pragma once
10 
11 #include <mutex>
12 #include <string>
13 #include <unordered_set>
14 
15 #include <sycl/detail/common.hpp>
16 #include <sycl/version.hpp>
17 
18 #ifdef XPTI_ENABLE_INSTRUMENTATION
19 // Include the headers necessary for emitting
20 // traces using the trace framework
21 #include "xpti/xpti_trace_framework.hpp"
22 #endif
23 
24 namespace sycl {
26 namespace detail {
27 // We define a sycl stream name and this will be used by the instrumentation
28 // framework
29 inline constexpr const char *SYCL_STREAM_NAME = "sycl";
30 // Stream name being used for traces generated from the SYCL plugin layer
31 inline constexpr const char *SYCL_PICALL_STREAM_NAME = "sycl.pi";
32 // Stream name being used for traces generated from PI calls. This stream
33 // contains information about function arguments.
34 inline constexpr const char *SYCL_PIDEBUGCALL_STREAM_NAME = "sycl.pi.debug";
35 inline constexpr auto SYCL_MEM_ALLOC_STREAM_NAME =
36  "sycl.experimental.mem_alloc";
37 
38 #ifdef XPTI_ENABLE_INSTRUMENTATION
39 extern uint8_t GBufferStreamID;
40 extern uint8_t GMemAllocStreamID;
41 extern xpti::trace_event_data_t *GMemAllocEvent;
42 extern xpti::trace_event_data_t *GSYCLGraphEvent;
43 
44 #define STR(x) #x
45 #define SYCL_VERSION_STR \
46  "sycl " STR(__LIBSYCL_MAJOR_VERSION) "." STR(__LIBSYCL_MINOR_VERSION)
47 
50 constexpr uint32_t GMajVer = __LIBSYCL_MAJOR_VERSION;
51 constexpr uint32_t GMinVer = __LIBSYCL_MINOR_VERSION;
52 constexpr const char *GVerStr = SYCL_VERSION_STR;
53 #endif
54 
55 // Stream name being used to notify about buffer objects.
56 inline constexpr const char *SYCL_BUFFER_STREAM_NAME =
57  "sycl.experimental.buffer";
58 
59 class XPTIRegistry {
60 public:
62 #ifdef XPTI_ENABLE_INSTRUMENTATION
63  std::call_once(MInitialized, [this] {
64  xptiFrameworkInitialize();
65  // SYCL buffer events
66  GBufferStreamID = xptiRegisterStream(SYCL_BUFFER_STREAM_NAME);
67  this->initializeStream(SYCL_BUFFER_STREAM_NAME, 0, 1, "0.1");
68 
69  // Memory allocation events
70  GMemAllocStreamID = xptiRegisterStream(SYCL_MEM_ALLOC_STREAM_NAME);
71  this->initializeStream(SYCL_MEM_ALLOC_STREAM_NAME, 0, 1, "0.1");
72  xpti::payload_t MAPayload("SYCL Memory Allocations Layer");
73  uint64_t MAInstanceNo = 0;
74  GMemAllocEvent = xptiMakeEvent("SYCL Memory Allocations", &MAPayload,
75  xpti::trace_algorithm_event,
76  xpti_at::active, &MAInstanceNo);
77  });
78 #endif
79  }
80 
87  void initializeStream(const std::string &StreamName, uint32_t MajVer,
88  uint32_t MinVer, const std::string &VerStr) {
89 #ifdef XPTI_ENABLE_INSTRUMENTATION
90  MActiveStreams.insert(StreamName);
91  xptiInitialize(StreamName.c_str(), MajVer, MinVer, VerStr.c_str());
92 #endif // XPTI_ENABLE_INSTRUMENTATION
93  }
94 
96 #ifdef XPTI_ENABLE_INSTRUMENTATION
97  for (const auto &StreamName : MActiveStreams) {
98  xptiFinalize(StreamName.c_str());
99  }
100  xptiFrameworkFinalize();
101 #endif // XPTI_ENABLE_INSTRUMENTATION
102  }
103 
104  static void bufferConstructorNotification(const void *,
105  const detail::code_location &,
106  const void *, const void *,
107  uint32_t, uint32_t, size_t[3]);
108  static void bufferAssociateNotification(const void *, const void *);
109  static void bufferReleaseNotification(const void *, const void *);
110  static void bufferDestructorNotification(const void *);
111  static void bufferAccessorNotification(const void *, const void *, uint32_t,
112  uint32_t,
113  const detail::code_location &);
114 
115 private:
116  std::unordered_set<std::string> MActiveStreams;
117  std::once_flag MInitialized;
118 
119 #ifdef XPTI_ENABLE_INSTRUMENTATION
120  static xpti::trace_event_data_t *
121  createTraceEvent(const void *Obj, const void *ObjName, uint64_t &IId,
122  const detail::code_location &CodeLoc,
123  uint16_t TraceEventType);
124 #endif // XPTI_ENABLE_INSTRUMENTATION
125 };
126 
130 #if XPTI_ENABLE_INSTRUMENTATION
131 class XPTIScope {
132 public:
133  using TracePoint = xpti::framework::tracepoint_t;
141  XPTIScope(void *CodePtr, uint16_t TraceType, const char *StreamName,
142  const char *UserData)
143  : MUserData(UserData), MStreamID(0), MInstanceID(0), MScopedNotify(false),
144  MTraceType(0) {
146  auto TData = Tls.query();
147  // If TLS is not set, we can still genertate universal IDs with user data
148  // and CodePtr information
149  const char *FuncName = UserData;
150  if (TData.functionName())
151  FuncName = TData.functionName();
152  // Create a tracepoint object that has a lifetime of this class
153  MTP = new TracePoint(TData.fileName(), FuncName, TData.lineNumber(),
154  TData.columnNumber(), CodePtr);
155  if (MTraceType == (uint16_t)xpti::trace_point_type_t::graph_create ||
156  MTraceType == (uint16_t)xpti::trace_point_type_t::node_create ||
157  MTraceType == (uint16_t)xpti::trace_point_type_t::edge_create)
158  MTP->parent_event(GSYCLGraphEvent);
159  // Now if tracing is enabled, create trace events and notify
160  if (xptiTraceEnabled() && MTP) {
161  MTP->stream(StreamName).trace_type((xpti::trace_point_type_t)TraceType);
162  MTraceEvent = const_cast<xpti::trace_event_data_t *>(MTP->trace_event());
163  MStreamID = MTP->stream_id();
164  MInstanceID = MTP->instance_id();
165  }
166  }
167 
168  xpti::trace_event_data_t *traceEvent() { return MTraceEvent; }
169 
170  uint8_t streamID() { return MStreamID; }
171 
172  uint64_t instanceID() { return MTP ? MTP->instance_id() : 0; }
173 
174  XPTIScope &
175  addMetadata(const std::function<void(xpti::trace_event_data_t *)> &Callback) {
176  if (xptiTraceEnabled() && MTP) {
177  auto TEvent = const_cast<xpti::trace_event_data_t *>(MTP->trace_event());
178  Callback(TEvent);
179  }
180  return *this;
181  }
182 
183  XPTIScope &notify() {
184  MTP->notify(static_cast<const void *>(MUserData));
185  return *this;
186  }
187 
190  XPTIScope &scopedNotify(uint16_t TraceType) {
191  if (xptiTraceEnabled() && MTP) {
192  MTraceType = TraceType & 0xfffe;
193  MScopedNotify = true;
194  xptiNotifySubscribers(MStreamID, MTraceType, nullptr, MTraceEvent,
195  MInstanceID, static_cast<const void *>(MUserData));
196  }
197  return *this;
198  }
199  ~XPTIScope() {
200  if (xptiTraceEnabled() && MTP && MScopedNotify) {
201  if (MTraceType == (uint16_t)xpti::trace_point_type_t::signal ||
202  MTraceType == (uint16_t)xpti::trace_point_type_t::graph_create ||
203  MTraceType == (uint16_t)xpti::trace_point_type_t::node_create ||
204  MTraceType == (uint16_t)xpti::trace_point_type_t::edge_create ||
205  MTraceType == (uint16_t)xpti::trace_point_type_t::diagnostics)
206  return;
207 
208  // The definition of the following trace point types have an error and
209  // cannot be fixed until the next ABI breakage window. Until then, we
210  // expclicity handle these cases. Once the types mem_alloc_end,
211  // mem_release_end and offload_alloc_destruct have been defined correctly,
212  // then all we need is (MTraceType = MTraceType | 1)
213  if (MTraceType == (uint16_t)xpti::trace_point_type_t::mem_alloc_begin) {
214  MTraceType = (uint16_t)xpti::trace_point_type_t::mem_alloc_end;
215  } else if (MTraceType ==
216  (uint16_t)xpti::trace_point_type_t::mem_release_begin) {
217  MTraceType = (uint16_t)xpti::trace_point_type_t::mem_release_end;
218  } else if (MTraceType ==
219  (uint16_t)xpti::trace_point_type_t::offload_alloc_construct) {
220  MTraceType = (uint16_t)xpti::trace_point_type_t::offload_alloc_destruct;
221  } else
222  MTraceType = MTraceType | 1;
223 
224  // Only notify for a trace type that has a begin/end
225  xptiNotifySubscribers(MStreamID, MTraceType, nullptr, MTraceEvent,
226  MInstanceID, static_cast<const void *>(MUserData));
227  }
228  // Delete the tracepoint object which will clear TLS if it is the top of
229  // the scope
230  delete MTP;
231  }
232 
233 private:
234  // Tracepoint_t object who's lifetime is that of the class
235  TracePoint *MTP = nullptr;
236  // Trace event created from the TLS data, if it exists
237  xpti::trace_event_data_t *MTraceEvent = nullptr;
238  // The const string that indicates the operation
239  const char *MUserData = nullptr;
240  // The stream on which the notifications occur
241  uint8_t MStreamID;
242  // The instance ID for the trace event; if it is called in a loop, then the
243  // trace event ID will remain the same, but the instance ID will increment
244  uint64_t MInstanceID;
245  // If scoped notifcation is requested, this tracks the request
246  bool MScopedNotify;
247  // The trace type information for scoped notifications
248  uint16_t MTraceType;
249 }; // class XPTIScope
250 #endif
251 
252 } // namespace detail
253 } // __SYCL_INLINE_VER_NAMESPACE(_V1)
254 } // namespace sycl
sycl::_V1::detail::tls_code_loc_t::query
const detail::code_location & query()
Query the information in the TLS slot.
Definition: common.cpp:55
sycl::_V1::detail::SYCL_STREAM_NAME
constexpr const char * SYCL_STREAM_NAME
Definition: xpti_registry.hpp:29
sycl::_V1::detail::SYCL_MEM_ALLOC_STREAM_NAME
constexpr auto SYCL_MEM_ALLOC_STREAM_NAME
Definition: xpti_registry.hpp:35
__SYCL_INLINE_VER_NAMESPACE
#define __SYCL_INLINE_VER_NAMESPACE(X)
Definition: defines_elementary.hpp:11
sycl::_V1::detail::SYCL_PIDEBUGCALL_STREAM_NAME
constexpr const char * SYCL_PIDEBUGCALL_STREAM_NAME
Definition: xpti_registry.hpp:34
sycl
---— Error handling, matching OpenCL plugin semantics.
Definition: access.hpp:14
sycl::_V1::detail::SYCL_BUFFER_STREAM_NAME
constexpr const char * SYCL_BUFFER_STREAM_NAME
Definition: xpti_registry.hpp:56
sycl::_V1::detail::XPTIRegistry
Definition: xpti_registry.hpp:59
sycl::_V1::detail::tls_code_loc_t
Data type that manages the code_location information in TLS.
Definition: common.hpp:152
sycl::_V1::detail::SYCL_PICALL_STREAM_NAME
constexpr const char * SYCL_PICALL_STREAM_NAME
Definition: xpti_registry.hpp:31
sycl::_V1::detail::XPTIRegistry::initializeFrameworkOnce
void initializeFrameworkOnce()
Definition: xpti_registry.hpp:61
sycl::_V1::detail::code_location::functionName
constexpr const char * functionName() const noexcept
Definition: common.hpp:90
common.hpp
sycl::_V1::detail::XPTIRegistry::initializeStream
void initializeStream(const std::string &StreamName, uint32_t MajVer, uint32_t MinVer, const std::string &VerStr)
Notifies XPTI subscribers about new stream.
Definition: xpti_registry.hpp:87
GVerStr
constexpr auto GVerStr
Definition: tracing.cpp:33
GMajVer
constexpr int GMajVer
Definition: tracing.cpp:34
sycl::_V1::detail::code_location
Definition: common.hpp:66
GMinVer
constexpr int GMinVer
Definition: tracing.cpp:35
sycl::_V1::detail::XPTIRegistry::~XPTIRegistry
~XPTIRegistry()
Definition: xpti_registry.hpp:95