Loading...
Searching...
No Matches
sycl.cpp
Go to the documentation of this file.
1/**
2 * SYCLGPUDeviceBackendImpl — concrete SYCL/oneAPI GPU device backend.
3 *
4 * Provides device lifecycle management, unified shared memory allocation
5 * via sycl::malloc_shared(), and device synchronization via queue.wait_and_throw().
6 *
7 * Device info (name, memory) is queried via SYCL device info descriptors.
8 * The default selector picks the best available device (GPU if present,
9 * otherwise falls back to CPU for development/testing).
10 */
11
14
15#include <stdexcept>
16#include <string>
17
18namespace q3 {
19namespace execution {
20namespace gpu {
21namespace device {
22
24 public:
25 /**
26 * Construct and initialize the SYCL device backend.
27 *
28 * Uses the default selector, which prefers GPU devices when available
29 * and falls back to CPU for development/testing on systems without
30 * a discrete GPU.
31 */
32 SYCLGPUDeviceBackendImpl() : queue_(sycl::default_selector_v) {}
33
34 /**
35 * Human-readable name of the SYCL device (e.g., "Intel(R) Data Center GPU Max 1550").
36 */
37 std::string device_name() const override {
38 return queue_.get_device().get_info<sycl::info::device::name>();
39 }
40
41 /**
42 * Total device global memory in bytes.
43 */
44 size_t total_memory_bytes() const override {
45 return queue_.get_device().get_info<sycl::info::device::global_mem_size>();
46 }
47
48 /**
49 * Whether the device supports native double precision (FP64) computation.
50 *
51 * Checks for the sycl::aspect::fp64 capability. Most Intel Data Center GPUs
52 * support FP64; some consumer GPUs may not.
53 */
54 bool supports_double_precision() const override {
55 return queue_.get_device().has(sycl::aspect::fp64);
56 }
57
58 /**
59 * Allocate unified shared memory via sycl::malloc_shared().
60 *
61 * Shared memory is accessible from both host and device with automatic
62 * data migration managed by the SYCL runtime. This is the SYCL
63 * equivalent of CUDA's cudaMallocManaged().
64 */
65 void* allocate_unified(size_t size_bytes) override {
66 void* pointer = sycl::malloc_shared(size_bytes, queue_);
67 if (pointer == nullptr) {
68 throw std::runtime_error("SYCLGPUDeviceBackendImpl: sycl::malloc_shared failed for " +
69 std::to_string(size_bytes) + " bytes");
70 }
71 return pointer;
72 }
73
74 /**
75 * Deallocate memory previously allocated via allocate_unified().
76 */
77 void deallocate(void* pointer) override {
78 sycl::free(pointer, queue_);
79 }
80
81 /**
82 * Block until all pending GPU operations on this queue have completed.
83 *
84 * Uses wait_and_throw() to surface any asynchronous exceptions from
85 * previously submitted kernel or memory operations.
86 */
87 void synchronize() override {
88 queue_.wait_and_throw();
89 }
90
91 /**
92 * Access the underlying SYCL queue for vendor-specific operations.
93 */
94 sycl::queue& queue() override {
95 return queue_;
96 }
97
98 /**
99 * Access the underlying SYCL queue (const).
100 */
101 const sycl::queue& queue() const override {
102 return queue_;
103 }
104
105 private:
106 sycl::queue queue_;
107};
108
109// ── Factory ─────────────────────────────────────────────────────────────────
110
111std::shared_ptr<GPUDeviceBackend> create_gpu_device_backend() {
112 return std::make_shared<SYCLGPUDeviceBackendImpl>();
113}
114
115} // namespace device
116} // namespace gpu
117} // namespace execution
118} // namespace q3
void * allocate_unified(size_t size_bytes) override
Definition sycl.cpp:65
const sycl::queue & queue() const override
Definition sycl.cpp:101
void deallocate(void *pointer) override
Definition sycl.cpp:77
std::string device_name() const override
Definition sycl.cpp:37
std::shared_ptr< GPUDeviceBackend > create_gpu_device_backend()
Definition cuda.cpp:103