:github_url: https://github.com/pytorch/pytorch .. _program_listing_file_c10_core_Device.h: Program Listing for File Device.h ================================= |exhale_lsh| :ref:`Return to documentation for file ` (``c10/core/Device.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include #include #include #include #include #include #include #include namespace c10 { using DeviceIndex = int8_t; struct C10_API Device final { using Type = DeviceType; /* implicit */ Device(DeviceType type, DeviceIndex index = -1) : type_(type), index_(index) { validate(); } /* implicit */ Device(const std::string& device_string); bool operator==(const Device& other) const noexcept { return this->type_ == other.type_ && this->index_ == other.index_; } bool operator!=(const Device& other) const noexcept { return !(*this == other); } void set_index(DeviceIndex index) { index_ = index; } DeviceType type() const noexcept { return type_; } DeviceIndex index() const noexcept { return index_; } bool has_index() const noexcept { return index_ != -1; } bool is_cuda() const noexcept { return type_ == DeviceType::CUDA; } bool is_privateuseone() const noexcept { return type_ == DeviceType::PrivateUse1; } bool is_mps() const noexcept { return type_ == DeviceType::MPS; } bool is_hip() const noexcept { return type_ == DeviceType::HIP; } bool is_ve() const noexcept { return type_ == DeviceType::VE; } bool is_xpu() const noexcept { return type_ == DeviceType::XPU; } bool is_ipu() const noexcept { return type_ == DeviceType::IPU; } bool is_xla() const noexcept { return type_ == DeviceType::XLA; } bool is_mtia() const noexcept { return type_ == DeviceType::MTIA; } bool is_hpu() const noexcept { return type_ == DeviceType::HPU; } bool is_lazy() const noexcept { return type_ == DeviceType::Lazy; } bool is_vulkan() const noexcept { return type_ == DeviceType::Vulkan; } bool is_metal() const noexcept { return type_ == DeviceType::Metal; } bool is_maia() const noexcept { return type_ == DeviceType::MAIA; } bool is_meta() const noexcept { return type_ == DeviceType::Meta; } bool is_cpu() const noexcept { return type_ == DeviceType::CPU; } bool supports_as_strided() const noexcept { return type_ != DeviceType::IPU && type_ != DeviceType::XLA && type_ != DeviceType::Lazy; } std::string str() const; private: DeviceType type_; DeviceIndex index_ = -1; void validate() { // Removing these checks in release builds noticeably improves // performance in micro-benchmarks. // This is safe to do, because backends that use the DeviceIndex // have a later check when we actually try to switch to that device. TORCH_INTERNAL_ASSERT_DEBUG_ONLY( index_ >= -1, "Device index must be -1 or non-negative, got ", static_cast(index_)); TORCH_INTERNAL_ASSERT_DEBUG_ONLY( !is_cpu() || index_ <= 0, "CPU device index must be -1 or zero, got ", static_cast(index_)); } }; C10_API std::ostream& operator<<(std::ostream& stream, const Device& device); } // namespace c10 namespace std { template <> struct hash { size_t operator()(c10::Device d) const noexcept { // Are you here because this static assert failed? Make sure you ensure // that the bitmasking code below is updated accordingly! static_assert(sizeof(c10::DeviceType) == 1, "DeviceType is not 8-bit"); static_assert(sizeof(c10::DeviceIndex) == 1, "DeviceIndex is not 8-bit"); // Note [Hazard when concatenating signed integers] // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // We must first convert to a same-sized unsigned type, before promoting to // the result type, to prevent sign extension when any of the values is -1. // If sign extension occurs, you'll clobber all of the values in the MSB // half of the resulting integer. // // Technically, by C/C++ integer promotion rules, we only need one of the // uint32_t casts to the result type, but we put in both for explicitness's // sake. uint32_t bits = static_cast(static_cast(d.type())) << 16 | static_cast(static_cast(d.index())); return std::hash{}(bits); } }; } // namespace std