#pragma once #include #include #include #include #include #include #include #include namespace torch::profiler::impl { class RecordQueue; struct Result; namespace python_tracer { using TraceKey = strong::type< uint64_t, struct TraceKey_, strong::regular, strong::hashable, strong::ostreamable>; struct CompressedEvent { TraceKey key_; uint64_t system_tid_{}; kineto::DeviceAndResource kineto_info_{}; c10::time_t enter_t_{}; }; /* Libtorch does not depend on Python (e.g. cannot #include ); however when we call the profiler from libtorch_python we need the profiler to be able to ingest the data that we collect from the Python tracer. (`PyEval_SetProfile`) In order to solve this dependency issue we define a virtual base and a function to register a getter. The python tracer then implements these functions and exposes itself by calling `registerTracer` from `torch/csrc/autograd/init.cpp`. This pattern of registration for faux python dependencies in libtorch is common in the PyTorch codebase. */ struct TORCH_API PythonTracerBase { static std::unique_ptr make(RecordQueue* queue); virtual ~PythonTracerBase() = default; virtual void stop() = 0; virtual void restart() = 0; virtual std::vector> getEvents( std::function time_converter, std::vector& enters, c10::time_t end_time_ns) = 0; }; using MakeFn = std::unique_ptr (*)(RecordQueue*); TORCH_API void registerTracer(MakeFn make_tracer); /** * Memory Tracer Implementation */ struct TORCH_API PythonMemoryTracerBase { static std::unique_ptr make(); virtual ~PythonMemoryTracerBase() = default; virtual void start() = 0; virtual void stop() = 0; virtual void export_memory_history(const std::string& path) = 0; }; using MakeMemoryFn = std::unique_ptr (*)(); TORCH_API void registerMemoryTracer(MakeMemoryFn make_memory_tracer); } // namespace python_tracer } // namespace torch::profiler::impl