28#include <unordered_map>
33#if __has_include(<nlohmann/json.hpp>)
34 #include "nlohmann/json.hpp"
41 unsigned long long start;
42 unsigned long long first_end;
43 unsigned long long last_end;
50#if __has_include(<nlohmann/json.hpp>)
52NLOHMANN_JSON_NAMESPACE_BEGIN
54struct adl_serializer<
sham::TimelineEvent> {
57 = {{
"start", e.start},
58 {
"first_end", e.first_end},
59 {
"last_end", e.last_end},
64NLOHMANN_JSON_NAMESPACE_END
80 sham::DeviceScheduler_ptr dev_sched;
89 const sham::DeviceScheduler_ptr &dev_sched,
u32 max_event_count)
90 : dev_sched(dev_sched), frame_start_clock(1, dev_sched),
91 events(max_event_count, dev_sched), event_count(1, dev_sched) {
92 event_count.set_val_at_idx(0, 0);
109 static std::unordered_map<DeviceScheduler *, bool> cache;
110 auto it = cache.find(dev_sched.get());
111 if (it == cache.end()) {
116 dev_sched->get_queue(),
121#if defined(SHAMROCK_INTRISICS_GET_DEVICE_CLOCK_AVAILABLE) \
122 && defined(SHAMROCK_INTRISICS_GET_SMID_AVAILABLE)
131 if (!cache[dev_sched.get()]) {
133 "Backend",
"gpu_core_timeline_profilier is not available on the device");
137 return cache[dev_sched.get()];
147 dev_sched->get_queue(),
152#ifdef SHAMROCK_INTRISICS_GET_DEVICE_CLOCK_AVAILABLE
153 *clock = sham::get_device_clock();
160 inline u64 get_base_clock_value() {
return frame_start_clock.
get_val_at_idx(0); }
162 struct local_access_t {
163 sycl::local_accessor<uint> _index;
164 sycl::local_accessor<bool> _valid;
166 local_access_t(sycl::handler &cgh) : _index(1, cgh), _valid(1, cgh) {}
193 if (item.get_local_id(0) == 0) {
196 sycl::memory_order_relaxed,
197 sycl::memory_scope_device,
198 sycl::access::address_space::global_space>
199 ev_cnt_ref(event_count[0]);
201 acc._index[0] = ev_cnt_ref.fetch_add(1_u64);
202 acc._valid[0] =
acc._index[0] < max_event_count;
205#ifdef SHAMROCK_INTRISICS_GET_SMID_AVAILABLE
206 events[
acc._index[0]]
233 sycl::memory_order_relaxed,
234 sycl::memory_scope_device,
235 sycl::access::address_space::global_space>
236 start_val(events[
acc._index[0]].start);
238 using ull =
unsigned long long;
240#ifdef SHAMROCK_INTRISICS_GET_DEVICE_CLOCK_AVAILABLE
246 start_val.fetch_min(clock);
262 sycl::memory_order_relaxed,
263 sycl::memory_scope_device,
264 sycl::access::address_space::global_space>
265 first_end(events[
acc._index[0]].first_end);
269 sycl::memory_order_relaxed,
270 sycl::memory_scope_device,
271 sycl::access::address_space::global_space>
272 last_end(events[
acc._index[0]].last_end);
274 using ull =
unsigned long long;
276#ifdef SHAMROCK_INTRISICS_GET_DEVICE_CLOCK_AVAILABLE
282 first_end.fetch_min(clock);
283 last_end.fetch_max(clock);
297 .events = events.get_write_access(deps),
298 .event_count = event_count.get_write_access(deps),
299 .max_event_count = events.get_size()};
310 events.complete_event_state(e);
311 event_count.complete_event_state(e);
314#if __has_include(<nlohmann/json.hpp>)
335 inline void dump_to_file(
const std::string &filename) {
339 std::cout <<
"dumping to " << filename <<
" size = " << sz << std::endl;
341 std::vector<TimelineEvent> events = this->events.copy_to_stdvec_idx_range(0, sz);
343 u64 base_clock = get_base_clock_value();
345 for (
auto &t : events) {
346 t.start -= base_clock;
347 t.first_end -= base_clock;
348 t.last_end -= base_clock;
351 std::ofstream file(filename);
352 file << nlohmann::json(events).dump(4) << std::endl;
void to_json(nlohmann::json &j, const PatchSchedulerConfig &p)
Converts a PatchSchedulerConfig object to a JSON object.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
A buffer allocated in USM (Unified Shared Memory).
T get_val_at_idx(size_t idx) const
Get the value at a given index in the buffer.
Class to manage a list of SYCL events.
void complete_event_state(sycl::event e)
void setFrameStartClock()
Recover the current device time in the frame_start_clock buffer.
gpu_core_timeline_profilier(const sham::DeviceScheduler_ptr &dev_sched, u32 max_event_count)
CTOR.
acc get_write_access(sham::EventList &deps)
Get a write access to the timeline events and the event count.
bool is_available_on_device()
Check if gpu_core_timeline_profilier is available on the device.
This file implement the GPU core timeline tool from A. Richermoz, F. Neyret 2024.
namespace for backends this one is named only sham since shambackends is too long to write
u32 get_sm_id()
Return the SM (Streaming Multiprocessor) ID of the calling thread, or equivalent if implemented.
void kernel_call(sham::DeviceQueue &q, RefIn in, RefOut in_out, u32 n, Functor &&func, SourceLocation &&callsite=SourceLocation{})
Submit a kernel to a SYCL queue.
u64 get_device_clock()
Return the number of clock cycles elapsed since an arbitrary starting point on the device.
constexpr u64 u64_max
u64 max value
void warn_ln(std::string module_name, Types... var2)
Prints a log message with multiple arguments followed by a newline.
A class that references multiple buffers or similar objects.
A timeline event for the gpu core timeline.
void start_timeline_event(const local_access_t &acc) const
Start a timeline event.
void init_timeline_event(sycl::nd_item< 1 > item, const local_access_t &acc) const
Initialize a timeline event.
void end_timeline_event(const local_access_t &acc) const
Finish a timeline event.