#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION) #pragma once #include #include #include #include #include namespace c10 { // Identifies a slot in ThreadLocalDebugInfo for storing a specific type // of thread-local state. // // This class is trivial to copy and move, and is cheap to construct and // destroy. // // Example: // // inline constexpr std::string_view kMyCustomInfoName = "MY_CUSTOM_INFO"; // inline const DebugInfoKind kMyCustomInfo(&kMyCustomInfoName); // ... // ThreadLocalDebugInfo::_push(kMyCustomInfo, my_custom_info_shared_ptr); // ... // const DebugInfoBase* info = ThreadLocalDebugInfo::get(kMyCustomInfo); // ... // ThreadLocalDebugInfo::_pop(kMyCustomInfo); class DebugInfoKind { private: // Must be a non-null pointer to a string_view literal with static storage // duration. using value_type = const std::string_view*; public: // Creates an uninitialized DebugInfoKind. constexpr DebugInfoKind() = default; // Creates a DebugInfoKind with the given identity, which must be a non-null // pointer to a string_view literal with static storage duration. The pointer // address (not the string itself) is used as the identifier for the slot. The // string itself is only used for debugging purposes and should be descriptive // of the slot's purpose and ideally (but not required) be unique. // // If called with a null value in a constexpr context, will trigger a compile // time error. If called with a null value in a non-constexpr context, will // trigger a runtime exception. explicit constexpr DebugInfoKind(value_type value) : value_(value) { if (value == nullptr) { // Since this function is not constexpr, it will trigger a compile-time // error if the DebugInfoKind() ctor is called in a constexpr context // with a null value. DebugInfoKind_ctor_parameter_must_not_be_null(); } } // Predefined DebugInfoKinds for common use cases. static C10_API const DebugInfoKind PRODUCER_INFO; static C10_API const DebugInfoKind MOBILE_RUNTIME_INFO; static C10_API const DebugInfoKind PROFILER_STATE; static C10_API const DebugInfoKind INFERENCE_CONTEXT; // for inference usage static C10_API const DebugInfoKind PARAM_COMMS_INFO; static C10_API const DebugInfoKind TEST_INFO; // used only in tests static C10_API const DebugInfoKind TEST_INFO_2; // used only in tests // Comparison operators. These allow putting DebugInfoKind in containers like // std::set and std::map. constexpr bool operator==(const DebugInfoKind other) const { return value_ == other.value_; } constexpr bool operator!=(const DebugInfoKind other) const { return value_ != other.value_; } constexpr bool operator<(const DebugInfoKind other) const { return value_ < other.value_; } C10_API friend std::ostream& operator<<( std::ostream& os, const DebugInfoKind& kind); private: // Doesn't compile in a constexpr context; throws in a non-constexpr context. // The function name is intentionally verbose to make the compiler error // more readable. [[noreturn]] static inline void DebugInfoKind_ctor_parameter_must_not_be_null() { TORCH_INTERNAL_ASSERT( false, "DebugInfoKind must be initialized with a non-null pointer."); } value_type value_ = nullptr; }; class C10_API DebugInfoBase { public: DebugInfoBase() = default; virtual ~DebugInfoBase() = default; }; // Thread local debug information is propagated across the forward // (including async fork tasks) and backward passes and is supposed // to be utilized by the user's code to pass extra information from // the higher layers (e.g. model id) down to the lower levels // (e.g. to the operator observers used for debugging, logging, // profiling, etc) class C10_API ThreadLocalDebugInfo { public: static DebugInfoBase* get(DebugInfoKind kind); // Get current ThreadLocalDebugInfo static std::shared_ptr current(); // Internal, use DebugInfoGuard/ThreadLocalStateGuard static void _forceCurrentDebugInfo( std::shared_ptr info); // Push debug info struct of a given kind static void _push(DebugInfoKind kind, std::shared_ptr info); // Pop debug info, throws in case the last pushed // debug info is not of a given kind static std::shared_ptr _pop(DebugInfoKind kind); // Peek debug info, throws in case the last pushed debug info is not of the // given kind static std::shared_ptr _peek(DebugInfoKind kind); private: std::shared_ptr info_; DebugInfoKind kind_; std::shared_ptr parent_info_; friend class DebugInfoGuard; }; // DebugInfoGuard is used to set debug information, // ThreadLocalDebugInfo is semantically immutable, the values are set // through the scope-based guard object. // Nested DebugInfoGuard adds/overrides existing values in the scope, // restoring the original values after exiting the scope. // Users can access the values through the ThreadLocalDebugInfo::get() call; class C10_API DebugInfoGuard { public: DebugInfoGuard(DebugInfoKind kind, std::shared_ptr info); explicit DebugInfoGuard(std::shared_ptr info); ~DebugInfoGuard(); DebugInfoGuard(const DebugInfoGuard&) = delete; DebugInfoGuard(DebugInfoGuard&&) = delete; DebugInfoGuard& operator=(const DebugInfoGuard&) = delete; DebugInfoGuard& operator=(DebugInfoGuard&&) = delete; private: bool active_ = false; std::shared_ptr prev_info_ = nullptr; }; } // namespace c10 #else #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined." #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)