DPNP C++ backend kernel library 0.18.0dev0
Data Parallel Extension for NumPy*
Loading...
Searching...
No Matches
dpnpc_memory_adapter.hpp
1//*****************************************************************************
2// Copyright (c) 2016-2025, Intel Corporation
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7// - Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// - Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
17// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23// THE POSSIBILITY OF SUCH DAMAGE.
24//*****************************************************************************
25
26#pragma once
27#ifndef DPNP_MEMORY_ADAPTER_H // Cython compatibility
28#define DPNP_MEMORY_ADAPTER_H
29
30#include "dpnp_utils.hpp"
31#include "queue_sycl.hpp"
32
44template <typename _DataType>
46{
47 DPCTLSyclQueueRef queue_ref;
48 sycl::queue queue;
49 void *aux_ptr = nullptr;
50 void *orig_ptr =
51 nullptr;
52 size_t size_in_bytes = 0;
53 bool allocated = false;
55 bool target_no_queue = false;
57 bool copy_back = false;
59 const bool verbose = false;
60 std::vector<sycl::event> deps;
61
62public:
63 DPNPC_ptr_adapter() = delete;
64
65 DPNPC_ptr_adapter(DPCTLSyclQueueRef q_ref,
66 const void *src_ptr,
67 const size_t size,
68 bool target_no_sycl = false,
69 bool copy_back_request = false)
70 {
71 queue_ref = q_ref;
72 queue = *(reinterpret_cast<sycl::queue *>(queue_ref));
73 target_no_queue = target_no_sycl;
74 copy_back = copy_back_request;
75 orig_ptr = const_cast<void *>(src_ptr);
76 size_in_bytes = size * sizeof(_DataType);
77 deps = std::vector<sycl::event>{};
78
79 // enum class alloc { host = 0, device = 1, shared = 2, unknown = 3 };
80 sycl::usm::alloc src_ptr_type = sycl::usm::alloc::unknown;
81 src_ptr_type = sycl::get_pointer_type(src_ptr, queue.get_context());
82 if (verbose) {
83 std::cerr << "DPNPC_ptr_converter:";
84 std::cerr << "\n\t target_no_queue=" << target_no_queue;
85 std::cerr << "\n\t copy_back=" << copy_back;
86 std::cerr << "\n\t pointer=" << src_ptr;
87 std::cerr << "\n\t size=" << size;
88 std::cerr << "\n\t size_in_bytes=" << size_in_bytes;
89 std::cerr << "\n\t pointer type=" << (long)src_ptr_type;
90 std::cerr << "\n\t queue inorder=" << queue.is_in_order();
91 std::cerr << "\n\t queue device is_cpu="
92 << queue.get_device().is_cpu();
93 std::cerr << "\n\t queue device is_gpu="
94 << queue.get_device().is_gpu();
95 std::cerr << "\n\t queue device is_accelerator="
96 << queue.get_device().is_accelerator();
97 std::cerr << std::endl;
98 }
99
100 if (is_memcpy_required(src_ptr_type)) {
101 aux_ptr = dpnp_memory_alloc_c(queue_ref, size_in_bytes);
102 dpnp_memory_memcpy_c(queue_ref, aux_ptr, src_ptr, size_in_bytes);
103 allocated = true;
104 if (verbose) {
105 std::cerr << "DPNPC_ptr_converter::alloc and copy memory"
106 << " from=" << src_ptr << " to=" << aux_ptr
107 << " size_in_bytes=" << size_in_bytes << std::endl;
108 }
109 }
110 else {
111 aux_ptr = const_cast<void *>(src_ptr);
112 }
113 }
114
116 {
117 if (allocated) {
118 if (verbose) {
119 std::cerr << "DPNPC_ptr_converter::free_memory at=" << aux_ptr
120 << std::endl;
121 }
122
123 sycl::event::wait(deps);
124
125 if (copy_back) {
126 copy_data_back();
127 }
128
129 dpnp_memory_free_c(queue_ref, aux_ptr);
130 }
131 }
132
133 bool is_memcpy_required(sycl::usm::alloc src_ptr_type)
134 {
135 if (target_no_queue || queue.get_device().is_gpu()) {
136 if (src_ptr_type == sycl::usm::alloc::unknown) {
137 return true;
138 }
139 else if (target_no_queue &&
140 src_ptr_type == sycl::usm::alloc::device) {
141 return true;
142 }
143 }
144
145 return false;
146 }
147
148 _DataType *get_ptr() const
149 {
150 return reinterpret_cast<_DataType *>(aux_ptr);
151 }
152
153 void copy_data_back() const
154 {
155 if (verbose) {
156 std::cerr << "DPNPC_ptr_converter::copy_data_back:"
157 << " from=" << aux_ptr << " to=" << orig_ptr
158 << " size_in_bytes=" << size_in_bytes << std::endl;
159 }
160
161 dpnp_memory_memcpy_c(queue_ref, orig_ptr, aux_ptr, size_in_bytes);
162 }
163
164 void depends_on(const std::vector<sycl::event> &new_deps)
165 {
166 assert(allocated);
167 deps.insert(std::end(deps), std::begin(new_deps), std::end(new_deps));
168 }
169
170 void depends_on(const sycl::event &new_dep)
171 {
172 assert(allocated);
173 deps.push_back(new_dep);
174 }
175};
176
177#endif // DPNP_MEMORY_ADAPTER_H
Adapter for the memory given by parameters in the DPNPC functions.
char * dpnp_memory_alloc_c(DPCTLSyclQueueRef q_ref, size_t size_in_bytes)
SYCL queue memory allocation.