Skip to content

Commit fd50ead

Browse files
author
Alexander Batashev
authored
[XPTI] Allow arbitrary data types in metadata (#4998)
1 parent 8aa15c1 commit fd50ead

23 files changed

+1042
-122
lines changed

sycl/doc/SYCLInstrumentationUsingXPTI.md

Lines changed: 29 additions & 5 deletions
Large diffs are not rendered by default.

sycl/source/detail/device_impl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,13 @@ bool device_impl::isAssertFailSupported() const {
347347
return MIsAssertFailSupported;
348348
}
349349

350+
std::string device_impl::getDeviceName() const {
351+
std::call_once(MDeviceNameFlag,
352+
[this]() { MDeviceName = get_info<info::device::name>(); });
353+
354+
return MDeviceName;
355+
}
356+
350357
} // namespace detail
351358
} // namespace sycl
352359
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/source/detail/device_impl.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <detail/platform_impl.hpp>
1717

1818
#include <memory>
19+
#include <mutex>
1920

2021
__SYCL_INLINE_NAMESPACE(cl) {
2122
namespace sycl {
@@ -225,6 +226,8 @@ class device_impl {
225226

226227
bool isAssertFailSupported() const;
227228

229+
std::string getDeviceName() const;
230+
228231
private:
229232
explicit device_impl(pi_native_handle InteropDevice, RT::PiDevice Device,
230233
PlatformImplPtr Platform, const plugin &Plugin);
@@ -234,6 +237,8 @@ class device_impl {
234237
bool MIsHostDevice;
235238
PlatformImplPtr MPlatform;
236239
bool MIsAssertFailSupported = false;
240+
mutable std::string MDeviceName;
241+
mutable std::once_flag MDeviceNameFlag;
237242
}; // class device_impl
238243

239244
} // namespace detail

sycl/source/detail/queue_impl.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,12 @@ void *queue_impl::instrumentationProlog(const detail::code_location &CodeLoc,
231231
DevStr = "ACCELERATOR";
232232
else
233233
DevStr = "UNKNOWN";
234-
xptiAddMetadata(WaitEvent, "sycl_device", DevStr.c_str());
234+
xpti::addMetadata(WaitEvent, "sycl_device", DevStr);
235235
if (HasSourceInfo) {
236-
xptiAddMetadata(WaitEvent, "sym_function_name", CodeLoc.functionName());
237-
xptiAddMetadata(WaitEvent, "sym_source_file_name", CodeLoc.fileName());
238-
xptiAddMetadata(WaitEvent, "sym_line_no",
239-
std::to_string(CodeLoc.lineNumber()).c_str());
236+
xpti::addMetadata(WaitEvent, "sym_function_name", CodeLoc.functionName());
237+
xpti::addMetadata(WaitEvent, "sym_source_file_name", CodeLoc.fileName());
238+
xpti::addMetadata(WaitEvent, "sym_line_no",
239+
std::to_string(CodeLoc.lineNumber()));
240240
}
241241
xptiNotifySubscribers(StreamID, xpti::trace_wait_begin, nullptr, WaitEvent,
242242
QWaitInstanceNo,

sycl/source/detail/scheduler/commands.cpp

Lines changed: 119 additions & 65 deletions
Large diffs are not rendered by default.

sycl/source/detail/scheduler/commands.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <cstdint>
1313
#include <deque>
1414
#include <memory>
15+
#include <optional>
1516
#include <set>
1617
#include <unordered_set>
1718
#include <vector>
@@ -161,9 +162,9 @@ class Command {
161162
/// instrumentation to report these dependencies as edges.
162163
void resolveReleaseDependencies(std::set<Command *> &list);
163164
/// Creates an edge event when the dependency is a command.
164-
void emitEdgeEventForCommandDependence(Command *Cmd, void *ObjAddr,
165-
const std::string &Prefix,
166-
bool IsCommand);
165+
void emitEdgeEventForCommandDependence(
166+
Command *Cmd, void *ObjAddr, bool IsCommand,
167+
std::optional<access::mode> AccMode = std::nullopt);
167168
/// Creates an edge event when the dependency is an event.
168169
void emitEdgeEventForEventDependence(Command *Cmd, RT::PiEvent &EventAddr);
169170
/// Creates a signal event with the enqueued kernel event handle.

xpti/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 14)
66

77
set(XPTI_DIR ${CMAKE_CURRENT_LIST_DIR})
88
# Setting the same version as SYCL
9-
set(CMAKE_CXX_STANDARD 11)
9+
set(CMAKE_CXX_STANDARD 17)
1010

1111
option(XPTI_ENABLE_WERROR OFF)
1212

xpti/include/xpti/xpti_data_types.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ enum class payload_flag_t {
105105
using trace_point_t = uint16_t;
106106
using event_type_t = uint16_t;
107107
using string_id_t = int32_t;
108+
using object_id_t = int32_t;
108109

109110
using safe_flag_t = std::atomic<bool>;
110111
using safe_uint64_t = std::atomic<uint64_t>;
@@ -113,7 +114,7 @@ using safe_uint16_t = std::atomic<uint16_t>;
113114
using safe_int64_t = std::atomic<int64_t>;
114115
using safe_int32_t = std::atomic<int32_t>;
115116
using safe_int16_t = std::atomic<int16_t>;
116-
using metadata_t = std::unordered_map<string_id_t, string_id_t>;
117+
using metadata_t = std::unordered_map<string_id_t, object_id_t>;
117118

118119
#define XPTI_EVENT(val) xpti::event_type_t(val)
119120
#define XPTI_TRACE_POINT_BEGIN(val) xpti::trace_point_t(val << 1 | 0)
@@ -123,6 +124,12 @@ using metadata_t = std::unordered_map<string_id_t, string_id_t>;
123124
#define XPTI_PACK16_RET32(value1, value2) ((value1 << 16) | value2)
124125
#define XPTI_PACK32_RET64(value1, value2) (((uint64_t)value1 << 32) | value2)
125126

127+
struct object_data_t {
128+
size_t size;
129+
const char *data;
130+
uint8_t type;
131+
};
132+
126133
/// @brief Payload data structure that is optional for trace point callback
127134
/// API
128135
/// @details The payload structure, if determined at compile time, can deliver
@@ -479,6 +486,16 @@ enum class trace_activity_type_t {
479486
sleep_activity = 1 << 3
480487
};
481488

489+
/// Provides hints to the tools on how to interpret unknown metadata values.
490+
enum class metadata_type_t {
491+
binary = 0,
492+
string = 1,
493+
signed_integer = 2,
494+
unsigned_integer = 3,
495+
floating = 4,
496+
boolean = 5
497+
};
498+
482499
struct reserved_data_t {
483500
/// Has a reference to the associated payload field for an event
484501
payload_t *payload = nullptr;

xpti/include/xpti/xpti_trace_framework.h

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,32 @@ XPTI_EXPORT_API xpti::string_id_t xptiRegisterString(const char *string,
126126
/// @return A reference to the string identified by the string ID.
127127
XPTI_EXPORT_API const char *xptiLookupString(xpti::string_id_t id);
128128

129+
/// @brief Register an object to the object table
130+
///
131+
/// @details All object in the XPTI framework are referred to by their object
132+
/// IDs and this method allow you to register an object and get the object ID
133+
/// for it. This lifetime of this object reference is equal to the lifetime of
134+
/// the XPTI framework.
135+
/// @param data Raw bytes of data to be registered with the object table. If the
136+
/// object already exists in the table, the previous ID is returned.
137+
/// @param size Size in bytes of the object.
138+
/// @param type One of xpti::metadata_type_t values. These only serve as a hint
139+
/// to the tools for processing unknown values.
140+
/// @return The ID of the object being registered. If an error occurs
141+
/// during registration, xpti::invalid_id is returned.
142+
XPTI_EXPORT_API xpti::object_id_t xptiRegisterObject(const char *data,
143+
size_t size, uint8_t type);
144+
145+
/// @brief Lookup an object in the object table with its ID
146+
///
147+
/// @details All object in the XPTI framework are referred to by their object
148+
/// IDs and this method allows you to lookup an object by its object ID. The
149+
/// lifetime of the returned object reference is equal to the lifetime of the
150+
/// XPTI framework.
151+
/// @param id The ID of the object to lookup.
152+
/// @return A reference to the object identified by the object ID.
153+
XPTI_EXPORT_API xpti::object_data_t xptiLookupObject(xpti::object_id_t id);
154+
129155
/// @brief Register a payload with the framework
130156
/// @details Since a payload may contain multiple strings that may have been
131157
/// defined on the stack, it is recommended the payload object is registered
@@ -389,14 +415,14 @@ xptiNotifySubscribers(uint8_t stream_id, uint16_t trace_type,
389415
///
390416
/// @param e The event for which the metadata is being added
391417
/// @param key The key that identifies the metadata as a string
392-
/// @param value The value for the key as a string
418+
/// @param value_id The value for the key as an ID of a registered object.
393419
/// @return The result code which can be one of:
394420
/// 1. XPTI_RESULT_SUCCESS when the add is successful
395421
/// 2. XPTI_RESULT_INVALIDARG when the inputs are invalid
396422
/// 3. XPTI_RESULT_DUPLICATE when the key-value pair already exists
397423
XPTI_EXPORT_API xpti::result_t xptiAddMetadata(xpti::trace_event_data_t *e,
398424
const char *key,
399-
const char *value);
425+
xpti::object_id_t value_id);
400426

401427
/// @brief Query the metadata table for a given event
402428
/// @details In order to retrieve metadata information for a given event, you
@@ -453,6 +479,9 @@ typedef void (*xpti_set_universal_id_t)(uint64_t uid);
453479
typedef uint64_t (*xpti_get_unique_id_t)();
454480
typedef xpti::string_id_t (*xpti_register_string_t)(const char *, char **);
455481
typedef const char *(*xpti_lookup_string_t)(xpti::string_id_t);
482+
typedef xpti::string_id_t (*xpti_register_object_t)(const char *, size_t,
483+
uint8_t);
484+
typedef xpti::object_data_t (*xpti_lookup_object_t)(xpti::object_id_t);
456485
typedef uint64_t (*xpti_register_payload_t)(xpti::payload_t *);
457486
typedef uint8_t (*xpti_register_stream_t)(const char *);
458487
typedef xpti::result_t (*xpti_unregister_stream_t)(const char *);
@@ -473,7 +502,7 @@ typedef xpti::result_t (*xpti_notify_subscribers_t)(
473502
uint8_t, uint16_t, xpti::trace_event_data_t *, xpti::trace_event_data_t *,
474503
uint64_t instance, const void *temporal_user_data);
475504
typedef xpti::result_t (*xpti_add_metadata_t)(xpti::trace_event_data_t *,
476-
const char *, const char *);
505+
const char *, xpti::object_id_t);
477506
typedef xpti::metadata_t *(*xpti_query_metadata_t)(xpti::trace_event_data_t *);
478507
typedef bool (*xpti_trace_enabled_t)();
479508
}

xpti/include/xpti/xpti_trace_framework.hpp

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
#pragma once
99

1010
#include <atomic>
11+
#include <cassert>
1112
#include <cstdint>
13+
#include <cstring>
1214
#include <memory>
1315
#include <sstream>
1416
#include <thread>
@@ -306,6 +308,165 @@ struct finally {
306308

307309
} // namespace utils
308310

311+
template <typename T>
312+
inline result_t addMetadata(trace_event_data_t *Event, const std::string &Key,
313+
const T &Data) {
314+
static_assert(std::is_trivially_copyable_v<T>,
315+
"T must be trivially copyable");
316+
static_assert(!std::is_same_v<T, const char *>);
317+
318+
const uint8_t Type = [] {
319+
if (std::is_same_v<bool, T>) {
320+
return static_cast<uint8_t>(metadata_type_t::boolean);
321+
}
322+
if (std::numeric_limits<T>::is_integer &&
323+
std::numeric_limits<T>::is_signed) {
324+
return static_cast<uint8_t>(metadata_type_t::signed_integer);
325+
}
326+
if (std::numeric_limits<T>::is_integer &&
327+
!std::numeric_limits<T>::is_signed) {
328+
return static_cast<uint8_t>(metadata_type_t::unsigned_integer);
329+
}
330+
if (std::numeric_limits<T>::is_specialized &&
331+
!std::numeric_limits<T>::is_integer) {
332+
return static_cast<uint8_t>(metadata_type_t::floating);
333+
}
334+
335+
return static_cast<uint8_t>(metadata_type_t::binary);
336+
}();
337+
338+
object_id_t Value = xptiRegisterObject(reinterpret_cast<const char *>(&Data),
339+
sizeof(Data), Type);
340+
return xptiAddMetadata(Event, Key.c_str(), Value);
341+
}
342+
343+
template <>
344+
inline result_t addMetadata<std::string>(trace_event_data_t *Event,
345+
const std::string &Key,
346+
const std::string &Data) {
347+
const uint8_t Type = static_cast<uint8_t>(metadata_type_t::string);
348+
object_id_t Value = xptiRegisterObject(Data.c_str(), Data.size(), Type);
349+
return xptiAddMetadata(Event, Key.c_str(), Value);
350+
}
351+
352+
template <>
353+
inline result_t addMetadata<const char *>(trace_event_data_t *Event,
354+
const std::string &Key,
355+
const char *const &Data) {
356+
const uint8_t Type = static_cast<uint8_t>(metadata_type_t::string);
357+
object_id_t Value = xptiRegisterObject(Data, strlen(Data), Type);
358+
return xptiAddMetadata(Event, Key.c_str(), Value);
359+
}
360+
361+
template <typename T>
362+
inline std::pair<std::string_view, T>
363+
getMetadata(const metadata_t::value_type &MD) {
364+
static_assert(std::is_trivially_copyable<T>::value,
365+
"T must be trivially copyable");
366+
367+
object_data_t RawData = xptiLookupObject(MD.second);
368+
assert(RawData.size == sizeof(T));
369+
370+
T Value = *reinterpret_cast<const T *>(RawData.data);
371+
372+
const char *Key = xptiLookupString(MD.first);
373+
374+
return std::make_pair(std::string_view(Key), Value);
375+
}
376+
377+
template <>
378+
inline std::pair<std::string_view, std::string>
379+
getMetadata(const metadata_t::value_type &MD) {
380+
object_data_t RawData = xptiLookupObject(MD.second);
381+
382+
std::string Value(RawData.data, RawData.size);
383+
384+
const char *Key = xptiLookupString(MD.first);
385+
386+
return std::make_pair(std::string_view(Key), Value);
387+
}
388+
389+
template <>
390+
inline std::pair<std::string_view, std::string_view>
391+
getMetadata(const metadata_t::value_type &MD) {
392+
object_data_t RawData = xptiLookupObject(MD.second);
393+
394+
std::string_view Value(RawData.data, RawData.size);
395+
396+
const char *Key = xptiLookupString(MD.first);
397+
398+
return std::make_pair(std::string_view(Key), Value);
399+
}
400+
401+
inline std::string readMetadata(const metadata_t::value_type &MD) {
402+
object_data_t RawData = xptiLookupObject(MD.second);
403+
404+
if (RawData.type == static_cast<uint8_t>(metadata_type_t::binary)) {
405+
return std::string("Binary data, size: ") + std::to_string(RawData.size);
406+
}
407+
408+
if (RawData.type == static_cast<uint8_t>(metadata_type_t::boolean)) {
409+
bool Value = *reinterpret_cast<const bool *>(RawData.data);
410+
return Value ? "true" : "false";
411+
}
412+
413+
if (RawData.type == static_cast<uint8_t>(metadata_type_t::signed_integer)) {
414+
if (RawData.size == 1) {
415+
auto I = *reinterpret_cast<const int8_t *>(RawData.data);
416+
return std::to_string(I);
417+
}
418+
if (RawData.size == 2) {
419+
auto I = *reinterpret_cast<const int16_t *>(RawData.data);
420+
return std::to_string(I);
421+
}
422+
if (RawData.size == 4) {
423+
auto I = *reinterpret_cast<const int32_t *>(RawData.data);
424+
return std::to_string(I);
425+
}
426+
if (RawData.size == 8) {
427+
auto I = *reinterpret_cast<const int64_t *>(RawData.data);
428+
return std::to_string(I);
429+
}
430+
}
431+
432+
if (RawData.type == static_cast<uint8_t>(metadata_type_t::unsigned_integer)) {
433+
if (RawData.size == 1) {
434+
auto I = *reinterpret_cast<const uint8_t *>(RawData.data);
435+
return std::to_string(I);
436+
}
437+
if (RawData.size == 2) {
438+
auto I = *reinterpret_cast<const uint16_t *>(RawData.data);
439+
return std::to_string(I);
440+
}
441+
if (RawData.size == 4) {
442+
auto I = *reinterpret_cast<const uint32_t *>(RawData.data);
443+
return std::to_string(I);
444+
}
445+
if (RawData.size == 8) {
446+
auto I = *reinterpret_cast<const uint64_t *>(RawData.data);
447+
return std::to_string(I);
448+
}
449+
}
450+
451+
if (RawData.type == static_cast<uint8_t>(metadata_type_t::floating)) {
452+
if (RawData.size == 4) {
453+
auto F = *reinterpret_cast<const float *>(RawData.data);
454+
return std::to_string(F);
455+
}
456+
if (RawData.size == 8) {
457+
auto F = *reinterpret_cast<const double *>(RawData.data);
458+
return std::to_string(F);
459+
}
460+
}
461+
462+
if (RawData.type == static_cast<uint8_t>(metadata_type_t::string)) {
463+
return std::string(RawData.data, RawData.size);
464+
}
465+
466+
return std::string("Unknown metadata type, size ") +
467+
std::to_string(RawData.size);
468+
}
469+
309470
namespace framework {
310471
constexpr uint16_t signal = (uint16_t)xpti::trace_point_type_t::signal;
311472
constexpr uint16_t graph_create =

0 commit comments

Comments
 (0)