mirror of
https://github.com/pytorch/pytorch.git
synced 2025-10-20 21:14:14 +08:00
Add uuid to XPU device properties (#161392)
# Motivation Fix https://github.com/intel/torch-xpu-ops/issues/1955 Refer to https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/supported/sycl_ext_intel_device_info.md#device-uuid, `ext::intel::info::device::uuid` returns `std::array<unsigned char, 16>` as the UUID. Pull Request resolved: https://github.com/pytorch/pytorch/pull/161392 Approved by: https://github.com/EikanWang, https://github.com/albanD
This commit is contained in:
committed by
PyTorch MergeBot
parent
8703debf66
commit
f8746b878d
@ -115,19 +115,22 @@ namespace c10::xpu {
|
|||||||
|
|
||||||
#define AT_FORALL_XPU_EXT_DEVICE_PROPERTIES(_) \
|
#define AT_FORALL_XPU_EXT_DEVICE_PROPERTIES(_) \
|
||||||
/* the number of EUs associated with the Intel GPU. */ \
|
/* the number of EUs associated with the Intel GPU. */ \
|
||||||
_(gpu_eu_count, 512) \
|
_(gpu_eu_count, gpu_eu_count, 512) \
|
||||||
\
|
\
|
||||||
/* the number of EUs in a subslice. */ \
|
/* the number of EUs in a subslice. */ \
|
||||||
_(gpu_eu_count_per_subslice, 8) \
|
_(gpu_eu_count_per_subslice, gpu_eu_count_per_subslice, 8) \
|
||||||
\
|
\
|
||||||
/* the simd width of EU of GPU. */ \
|
/* the simd width of EU of GPU. */ \
|
||||||
_(gpu_eu_simd_width, 8) \
|
_(gpu_eu_simd_width, gpu_eu_simd_width, 8) \
|
||||||
\
|
\
|
||||||
/* the number of hardware threads per EU of GPU. */ \
|
/* the number of hardware threads per EU of GPU. */ \
|
||||||
_(gpu_hw_threads_per_eu, 8) \
|
_(gpu_hw_threads_per_eu, gpu_hw_threads_per_eu, 8) \
|
||||||
\
|
\
|
||||||
/* the device identifier of the Intel GPU, also known as the product ID. */ \
|
/* the device identifier of the Intel GPU, also known as the product ID. */ \
|
||||||
_(device_id, 0)
|
_(device_id, device_id, 0) \
|
||||||
|
\
|
||||||
|
/* the device descriptor for device Universal Unique ID, 16 bytes*/ \
|
||||||
|
_(uuid, device_info_uuid, (std::array<unsigned char, 16>{}))
|
||||||
|
|
||||||
#define AT_FORALL_XPU_DEVICE_ASPECT(_) \
|
#define AT_FORALL_XPU_DEVICE_ASPECT(_) \
|
||||||
/* sycl::half is supported on device. */ \
|
/* sycl::half is supported on device. */ \
|
||||||
|
@ -157,8 +157,8 @@ void initDeviceProperties(DeviceProp* device_prop, DeviceIndex device) {
|
|||||||
#define ASSIGN_DEVICE_PROP(property) \
|
#define ASSIGN_DEVICE_PROP(property) \
|
||||||
device_prop->property = raw_device.get_info<device::property>();
|
device_prop->property = raw_device.get_info<device::property>();
|
||||||
|
|
||||||
#define ASSIGN_EXT_DEVICE_PROP(property, default_value) \
|
#define ASSIGN_EXT_DEVICE_PROP(property, aspect_tag, default_value) \
|
||||||
device_prop->property = raw_device.has(sycl::aspect::ext_intel_##property) \
|
device_prop->property = raw_device.has(sycl::aspect::ext_intel_##aspect_tag) \
|
||||||
? raw_device.get_info<intel::info::device::property>() \
|
? raw_device.get_info<intel::info::device::property>() \
|
||||||
: default_value;
|
: default_value;
|
||||||
|
|
||||||
|
@ -134,6 +134,10 @@ class TestXpu(TestCase):
|
|||||||
device_properties.architecture,
|
device_properties.architecture,
|
||||||
device_capability["architecture"],
|
device_capability["architecture"],
|
||||||
)
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
len(str(device_properties.uuid)), 36
|
||||||
|
) # xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
|
self.assertEqual(len(device_properties.uuid.bytes), 16)
|
||||||
|
|
||||||
@unittest.skipIf(IS_WINDOWS, "not applicable to Windows (only fails with fork)")
|
@unittest.skipIf(IS_WINDOWS, "not applicable to Windows (only fails with fork)")
|
||||||
def test_wrong_xpu_fork(self):
|
def test_wrong_xpu_fork(self):
|
||||||
|
@ -2389,6 +2389,7 @@ class _XpuDeviceProperties:
|
|||||||
gpu_subslice_count: _int
|
gpu_subslice_count: _int
|
||||||
architecture: _int
|
architecture: _int
|
||||||
type: str
|
type: str
|
||||||
|
uuid: Any
|
||||||
|
|
||||||
# Defined in torch/csrc/xpu/Stream.cpp
|
# Defined in torch/csrc/xpu/Stream.cpp
|
||||||
class _XpuStreamBase(Stream):
|
class _XpuStreamBase(Stream):
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <c10/core/Device.h>
|
#include <c10/core/Device.h>
|
||||||
#include <c10/core/TensorImpl.h>
|
#include <c10/core/TensorImpl.h>
|
||||||
#include <c10/util/UniqueVoidPtr.h>
|
#include <c10/util/UniqueVoidPtr.h>
|
||||||
#include <fmt/core.h>
|
|
||||||
#include <pybind11/pytypes.h>
|
#include <pybind11/pytypes.h>
|
||||||
#include <torch/csrc/utils/python_arg_parser.h>
|
#include <torch/csrc/utils/python_arg_parser.h>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
@ -1017,34 +1016,6 @@ PyObject* THCPModule_cudaGetSyncDebugMode(PyObject* self, PyObject* noargs) {
|
|||||||
END_HANDLE_TH_ERRORS
|
END_HANDLE_TH_ERRORS
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string uuid_to_string(const char* uuid_bytes) {
|
|
||||||
// UUIDs are a 128-bit label. CUDA and HIP store this as char[16].
|
|
||||||
// For string representation, the code here expands this to
|
|
||||||
// 8-4-4-4-12 hex format, so each byte becomes 2 hex characters.
|
|
||||||
return fmt::format(
|
|
||||||
"{:02x}{:02x}{:02x}{:02x}-"
|
|
||||||
"{:02x}{:02x}-"
|
|
||||||
"{:02x}{:02x}-"
|
|
||||||
"{:02x}{:02x}-"
|
|
||||||
"{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
|
|
||||||
(uint8_t)uuid_bytes[0],
|
|
||||||
(uint8_t)uuid_bytes[1],
|
|
||||||
(uint8_t)uuid_bytes[2],
|
|
||||||
(uint8_t)uuid_bytes[3],
|
|
||||||
(uint8_t)uuid_bytes[4],
|
|
||||||
(uint8_t)uuid_bytes[5],
|
|
||||||
(uint8_t)uuid_bytes[6],
|
|
||||||
(uint8_t)uuid_bytes[7],
|
|
||||||
(uint8_t)uuid_bytes[8],
|
|
||||||
(uint8_t)uuid_bytes[9],
|
|
||||||
(uint8_t)uuid_bytes[10],
|
|
||||||
(uint8_t)uuid_bytes[11],
|
|
||||||
(uint8_t)uuid_bytes[12],
|
|
||||||
(uint8_t)uuid_bytes[13],
|
|
||||||
(uint8_t)uuid_bytes[14],
|
|
||||||
(uint8_t)uuid_bytes[15]);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Cuda module initialization
|
// Cuda module initialization
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -240,6 +240,34 @@ uint8_t storage_get(const at::Storage& self, ptrdiff_t idx) {
|
|||||||
return self_t[idx].item<uint8_t>();
|
return self_t[idx].item<uint8_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string uuid_to_string(const char* uuid_bytes) {
|
||||||
|
// UUIDs are a 128-bit label. CUDA/HIP and XPU store this as char[16].
|
||||||
|
// For string representation, the code here expands this to
|
||||||
|
// 8-4-4-4-12 hex format, so each byte becomes 2 hex characters.
|
||||||
|
return fmt::format(
|
||||||
|
"{:02x}{:02x}{:02x}{:02x}-"
|
||||||
|
"{:02x}{:02x}-"
|
||||||
|
"{:02x}{:02x}-"
|
||||||
|
"{:02x}{:02x}-"
|
||||||
|
"{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
|
||||||
|
(uint8_t)uuid_bytes[0],
|
||||||
|
(uint8_t)uuid_bytes[1],
|
||||||
|
(uint8_t)uuid_bytes[2],
|
||||||
|
(uint8_t)uuid_bytes[3],
|
||||||
|
(uint8_t)uuid_bytes[4],
|
||||||
|
(uint8_t)uuid_bytes[5],
|
||||||
|
(uint8_t)uuid_bytes[6],
|
||||||
|
(uint8_t)uuid_bytes[7],
|
||||||
|
(uint8_t)uuid_bytes[8],
|
||||||
|
(uint8_t)uuid_bytes[9],
|
||||||
|
(uint8_t)uuid_bytes[10],
|
||||||
|
(uint8_t)uuid_bytes[11],
|
||||||
|
(uint8_t)uuid_bytes[12],
|
||||||
|
(uint8_t)uuid_bytes[13],
|
||||||
|
(uint8_t)uuid_bytes[14],
|
||||||
|
(uint8_t)uuid_bytes[15]);
|
||||||
|
}
|
||||||
|
|
||||||
template class THPPointer<THPStorage>;
|
template class THPPointer<THPStorage>;
|
||||||
// NOLINTBEGIN(misc-use-internal-linkage)
|
// NOLINTBEGIN(misc-use-internal-linkage)
|
||||||
namespace torch::gdb {
|
namespace torch::gdb {
|
||||||
|
@ -201,3 +201,5 @@ bool maybeThrowBackCompatKeepdimWarn(char* func);
|
|||||||
void storage_fill(const at::Storage& self, uint8_t value);
|
void storage_fill(const at::Storage& self, uint8_t value);
|
||||||
void storage_set(const at::Storage& self, ptrdiff_t idx, uint8_t value);
|
void storage_set(const at::Storage& self, ptrdiff_t idx, uint8_t value);
|
||||||
uint8_t storage_get(const at::Storage& self, ptrdiff_t idx);
|
uint8_t storage_get(const at::Storage& self, ptrdiff_t idx);
|
||||||
|
|
||||||
|
std::string uuid_to_string(const char* uuid_bytes);
|
||||||
|
@ -295,8 +295,23 @@ static void registerXpuDeviceProperties(PyObject* module) {
|
|||||||
return static_cast<int64_t>(prop.architecture);
|
return static_cast<int64_t>(prop.architecture);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
// Wrapper class for XPU UUID
|
||||||
|
struct XPUuuid {
|
||||||
|
XPUuuid(const std::array<unsigned char, 16>& uuid) : bytes(uuid) {}
|
||||||
|
const std::array<unsigned char, 16>& bytes{};
|
||||||
|
};
|
||||||
auto m = py::handle(module).cast<py::module>();
|
auto m = py::handle(module).cast<py::module>();
|
||||||
|
|
||||||
|
py::class_<XPUuuid>(m, "_XPUuuid")
|
||||||
|
.def_property_readonly(
|
||||||
|
"bytes",
|
||||||
|
[](const XPUuuid& uuid) {
|
||||||
|
return std::vector<uint8_t>(uuid.bytes.begin(), uuid.bytes.end());
|
||||||
|
})
|
||||||
|
.def("__str__", [](const XPUuuid& uuid) {
|
||||||
|
return uuid_to_string(reinterpret_cast<const char*>(uuid.bytes.data()));
|
||||||
|
});
|
||||||
|
|
||||||
#define DEFINE_READONLY_MEMBER(member) \
|
#define DEFINE_READONLY_MEMBER(member) \
|
||||||
def_readonly(#member, &DeviceProp::member)
|
def_readonly(#member, &DeviceProp::member)
|
||||||
|
|
||||||
@ -328,6 +343,9 @@ static void registerXpuDeviceProperties(PyObject* module) {
|
|||||||
.def_property_readonly("architecture", get_device_architecture)
|
.def_property_readonly("architecture", get_device_architecture)
|
||||||
#endif
|
#endif
|
||||||
.def_property_readonly("type", get_device_type)
|
.def_property_readonly("type", get_device_type)
|
||||||
|
.def_property_readonly(
|
||||||
|
"uuid",
|
||||||
|
[](const DeviceProp& prop) -> XPUuuid { return XPUuuid(prop.uuid); })
|
||||||
.def(
|
.def(
|
||||||
"__repr__",
|
"__repr__",
|
||||||
[&get_device_type, &gpu_subslice_count](const DeviceProp& prop) {
|
[&get_device_type, &gpu_subslice_count](const DeviceProp& prop) {
|
||||||
@ -335,7 +353,9 @@ static void registerXpuDeviceProperties(PyObject* module) {
|
|||||||
stream << "_XpuDeviceProperties(name='" << prop.name
|
stream << "_XpuDeviceProperties(name='" << prop.name
|
||||||
<< "', platform_name='" << prop.platform_name << "', type='"
|
<< "', platform_name='" << prop.platform_name << "', type='"
|
||||||
<< get_device_type(prop) << "', device_id=0x" << std::hex
|
<< get_device_type(prop) << "', device_id=0x" << std::hex
|
||||||
<< std::uppercase << prop.device_id << std::dec
|
<< std::uppercase << prop.device_id << std::dec << ", uuid="
|
||||||
|
<< uuid_to_string(
|
||||||
|
reinterpret_cast<const char*>(prop.uuid.data()))
|
||||||
<< ", driver_version='" << prop.driver_version
|
<< ", driver_version='" << prop.driver_version
|
||||||
<< "', total_memory="
|
<< "', total_memory="
|
||||||
<< prop.global_mem_size / (1024ull * 1024) << "MB"
|
<< prop.global_mem_size / (1024ull * 1024) << "MB"
|
||||||
|
@ -236,15 +236,13 @@ def get_device_capability(device: Optional[_device_t] = None) -> dict[str, Any]:
|
|||||||
Dict[str, Any]: the xpu capability dictionary of the device
|
Dict[str, Any]: the xpu capability dictionary of the device
|
||||||
"""
|
"""
|
||||||
props = get_device_properties(device)
|
props = get_device_properties(device)
|
||||||
# pybind service attributes are no longer needed and their presence breaks
|
# Only keep attributes that are safe for dictionary serialization.
|
||||||
# the further logic related to the serialization of the created dictionary.
|
serializable_types = (int, float, bool, str, type(None), list, tuple, dict)
|
||||||
# In particular it filters out `<bound method PyCapsule._pybind11_conduit_v1_ of _XpuDeviceProperties..>`
|
|
||||||
# to fix Triton tests.
|
|
||||||
# This field appears after updating pybind to 2.13.6.
|
|
||||||
return {
|
return {
|
||||||
prop: getattr(props, prop)
|
key: value
|
||||||
for prop in dir(props)
|
for key in dir(props)
|
||||||
if not prop.startswith(("__", "_pybind11_"))
|
if not key.startswith("__")
|
||||||
|
and isinstance((value := getattr(props, key)), serializable_types)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user