Initial import: grid-bot — grid trading bot for BTC-USDT on Cifra Markets
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#pragma once
|
||||
|
||||
#include <c10/core/Device.h>
|
||||
#include <c10/macros/Macros.h>
|
||||
#include <c10/xpu/XPUMacros.h>
|
||||
|
||||
namespace c10::xpu {
|
||||
namespace detail {
|
||||
// Initialize the peer-to-peer access cache for XPU devices.
|
||||
C10_XPU_API void init_p2p_access_cache(c10::DeviceIndex num_devices);
|
||||
} // namespace detail
|
||||
|
||||
// Query if peer-to-peer access is available between two devices.
|
||||
C10_XPU_API bool get_p2p_access(
|
||||
c10::DeviceIndex dev,
|
||||
c10::DeviceIndex dev_to_access);
|
||||
|
||||
} // namespace c10::xpu
|
||||
|
||||
#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)
|
||||
@@ -0,0 +1,142 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#pragma once
|
||||
|
||||
#include <c10/core/AllocatorConfig.h>
|
||||
#include <c10/core/CachingDeviceAllocator.h>
|
||||
#include <c10/xpu/XPUStream.h>
|
||||
|
||||
namespace c10::xpu::XPUCachingAllocator {
|
||||
|
||||
class XPUAllocator : public DeviceAllocator {
|
||||
public:
|
||||
virtual void init(c10::DeviceIndex device_count) = 0;
|
||||
virtual void* raw_alloc(size_t size) = 0;
|
||||
virtual void raw_delete(void* ptr) = 0;
|
||||
};
|
||||
|
||||
C10_XPU_API extern std::atomic<XPUAllocator*> allocator;
|
||||
|
||||
struct AllocatorConfigInfo {
|
||||
bool expandable_segments;
|
||||
std::string last_allocator_settings;
|
||||
};
|
||||
|
||||
struct SnapshotInfo {
|
||||
std::vector<CachingDeviceAllocator::SegmentInfo> segments;
|
||||
std::vector<std::vector<CachingDeviceAllocator::TraceEntry>> device_traces;
|
||||
AllocatorConfigInfo config_metadata;
|
||||
};
|
||||
|
||||
inline XPUAllocator* get() {
|
||||
return allocator.load();
|
||||
}
|
||||
|
||||
inline void init(c10::DeviceIndex device_count) {
|
||||
get()->init(device_count);
|
||||
}
|
||||
|
||||
inline void emptyCache(MempoolId_t mempool_id = {0, 0}) {
|
||||
get()->emptyCache(mempool_id);
|
||||
}
|
||||
|
||||
inline void resetPeakStats(DeviceIndex device) {
|
||||
get()->resetPeakStats(device);
|
||||
}
|
||||
|
||||
inline void resetAccumulatedStats(DeviceIndex device) {
|
||||
get()->resetAccumulatedStats(device);
|
||||
}
|
||||
|
||||
inline c10::CachingDeviceAllocator::DeviceStats getDeviceStats(
|
||||
DeviceIndex device) {
|
||||
return get()->getDeviceStats(device);
|
||||
}
|
||||
|
||||
inline void* raw_alloc(size_t size) {
|
||||
return get()->raw_alloc(size);
|
||||
}
|
||||
|
||||
inline void raw_delete(void* ptr) {
|
||||
get()->raw_delete(ptr);
|
||||
}
|
||||
|
||||
inline void recordStream(const DataPtr& dataPtr, XPUStream stream) {
|
||||
get()->recordStream(dataPtr, stream);
|
||||
}
|
||||
|
||||
C10_XPU_API void enablePeerAccess(
|
||||
c10::DeviceIndex dev,
|
||||
c10::DeviceIndex dev_to_access);
|
||||
|
||||
C10_XPU_API double getMemoryFraction(DeviceIndex device);
|
||||
|
||||
C10_XPU_API void setMemoryFraction(double fraction, DeviceIndex device);
|
||||
|
||||
C10_XPU_API void recordHistory(
|
||||
bool enabled,
|
||||
CachingDeviceAllocator::CreateContextFn context_recorder,
|
||||
size_t alloc_trace_max_entries,
|
||||
CachingDeviceAllocator::RecordContext when,
|
||||
bool clearHistory,
|
||||
const std::vector<std::string>& skip_actions);
|
||||
|
||||
C10_XPU_API SnapshotInfo snapshot(MempoolId_t mempool_id = {0, 0});
|
||||
|
||||
C10_XPU_API void createOrIncrefPool(
|
||||
c10::DeviceIndex device,
|
||||
c10::MempoolId_t mempool_id,
|
||||
XPUAllocator* allocator = nullptr);
|
||||
|
||||
C10_XPU_API void beginAllocateToPool(
|
||||
c10::DeviceIndex device,
|
||||
c10::MempoolId_t mempool_id,
|
||||
std::function<bool(sycl::queue*)> filter);
|
||||
|
||||
C10_XPU_API void endAllocateToPool(
|
||||
c10::DeviceIndex device,
|
||||
c10::MempoolId_t mempool_id);
|
||||
|
||||
C10_XPU_API void releasePool(
|
||||
c10::DeviceIndex device,
|
||||
c10::MempoolId_t mempool_id);
|
||||
|
||||
C10_XPU_API int getPoolUseCount(
|
||||
c10::DeviceIndex device,
|
||||
c10::MempoolId_t mempool_id);
|
||||
|
||||
} // namespace c10::xpu::XPUCachingAllocator
|
||||
|
||||
namespace c10::xpu {
|
||||
|
||||
using c10::CaptureId_t;
|
||||
using c10::MempoolId_t;
|
||||
struct C10_XPU_API MemPool {
|
||||
MemPool(
|
||||
XPUCachingAllocator::XPUAllocator* allocator = nullptr,
|
||||
bool is_user_created = true,
|
||||
bool use_on_oom = false);
|
||||
MemPool(const MemPool&) = delete;
|
||||
MemPool(MemPool&&) = default;
|
||||
MemPool& operator=(const MemPool&) = delete;
|
||||
MemPool& operator=(MemPool&&) = default;
|
||||
~MemPool();
|
||||
|
||||
MempoolId_t id();
|
||||
XPUCachingAllocator::XPUAllocator* allocator();
|
||||
int use_count();
|
||||
c10::DeviceIndex device();
|
||||
static MempoolId_t graph_pool_handle(bool is_user_created = true);
|
||||
|
||||
private:
|
||||
static std::atomic<CaptureId_t> uid_;
|
||||
static std::atomic<CaptureId_t> uuid_;
|
||||
XPUCachingAllocator::XPUAllocator* allocator_;
|
||||
bool is_user_created_;
|
||||
MempoolId_t id_;
|
||||
c10::DeviceIndex device_;
|
||||
};
|
||||
} // namespace c10::xpu
|
||||
|
||||
#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)
|
||||
@@ -0,0 +1,222 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#pragma once
|
||||
|
||||
#include <c10/xpu/XPUMacros.h>
|
||||
#include <sycl/sycl.hpp>
|
||||
|
||||
namespace c10::xpu {
|
||||
|
||||
#define AT_FORALL_XPU_DEVICE_PROPERTIES(_) \
|
||||
/* the device name of this SYCL device. */ \
|
||||
_(name) \
|
||||
\
|
||||
/* the device type associated with the device. */ \
|
||||
_(device_type) \
|
||||
\
|
||||
/* the vendor of this SYCL device. */ \
|
||||
_(vendor) \
|
||||
\
|
||||
/* a backend-defined driver version as a std::string. */ \
|
||||
_(driver_version) \
|
||||
\
|
||||
/* the SYCL version as a std::string in the form <major>.<minor> */ \
|
||||
_(version) \
|
||||
\
|
||||
/* true if the SYCL device is available. Otherwise, return false. */ \
|
||||
_(is_available) \
|
||||
\
|
||||
/* the maximum size in bytes of the arguments that can be passed to a \
|
||||
* kernel. */ \
|
||||
_(max_parameter_size) \
|
||||
\
|
||||
/* the number of parallel compute units available to the device. */ \
|
||||
_(max_compute_units) \
|
||||
\
|
||||
/* the maximum dimensions that specify the global and local work-item IDs \
|
||||
* used by the data parallel execution model. */ \
|
||||
_(max_work_item_dimensions) \
|
||||
\
|
||||
/* the maximum number of workitems that are permitted in a work-group \
|
||||
* executing a kernel on a single compute unit. */ \
|
||||
_(max_work_group_size) \
|
||||
\
|
||||
/* the maximum number of subgroups in a work-group for any kernel executed \
|
||||
* on the device. */ \
|
||||
_(max_num_sub_groups) \
|
||||
\
|
||||
/* a std::vector of size_t containing the set of sub-group sizes supported \
|
||||
* by the device. */ \
|
||||
_(sub_group_sizes) \
|
||||
\
|
||||
/* the maximum configured clock frequency of this SYCL device in MHz. */ \
|
||||
_(max_clock_frequency) \
|
||||
\
|
||||
/* the default compute device address space size specified as an unsigned \
|
||||
* integer value in bits. Must return either 32 or 64. */ \
|
||||
_(address_bits) \
|
||||
\
|
||||
/* the maximum size of memory object allocation in bytes. */ \
|
||||
_(max_mem_alloc_size) \
|
||||
\
|
||||
/* the minimum value in bits of the largest supported SYCL built-in data \
|
||||
* type if this SYCL device is not of device type \
|
||||
* sycl::info::device_type::custom. */ \
|
||||
_(mem_base_addr_align) \
|
||||
\
|
||||
/* a std::vector of info::fp_config describing the half/single/double \
|
||||
* precision floating-point capability of this SYCL device. */ \
|
||||
_(half_fp_config) \
|
||||
_(single_fp_config) \
|
||||
_(double_fp_config) \
|
||||
\
|
||||
/* the size of global device memory in bytes. */ \
|
||||
_(global_mem_size) \
|
||||
\
|
||||
/* the type of global memory cache supported. */ \
|
||||
_(global_mem_cache_type) \
|
||||
\
|
||||
/* the size of global memory cache in bytes. */ \
|
||||
_(global_mem_cache_size) \
|
||||
\
|
||||
/* the size of global memory cache line in bytes. */ \
|
||||
_(global_mem_cache_line_size) \
|
||||
\
|
||||
/* the type of local memory supported. */ \
|
||||
_(local_mem_type) \
|
||||
\
|
||||
/* the size of local memory arena in bytes. */ \
|
||||
_(local_mem_size) \
|
||||
\
|
||||
/* the maximum number of sub-devices that can be created when this device is \
|
||||
* partitioned. */ \
|
||||
_(partition_max_sub_devices) \
|
||||
\
|
||||
/* the resolution of device timer in nanoseconds. */ \
|
||||
_(profiling_timer_resolution) \
|
||||
\
|
||||
/* the preferred native vector width size for built-in scalar types that can \
|
||||
* be put into vectors. */ \
|
||||
_(preferred_vector_width_char) \
|
||||
_(preferred_vector_width_short) \
|
||||
_(preferred_vector_width_int) \
|
||||
_(preferred_vector_width_long) \
|
||||
_(preferred_vector_width_float) \
|
||||
_(preferred_vector_width_double) \
|
||||
_(preferred_vector_width_half) \
|
||||
\
|
||||
/* the native ISA vector width. The vector width is defined as the number of \
|
||||
* scalar elements that can be stored in the vector. */ \
|
||||
_(native_vector_width_char) \
|
||||
_(native_vector_width_short) \
|
||||
_(native_vector_width_int) \
|
||||
_(native_vector_width_long) \
|
||||
_(native_vector_width_float) \
|
||||
_(native_vector_width_double) \
|
||||
_(native_vector_width_half)
|
||||
|
||||
#define AT_FORALL_XPU_EXT_DEVICE_PROPERTIES(_) \
|
||||
/* the number of EUs associated with the Intel GPU. */ \
|
||||
_(gpu_eu_count, gpu_eu_count, 512) \
|
||||
\
|
||||
/* the number of EUs in a subslice. */ \
|
||||
_(gpu_eu_count_per_subslice, gpu_eu_count_per_subslice, 8) \
|
||||
\
|
||||
/* the simd width of EU of GPU. */ \
|
||||
_(gpu_eu_simd_width, gpu_eu_simd_width, 8) \
|
||||
\
|
||||
/* the number of hardware threads per EU of GPU. */ \
|
||||
_(gpu_hw_threads_per_eu, gpu_hw_threads_per_eu, 8) \
|
||||
\
|
||||
/* the device identifier of the Intel GPU, also known as the product ID. */ \
|
||||
_(device_id, device_id, 0) \
|
||||
\
|
||||
/* the device descriptor for device Universal Unique ID, 16 bytes. */ \
|
||||
_(uuid, device_info_uuid, (std::array<unsigned char, 16>{})) \
|
||||
\
|
||||
/* the maximum clock rate of device's global memory in MHz. */ \
|
||||
_(memory_clock_rate, memory_clock_rate, 0) \
|
||||
\
|
||||
/* the maximum bus width between device and memory in bits. */ \
|
||||
_(memory_bus_width, memory_bus_width, 0)
|
||||
|
||||
#define AT_FORALL_XPU_DEVICE_ASPECT(_) \
|
||||
/* sycl::half is supported on device. */ \
|
||||
_(fp16) \
|
||||
\
|
||||
/* double is supported on device. */ \
|
||||
_(fp64) \
|
||||
\
|
||||
/* 64-bit atomic operation is supported on device. */ \
|
||||
_(atomic64)
|
||||
|
||||
#define AT_FORALL_XPU_EXP_CL_ASPECT(_) \
|
||||
/* conversion between single-precision 32-bit floating-point values and \
|
||||
* 16-bit bfloat16 values is supported on device. */ \
|
||||
_(bfloat16_conversions) \
|
||||
\
|
||||
/* specialized hardware to compute MMA is supported on device. */ \
|
||||
_(subgroup_matrix_multiply_accumulate) \
|
||||
\
|
||||
/* specialized hardware to compute MMA for 32-bit floating-point is \
|
||||
* supported on device. */ \
|
||||
_(subgroup_matrix_multiply_accumulate_tensor_float32) \
|
||||
\
|
||||
/* block read operations for efficient matrix multiplication is supported on \
|
||||
* device. */ \
|
||||
_(subgroup_2d_block_io)
|
||||
|
||||
#define AT_FORALL_XPU_EXP_DEVICE_PROPERTIES(_) \
|
||||
/* the device architecture of this SYCL device. */ \
|
||||
_(architecture)
|
||||
|
||||
#define _DEFINE_SYCL_PROP(ns, property, member) \
|
||||
ns::property::return_type member;
|
||||
|
||||
#define DEFINE_DEVICE_PROP(property) \
|
||||
_DEFINE_SYCL_PROP(sycl::info::device, property, property)
|
||||
|
||||
#define DEFINE_PLATFORM_PROP(property, member) \
|
||||
_DEFINE_SYCL_PROP(sycl::info::platform, property, member)
|
||||
|
||||
#define DEFINE_EXT_DEVICE_PROP(property, ...) \
|
||||
_DEFINE_SYCL_PROP(sycl::ext::intel::info::device, property, property)
|
||||
|
||||
#define DEFINE_DEVICE_ASPECT(member) bool has_##member;
|
||||
|
||||
#define DEFINE_EXP_DEVICE_PROP(property) \
|
||||
_DEFINE_SYCL_PROP( \
|
||||
sycl::ext::oneapi::experimental::info::device, property, property)
|
||||
|
||||
struct C10_XPU_API DeviceProp{
|
||||
AT_FORALL_XPU_DEVICE_PROPERTIES(DEFINE_DEVICE_PROP)
|
||||
|
||||
// the platform name.
|
||||
DEFINE_PLATFORM_PROP(name, platform_name)
|
||||
|
||||
// ext properties.
|
||||
AT_FORALL_XPU_EXT_DEVICE_PROPERTIES(DEFINE_EXT_DEVICE_PROP)
|
||||
|
||||
// device aspects.
|
||||
AT_FORALL_XPU_DEVICE_ASPECT(DEFINE_DEVICE_ASPECT)
|
||||
|
||||
// experimental device aspects.
|
||||
AT_FORALL_XPU_EXP_CL_ASPECT(DEFINE_DEVICE_ASPECT)
|
||||
|
||||
#if SYCL_COMPILER_VERSION >= 20250000
|
||||
// experimental device properties.
|
||||
AT_FORALL_XPU_EXP_DEVICE_PROPERTIES(DEFINE_EXP_DEVICE_PROP)
|
||||
#endif
|
||||
};
|
||||
|
||||
#undef _DEFINE_SYCL_PROP
|
||||
#undef DEFINE_DEVICE_PROP
|
||||
#undef DEFINE_PLATFORM_PROP
|
||||
#undef DEFINE_EXT_DEVICE_PROP
|
||||
#undef DEFINE_DEVICE_ASPECT
|
||||
#undef DEFINE_EXP_DEVICE_PROP
|
||||
|
||||
} // namespace c10::xpu
|
||||
|
||||
#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)
|
||||
@@ -0,0 +1,183 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#pragma once
|
||||
#include <c10/xpu/XPUStream.h>
|
||||
|
||||
namespace c10::xpu {
|
||||
|
||||
/*
|
||||
* XPUEvent are movable not copyable wrappers around SYCL event. XPUEvent are
|
||||
* constructed lazily when first recorded. It has a device, and this device is
|
||||
* acquired from the first recording stream. Later streams that record the event
|
||||
* must match the same device.
|
||||
*
|
||||
* Currently, XPUEvent does NOT support to export an inter-process event from
|
||||
* another process via inter-process communication(IPC). So it means that
|
||||
* inter-process communication for event handles between different processes is
|
||||
* not available. This could impact some applications that rely on cross-process
|
||||
* synchronization and communication.
|
||||
*/
|
||||
struct XPUEvent {
|
||||
// Constructors
|
||||
XPUEvent(bool enable_timing = false) noexcept
|
||||
: enable_timing_{enable_timing} {}
|
||||
|
||||
~XPUEvent() {
|
||||
if (isCreated()) {
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_event_deletion(
|
||||
c10::kXPU, reinterpret_cast<uintptr_t>(event_.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
C10_DISABLE_COPY_AND_ASSIGN(XPUEvent);
|
||||
|
||||
XPUEvent(XPUEvent&& other) = default;
|
||||
XPUEvent& operator=(XPUEvent&& other) = default;
|
||||
|
||||
operator sycl::event&() const {
|
||||
return event();
|
||||
}
|
||||
|
||||
std::optional<c10::Device> device() const {
|
||||
if (isCreated()) {
|
||||
return c10::Device(c10::kXPU, device_index_);
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool isCreated() const {
|
||||
return (event_.get() != nullptr);
|
||||
}
|
||||
|
||||
DeviceIndex device_index() const {
|
||||
return device_index_;
|
||||
}
|
||||
|
||||
sycl::event& event() const {
|
||||
return *event_;
|
||||
}
|
||||
|
||||
bool query() const {
|
||||
using namespace sycl::info;
|
||||
if (!isCreated()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return event().get_info<event::command_execution_status>() ==
|
||||
event_command_status::complete;
|
||||
}
|
||||
|
||||
void record() {
|
||||
record(getCurrentXPUStream());
|
||||
}
|
||||
|
||||
void recordOnce(const XPUStream& stream) {
|
||||
if (!isCreated()) {
|
||||
record(stream);
|
||||
}
|
||||
}
|
||||
|
||||
void record(const XPUStream& stream) {
|
||||
if (!isCreated()) {
|
||||
device_index_ = stream.device_index();
|
||||
assignEvent(stream.queue());
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_event_creation(
|
||||
c10::kXPU, reinterpret_cast<uintptr_t>(event_.get()));
|
||||
}
|
||||
} else {
|
||||
TORCH_CHECK(
|
||||
device_index_ == stream.device_index(),
|
||||
"Event device ",
|
||||
device_index_,
|
||||
" does not match recording stream's device ",
|
||||
stream.device_index(),
|
||||
".");
|
||||
reassignEvent(stream.queue());
|
||||
}
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_event_record(
|
||||
c10::kXPU,
|
||||
reinterpret_cast<uintptr_t>(event_.get()),
|
||||
reinterpret_cast<uintptr_t>(&stream.queue()));
|
||||
}
|
||||
}
|
||||
|
||||
void block(const XPUStream& stream) {
|
||||
if (isCreated()) {
|
||||
std::vector<sycl::event> event_list{event()};
|
||||
// Make this stream wait until event_ is completed.
|
||||
stream.queue().ext_oneapi_submit_barrier(event_list);
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_event_wait(
|
||||
c10::kXPU,
|
||||
reinterpret_cast<uintptr_t>(event_.get()),
|
||||
reinterpret_cast<uintptr_t>(&stream.queue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double elapsed_time(const XPUEvent& other) const {
|
||||
TORCH_CHECK(
|
||||
isCreated() && other.isCreated(),
|
||||
"Both events must be recorded before calculating elapsed time.");
|
||||
TORCH_CHECK(
|
||||
query() && other.query(),
|
||||
"Both events must be completed before calculating elapsed time.");
|
||||
TORCH_CHECK(
|
||||
enable_timing_ && other.enable_timing_,
|
||||
"Both events must be created with argument 'enable_timing=True'.");
|
||||
|
||||
using namespace sycl::info::event_profiling;
|
||||
// Block until both of the recorded events are completed.
|
||||
uint64_t end_time_ns = other.event().get_profiling_info<command_end>();
|
||||
uint64_t start_time_ns = event().get_profiling_info<command_end>();
|
||||
// Return the eplased time in milliseconds.
|
||||
return 1e-6 *
|
||||
(static_cast<double>(end_time_ns) - static_cast<double>(start_time_ns));
|
||||
}
|
||||
|
||||
void synchronize() const {
|
||||
if (isCreated()) {
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_event_synchronization(
|
||||
c10::kXPU, reinterpret_cast<uintptr_t>(event_.get()));
|
||||
}
|
||||
event().wait_and_throw();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void assignEvent(sycl::queue& queue) {
|
||||
if (enable_timing_) {
|
||||
event_ = std::make_unique<sycl::event>(
|
||||
sycl::ext::oneapi::experimental::submit_profiling_tag(queue));
|
||||
} else {
|
||||
event_ = std::make_unique<sycl::event>(queue.ext_oneapi_submit_barrier());
|
||||
}
|
||||
}
|
||||
|
||||
void reassignEvent(sycl::queue& queue) {
|
||||
event_.reset();
|
||||
assignEvent(queue);
|
||||
}
|
||||
|
||||
bool enable_timing_ = false;
|
||||
c10::DeviceIndex device_index_ = -1;
|
||||
// Only need to track the last event, as events in an in-order queue are
|
||||
// executed sequentially.
|
||||
std::unique_ptr<sycl::event> event_;
|
||||
};
|
||||
|
||||
} // namespace c10::xpu
|
||||
|
||||
#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)
|
||||
@@ -0,0 +1,28 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#pragma once
|
||||
|
||||
#include <c10/util/Exception.h>
|
||||
#include <sycl/sycl.hpp>
|
||||
|
||||
namespace c10::xpu {
|
||||
|
||||
static inline sycl::async_handler asyncHandler =
|
||||
[](const sycl::exception_list& el) {
|
||||
if (el.size() == 0) {
|
||||
return;
|
||||
}
|
||||
for (const auto& e : el) {
|
||||
try {
|
||||
std::rethrow_exception(e);
|
||||
} catch (sycl::exception& e) {
|
||||
TORCH_WARN("SYCL Exception: ", e.what());
|
||||
}
|
||||
}
|
||||
throw;
|
||||
};
|
||||
|
||||
} // namespace c10::xpu
|
||||
|
||||
#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)
|
||||
@@ -0,0 +1,50 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#pragma once
|
||||
|
||||
#include <c10/core/Device.h>
|
||||
#include <c10/xpu/XPUDeviceProp.h>
|
||||
#include <c10/xpu/XPUMacros.h>
|
||||
|
||||
// The naming convention used here matches the naming convention of torch.xpu
|
||||
|
||||
namespace c10::xpu {
|
||||
|
||||
// Log a warning only once if no devices are detected.
|
||||
C10_XPU_API DeviceIndex device_count();
|
||||
|
||||
// Throws an error if no devices are detected.
|
||||
C10_XPU_API DeviceIndex device_count_ensure_non_zero();
|
||||
|
||||
C10_XPU_API DeviceIndex current_device();
|
||||
|
||||
C10_XPU_API void set_device(DeviceIndex device);
|
||||
|
||||
C10_XPU_API DeviceIndex exchange_device(DeviceIndex device);
|
||||
|
||||
C10_XPU_API DeviceIndex maybe_exchange_device(DeviceIndex to_device);
|
||||
|
||||
C10_XPU_API sycl::device& get_raw_device(DeviceIndex device);
|
||||
|
||||
C10_XPU_API sycl::context& get_device_context();
|
||||
|
||||
C10_XPU_API void get_device_properties(
|
||||
DeviceProp* device_prop,
|
||||
DeviceIndex device);
|
||||
|
||||
C10_XPU_API DeviceIndex get_device_idx_from_pointer(void* ptr);
|
||||
|
||||
static inline void check_device_index(DeviceIndex device_index) {
|
||||
TORCH_CHECK(
|
||||
device_index >= 0 && device_index < c10::xpu::device_count(),
|
||||
"The device index is out of range. It must be in [0, ",
|
||||
static_cast<int>(c10::xpu::device_count()),
|
||||
"), but got ",
|
||||
static_cast<int>(device_index),
|
||||
".");
|
||||
}
|
||||
|
||||
} // namespace c10::xpu
|
||||
|
||||
#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)
|
||||
@@ -0,0 +1,47 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#pragma once
|
||||
|
||||
#include <c10/xpu/XPUStream.h>
|
||||
#include <iostream>
|
||||
|
||||
// XPU Graphs utils used by c10 and aten.
|
||||
using namespace sycl::ext::oneapi::experimental;
|
||||
namespace c10::xpu {
|
||||
|
||||
static_assert(
|
||||
int8_t(queue_state::executing) == 0,
|
||||
"unexpected int(queue_state::executing) value");
|
||||
static_assert(
|
||||
int8_t(queue_state::recording) == 1,
|
||||
"unexpected int(queue_state::recording) value");
|
||||
|
||||
enum class CaptureStatus : int8_t {
|
||||
Executing = int8_t(queue_state::executing),
|
||||
Recording = int8_t(queue_state::recording)
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, CaptureStatus status) {
|
||||
switch (status) {
|
||||
case CaptureStatus::Executing:
|
||||
os << "Executing";
|
||||
break;
|
||||
case CaptureStatus::Recording:
|
||||
os << "Recording";
|
||||
break;
|
||||
default:
|
||||
TORCH_INTERNAL_ASSERT(
|
||||
false, "Unknown XPU graph CaptureStatus", int(status));
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
inline CaptureStatus currentStreamCaptureStatusMayInitCtx() {
|
||||
auto state = c10::xpu::getCurrentXPUStream().queue().ext_oneapi_get_state();
|
||||
return CaptureStatus(state);
|
||||
}
|
||||
|
||||
} // namespace c10::xpu
|
||||
|
||||
#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)
|
||||
@@ -0,0 +1,38 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#pragma once
|
||||
|
||||
#ifndef C10_USING_CUSTOM_GENERATED_MACROS
|
||||
#include <c10/xpu/impl/xpu_cmake_macros.h>
|
||||
#endif
|
||||
|
||||
// See c10/macros/Export.h for a detailed explanation of what the function
|
||||
// of these macros are. We need one set of macros for every separate library
|
||||
// we build.
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(C10_XPU_BUILD_SHARED_LIBS)
|
||||
#define C10_XPU_EXPORT __declspec(dllexport)
|
||||
#define C10_XPU_IMPORT __declspec(dllimport)
|
||||
#else
|
||||
#define C10_XPU_EXPORT
|
||||
#define C10_XPU_IMPORT
|
||||
#endif
|
||||
#else // _WIN32
|
||||
#if defined(__GNUC__)
|
||||
#define C10_XPU_EXPORT __attribute__((__visibility__("default")))
|
||||
#else // defined(__GNUC__)
|
||||
#define C10_XPU_EXPORT
|
||||
#endif // defined(__GNUC__)
|
||||
#define C10_XPU_IMPORT C10_XPU_EXPORT
|
||||
#endif // _WIN32
|
||||
|
||||
// This one is being used by libc10_xpu.so
|
||||
#ifdef C10_XPU_BUILD_MAIN_LIB
|
||||
#define C10_XPU_API C10_XPU_EXPORT
|
||||
#else
|
||||
#define C10_XPU_API C10_XPU_IMPORT
|
||||
#endif
|
||||
|
||||
#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)
|
||||
@@ -0,0 +1,222 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#pragma once
|
||||
|
||||
#include <c10/core/Stream.h>
|
||||
#include <c10/core/impl/GPUTrace.h>
|
||||
#include <c10/xpu/XPUFunctions.h>
|
||||
|
||||
namespace c10::xpu {
|
||||
|
||||
/*
|
||||
* Note [Stream Management]
|
||||
*
|
||||
* An XPUStream is an abstraction of an actual SYCL queue in which SYCL kernel
|
||||
* can execute. Currently, there are several pools per device to manage SYCL
|
||||
* queue, and a device's pool is lazily created.
|
||||
*
|
||||
* There are two pools per device. The first pool contains "normal priority"
|
||||
* queues. The second pool is the "high priority" queues. There are 32 queues in
|
||||
* per pool per device, and when a queue is requested one of these queues is
|
||||
* returned round-robin. That is, the first queue requested is at index 0, the
|
||||
* second at index 1... to index 31, then index 0 again.
|
||||
*
|
||||
* This means that if 33 queues are requested, the first and last queues
|
||||
* requested are actually the same queue (under the covers) and kernels enqueued
|
||||
* on them cannot run concurrently.
|
||||
*
|
||||
* It is safe to enqueue a kernel on the same queue from two different
|
||||
* threads as the SYCL specification described.
|
||||
*/
|
||||
|
||||
static constexpr int max_compile_time_stream_priorities = 3;
|
||||
|
||||
/*
|
||||
* This serves as a wrapper around c10::Stream and acts as a representation for
|
||||
* a SYCL queue, which allows asynchronous execution of XPU tasks.
|
||||
*/
|
||||
class C10_XPU_API XPUStream {
|
||||
public:
|
||||
enum Unchecked { UNCHECKED };
|
||||
|
||||
/// Construct a XPUStream from a Stream. This construction is checked, and
|
||||
/// will raise an error if the Stream is not, in fact, a XPU stream.
|
||||
explicit XPUStream(Stream stream) : stream_(stream) {
|
||||
TORCH_CHECK(stream_.device_type() == DeviceType::XPU);
|
||||
}
|
||||
|
||||
/// Construct a XPUStream from a Stream with no error checking.
|
||||
explicit XPUStream(Unchecked /*unused*/, Stream stream) : stream_(stream) {}
|
||||
|
||||
bool operator==(const XPUStream& other) const noexcept {
|
||||
return unwrap() == other.unwrap();
|
||||
}
|
||||
|
||||
bool operator!=(const XPUStream& other) const noexcept {
|
||||
return unwrap() != other.unwrap();
|
||||
}
|
||||
|
||||
/// Implicit conversion to sycl::queue&.
|
||||
operator sycl::queue&() const {
|
||||
return queue();
|
||||
}
|
||||
|
||||
/// Implicit conversion to sycl::queue*.
|
||||
operator sycl::queue*() const {
|
||||
return &queue();
|
||||
}
|
||||
|
||||
/// Implicit conversion to Stream (a.k.a., forget that the stream is a
|
||||
/// XPU stream).
|
||||
operator Stream() const {
|
||||
return unwrap();
|
||||
}
|
||||
|
||||
/// Get the XPU device type that this stream is associated with.
|
||||
DeviceType device_type() const {
|
||||
return DeviceType::XPU;
|
||||
}
|
||||
|
||||
/// Get the XPU device index that this stream is associated with.
|
||||
DeviceIndex device_index() const {
|
||||
return stream_.device_index();
|
||||
}
|
||||
|
||||
/// Get the full Device that this stream is associated with. The Device is
|
||||
/// guaranteed to be a XPU device.
|
||||
Device device() const {
|
||||
return Device(DeviceType::XPU, device_index());
|
||||
}
|
||||
|
||||
/// Return the stream ID corresponding to this particular stream. StreamId is
|
||||
/// a int64_t representation generated by its type and index.
|
||||
StreamId id() const {
|
||||
return stream_.id();
|
||||
}
|
||||
|
||||
/// Return true if all enqueued tasks in this stream have been completed,
|
||||
/// otherwise return false.
|
||||
bool query() const {
|
||||
return queue().ext_oneapi_empty();
|
||||
}
|
||||
|
||||
/// Performs a blocking wait for the completion of all enqueued tasks in this
|
||||
/// stream.
|
||||
void synchronize() const {
|
||||
queue().wait_and_throw();
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_stream_synchronization(
|
||||
c10::kXPU, reinterpret_cast<uintptr_t>(&queue()));
|
||||
}
|
||||
}
|
||||
|
||||
bool is_capturing() const {
|
||||
return queue().ext_oneapi_get_state() ==
|
||||
sycl::ext::oneapi::experimental::queue_state::recording;
|
||||
}
|
||||
|
||||
/// Return the priority that this stream is associated with. Lower numbers
|
||||
/// represent higher priority.
|
||||
int priority() const;
|
||||
|
||||
/// Explicit conversion to sycl::queue&.
|
||||
sycl::queue& queue() const;
|
||||
|
||||
/// Explicit conversion to Stream.
|
||||
Stream unwrap() const {
|
||||
return stream_;
|
||||
}
|
||||
|
||||
/// Reversibly pack a XPUStream into a struct representation. The XPUStream
|
||||
/// can be unpacked using unpack3().
|
||||
struct c10::StreamData3 pack3() const {
|
||||
return stream_.pack3();
|
||||
}
|
||||
|
||||
/// Unpack a XPUStream from the 3 fields generated by pack3().
|
||||
static XPUStream unpack3(
|
||||
StreamId stream_id,
|
||||
DeviceIndex device_index,
|
||||
DeviceType device_type) {
|
||||
return XPUStream(Stream::unpack3(stream_id, device_index, device_type));
|
||||
}
|
||||
|
||||
/// Return the range of priority **supported by PyTorch**.
|
||||
static std::tuple<int, int> priority_range() {
|
||||
// See Note [XPU Stream priorities]
|
||||
return std::make_tuple(1, -max_compile_time_stream_priorities + 2);
|
||||
}
|
||||
|
||||
private:
|
||||
Stream stream_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a stream from the pool in a round-robin fashion.
|
||||
*
|
||||
* You can request a stream from the highest priority pool by setting
|
||||
* isHighPriority to true for a specific device.
|
||||
*/
|
||||
C10_XPU_API XPUStream
|
||||
getStreamFromPool(const bool isHighPriority = false, DeviceIndex device = -1);
|
||||
|
||||
/**
|
||||
* Get a stream from the pool in a round-robin fashion.
|
||||
*
|
||||
* You can request a stream by setting a priority value for a specific device.
|
||||
* The priority number lower, the priority higher.
|
||||
*/
|
||||
C10_XPU_API XPUStream
|
||||
getStreamFromPool(const int priority, DeviceIndex device = -1);
|
||||
|
||||
/**
|
||||
* Get an XPUStream from an external SYCL queue.
|
||||
*
|
||||
* This function allows interoperability with other libraries by enabling
|
||||
* the use of an external SYCL queue that was not created by PyTorch. This
|
||||
* can be useful for data exchange or other operations where integration
|
||||
* with non-PyTorch queues is required.
|
||||
*
|
||||
* NOTE: It is the user's responsibility to ensure that the referenced SYCL
|
||||
* queue remains alive while the corresponding XPUStream, or any c10::Stream
|
||||
* derived from it, is in use. The different SYCL queue pointers will result in
|
||||
* distinct XPUStream instances, even if the SYCL queues they dereference are
|
||||
* equivalent.
|
||||
*/
|
||||
C10_XPU_API XPUStream
|
||||
getStreamFromExternal(sycl::queue* ext_queue, DeviceIndex device_index);
|
||||
|
||||
/**
|
||||
* Get the current XPU stream, for the passed XPU device, or for the current
|
||||
* device if no device index is passed.
|
||||
*/
|
||||
C10_XPU_API XPUStream getCurrentXPUStream(DeviceIndex device = -1);
|
||||
|
||||
/**
|
||||
* Set the current stream on the device of the passed in stream to be the passed
|
||||
* in stream.
|
||||
*/
|
||||
C10_XPU_API void setCurrentXPUStream(XPUStream stream);
|
||||
|
||||
C10_XPU_API std::ostream& operator<<(std::ostream& stream, const XPUStream& s);
|
||||
|
||||
/**
|
||||
* Block all reserved SYCL queues in the stream pools on the device, and wait
|
||||
* for their synchronizations.
|
||||
*/
|
||||
C10_XPU_API void syncStreamsOnDevice(DeviceIndex device = -1);
|
||||
|
||||
} // namespace c10::xpu
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<c10::xpu::XPUStream> {
|
||||
size_t operator()(c10::xpu::XPUStream s) const noexcept {
|
||||
return std::hash<c10::Stream>{}(s.unwrap());
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
#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)
|
||||
@@ -0,0 +1,258 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#pragma once
|
||||
|
||||
#include <c10/core/DeviceGuard.h>
|
||||
#include <c10/core/impl/DeviceGuardImplInterface.h>
|
||||
#include <c10/core/impl/GPUTrace.h>
|
||||
#include <c10/xpu/XPUCachingAllocator.h>
|
||||
#include <c10/xpu/XPUFunctions.h>
|
||||
#include <c10/xpu/XPUStream.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace c10::xpu::impl {
|
||||
|
||||
struct XPUGuardImpl final : public c10::impl::DeviceGuardImplInterface {
|
||||
static constexpr DeviceType static_type = kXPU;
|
||||
|
||||
XPUGuardImpl() = default;
|
||||
|
||||
explicit XPUGuardImpl(DeviceType t) {
|
||||
TORCH_CHECK(
|
||||
t == kXPU, "XPUGuardImpl initialized with non-XPU DeviceType: ", t);
|
||||
}
|
||||
|
||||
DeviceType type() const override {
|
||||
return kXPU;
|
||||
}
|
||||
|
||||
Device exchangeDevice(Device d) const override {
|
||||
TORCH_CHECK(d.is_xpu(), "Expected a XPU device, but got ", d);
|
||||
const auto old_device_index = c10::xpu::exchange_device(d.index());
|
||||
return Device(kXPU, old_device_index);
|
||||
}
|
||||
|
||||
Device getDevice() const override {
|
||||
const auto device = c10::xpu::current_device();
|
||||
return Device(kXPU, device);
|
||||
}
|
||||
|
||||
void setDevice(Device d) const override {
|
||||
TORCH_CHECK(d.is_xpu(), "Expected a XPU device, but got ", d);
|
||||
c10::xpu::set_device(d.index());
|
||||
}
|
||||
|
||||
void uncheckedSetDevice(Device d) const noexcept override {
|
||||
c10::xpu::set_device(d.index());
|
||||
}
|
||||
|
||||
DeviceCapability getDeviceCapability(Device d) const override {
|
||||
DeviceCapability cap;
|
||||
cap.capability_data.capability_bits = (1ULL << kIndex_Byte) |
|
||||
(1ULL << kIndex_Char) | (1ULL << kIndex_Short) | (1ULL << kIndex_Int) |
|
||||
(1ULL << kIndex_Long) | (1ULL << kIndex_Float) |
|
||||
(1ULL << kIndex_ComplexFloat) | (1ULL << kIndex_Bool) |
|
||||
(1ULL << kIndex_Float8_e5m2) | (1ULL << kIndex_Float8_e4m3fn) |
|
||||
(1ULL << kIndex_Float8_e5m2fnuz) | (1ULL << kIndex_Float8_e4m3fnuz) |
|
||||
(1ULL << kIndex_Float8_e8m0fnu) | (1ULL << kIndex_UInt16) |
|
||||
(1ULL << kIndex_UInt32) | (1ULL << kIndex_UInt64);
|
||||
// BFloat16 may be emulated. We always assume BFloat16 is available;
|
||||
// users can call is_bf16_supported() to check for native hardware support.
|
||||
cap.capability_data.capability_bits |= (1ULL << kIndex_BFloat16);
|
||||
auto& device = c10::xpu::get_raw_device(d.index());
|
||||
if (device.has(sycl::aspect::fp16)) {
|
||||
cap.capability_data.capability_bits |= (1ULL << kIndex_Half);
|
||||
cap.capability_data.capability_bits |= (1ULL << kIndex_ComplexHalf);
|
||||
}
|
||||
if (device.has(sycl::aspect::fp64)) {
|
||||
cap.capability_data.capability_bits |= (1ULL << kIndex_Double);
|
||||
cap.capability_data.capability_bits |= (1ULL << kIndex_ComplexDouble);
|
||||
}
|
||||
return cap;
|
||||
}
|
||||
|
||||
Stream getStream(Device d) const override {
|
||||
return getCurrentXPUStream(d.index()).unwrap();
|
||||
}
|
||||
|
||||
Stream getNewStream(Device d, int priority = 0) const override {
|
||||
return getStreamFromPool(priority, d.index());
|
||||
}
|
||||
|
||||
Stream getStreamFromGlobalPool(Device d, bool isHighPriority = false)
|
||||
const override {
|
||||
return getStreamFromPool(isHighPriority, d.index());
|
||||
}
|
||||
|
||||
// NB: These do NOT set the current device
|
||||
Stream exchangeStream(Stream s) const override {
|
||||
const XPUStream stream(s);
|
||||
const auto old_stream = getCurrentXPUStream(s.device().index());
|
||||
setCurrentXPUStream(stream);
|
||||
return old_stream.unwrap();
|
||||
}
|
||||
|
||||
void* getStreamNativeHandle(const Stream s) const override {
|
||||
const XPUStream stream{s};
|
||||
return reinterpret_cast<void*>(&(stream.queue()));
|
||||
}
|
||||
|
||||
DeviceIndex deviceCount() const noexcept override {
|
||||
return c10::xpu::device_count();
|
||||
}
|
||||
|
||||
// Event-related functions
|
||||
void destroyEvent(void* event, const DeviceIndex device_index)
|
||||
const noexcept override {
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_event_deletion(
|
||||
c10::kXPU, reinterpret_cast<uintptr_t>(event));
|
||||
}
|
||||
|
||||
delete reinterpret_cast<sycl::event*>(event);
|
||||
}
|
||||
|
||||
void record(
|
||||
void** event,
|
||||
const Stream& stream,
|
||||
const DeviceIndex device_index,
|
||||
const EventFlag flag) const override {
|
||||
TORCH_CHECK(
|
||||
device_index == -1 || device_index == stream.device_index(),
|
||||
"Event device index ",
|
||||
device_index,
|
||||
" does not match recording stream's device index ",
|
||||
stream.device_index(),
|
||||
".");
|
||||
|
||||
auto* xpu_event = reinterpret_cast<sycl::event*>(*event);
|
||||
const XPUStream xpu_stream{stream};
|
||||
|
||||
// Delete the event previously recorded.
|
||||
if (xpu_event)
|
||||
delete xpu_event;
|
||||
#if SYCL_COMPILER_VERSION >= 20250000
|
||||
if (flag == EventFlag::BACKEND_DEFAULT) {
|
||||
// Use the profiling tag to record the event to enable timing feature.
|
||||
xpu_event =
|
||||
new sycl::event(sycl::ext::oneapi::experimental::submit_profiling_tag(
|
||||
xpu_stream.queue()));
|
||||
} else {
|
||||
xpu_event =
|
||||
new sycl::event(xpu_stream.queue().ext_oneapi_submit_barrier());
|
||||
}
|
||||
#else
|
||||
xpu_event = new sycl::event(xpu_stream.queue().ext_oneapi_submit_barrier());
|
||||
#endif
|
||||
*event = reinterpret_cast<void*>(xpu_event);
|
||||
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_event_record(
|
||||
c10::kXPU,
|
||||
reinterpret_cast<uintptr_t>(xpu_event),
|
||||
reinterpret_cast<uintptr_t>(&xpu_stream.queue()));
|
||||
}
|
||||
}
|
||||
|
||||
void block(void* event, const Stream& stream) const override {
|
||||
if (!event)
|
||||
return;
|
||||
auto* xpu_event = reinterpret_cast<sycl::event*>(event);
|
||||
std::vector<sycl::event> event_list{*xpu_event};
|
||||
const XPUStream xpu_stream(stream);
|
||||
xpu_stream.queue().ext_oneapi_submit_barrier(event_list);
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_event_wait(
|
||||
c10::kXPU,
|
||||
reinterpret_cast<uintptr_t>(xpu_event),
|
||||
reinterpret_cast<uintptr_t>(&xpu_stream.queue()));
|
||||
}
|
||||
}
|
||||
|
||||
bool queryEvent(void* event) const override {
|
||||
using namespace sycl::info;
|
||||
if (!event)
|
||||
return true;
|
||||
auto* xpu_event = reinterpret_cast<sycl::event*>(event);
|
||||
return xpu_event->get_info<event::command_execution_status>() ==
|
||||
event_command_status::complete;
|
||||
}
|
||||
|
||||
double elapsedTime(
|
||||
void* start_event,
|
||||
void* end_event,
|
||||
const DeviceIndex device_index) const override {
|
||||
#if SYCL_COMPILER_VERSION < 20250000
|
||||
TORCH_CHECK_NOT_IMPLEMENTED(
|
||||
false,
|
||||
"elapsedTime requires PyTorch to be built with SYCL compiler version 2025.0.0 or newer.");
|
||||
#endif
|
||||
TORCH_CHECK(
|
||||
start_event && end_event,
|
||||
"Both events must be recorded before calculating elapsed time.");
|
||||
auto* xpu_start_event = reinterpret_cast<sycl::event*>(start_event);
|
||||
auto* xpu_end_event = reinterpret_cast<sycl::event*>(end_event);
|
||||
|
||||
using namespace sycl::info::event_profiling;
|
||||
// Block until both of the recorded events are completed.
|
||||
uint64_t end_time_ns = xpu_end_event->get_profiling_info<command_end>();
|
||||
uint64_t start_time_ns = xpu_start_event->get_profiling_info<command_end>();
|
||||
// Return the eplased time in milliseconds.
|
||||
return 1e-6 *
|
||||
(static_cast<double>(end_time_ns) - static_cast<double>(start_time_ns));
|
||||
}
|
||||
|
||||
// Stream-related functions
|
||||
bool queryStream(const Stream& stream) const override {
|
||||
const XPUStream xpu_stream{stream};
|
||||
return xpu_stream.query();
|
||||
}
|
||||
|
||||
void synchronizeStream(const Stream& stream) const override {
|
||||
const XPUStream xpu_stream{stream};
|
||||
xpu_stream.synchronize();
|
||||
}
|
||||
|
||||
bool isStreamCapturing(const Stream& stream) const override {
|
||||
const XPUStream xpu_stream{stream};
|
||||
return xpu_stream.is_capturing();
|
||||
}
|
||||
|
||||
void synchronizeEvent(void* event) const override {
|
||||
if (!event)
|
||||
return;
|
||||
auto* xpu_event = reinterpret_cast<sycl::event*>(event);
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_event_synchronization(
|
||||
c10::kXPU, reinterpret_cast<uintptr_t>(xpu_event));
|
||||
}
|
||||
xpu_event->wait_and_throw();
|
||||
}
|
||||
|
||||
void synchronizeDevice(const c10::DeviceIndex device_index) const override {
|
||||
const c10::impl::PyInterpreter* interp = c10::impl::GPUTrace::get_trace();
|
||||
if (C10_UNLIKELY(interp)) {
|
||||
(*interp)->trace_gpu_device_synchronization(c10::kXPU);
|
||||
}
|
||||
c10::xpu::syncStreamsOnDevice(device_index);
|
||||
}
|
||||
|
||||
void recordDataPtrOnStream(const c10::DataPtr& data_ptr, const Stream& stream)
|
||||
const override {
|
||||
const XPUStream xpu_stream{stream};
|
||||
XPUCachingAllocator::recordStream(data_ptr, xpu_stream);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace c10::xpu::impl
|
||||
|
||||
#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)
|
||||
@@ -0,0 +1,26 @@
|
||||
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <c10/util/irange.h>
|
||||
|
||||
static inline void initHostData(int* hostData, int numel) {
|
||||
for (const auto i : c10::irange(numel)) {
|
||||
hostData[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void clearHostData(int* hostData, int numel) {
|
||||
for (const auto i : c10::irange(numel)) {
|
||||
hostData[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void validateHostData(int* hostData, int numel) {
|
||||
for (const auto i : c10::irange(numel)) {
|
||||
EXPECT_EQ(hostData[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
#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)
|
||||
Reference in New Issue
Block a user