DPNP C++ backend kernel library 0.21.0dev6
Data Parallel Extension for NumPy*
Loading...
Searching...
No Matches
common.hpp
1//*****************************************************************************
2// Copyright (c) 2024, 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// - Neither the name of the copyright holder nor the names of its contributors
13// may be used to endorse or promote products derived from this software
14// without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26// THE POSSIBILITY OF SUCH DAMAGE.
27//*****************************************************************************
28
29#pragma once
30
31#include <stdexcept>
32
33#include <oneapi/mkl.hpp>
34#include <pybind11/pybind11.h>
35#include <sycl/sycl.hpp>
36
37namespace dpnp::extensions::fft
38{
39namespace mkl_dft = oneapi::mkl::dft;
40namespace py = pybind11;
41
42template <mkl_dft::precision prec, mkl_dft::domain dom>
44{
45public:
46 using descr_type = mkl_dft::descriptor<prec, dom>;
47
48 DescriptorWrapper(std::int64_t n) : descr_(n), queue_ptr_{} {}
49 DescriptorWrapper(std::vector<std::int64_t> dimensions)
50 : descr_(dimensions), queue_ptr_{}
51 {
52 }
54
55 void commit(sycl::queue &q)
56 {
57 mkl_dft::precision fft_prec = get_precision();
58 if (fft_prec == mkl_dft::precision::DOUBLE &&
59 !q.get_device().has(sycl::aspect::fp64)) {
60 throw py::value_error("Descriptor is double precision but the "
61 "device does not support double precision.");
62 }
63
64 {
65 // Release GIL to avoid serialization of host task submissions
66 // to the same queue in OneMKL
67 py::gil_scoped_release lock{};
68
69 descr_.commit(q);
70 }
71 queue_ptr_ = std::make_unique<sycl::queue>(q);
72 }
73
74 descr_type &get_descriptor() { return descr_; }
75
76 const sycl::queue &get_queue() const
77 {
78 if (queue_ptr_) {
79 return *queue_ptr_;
80 }
81 else {
82 throw std::runtime_error(
83 "Attempt to get queue when it is not yet set");
84 }
85 }
86
87 // config_param::DIMENSION
88 template <typename valT = std::int64_t>
89 const valT get_dim()
90 {
91 valT dim = -1;
92 descr_.get_value(mkl_dft::config_param::DIMENSION, &dim);
93
94 return dim;
95 }
96
97 // config_param::NUMBER_OF_TRANSFORMS
98 template <typename valT = std::int64_t>
99 const valT get_number_of_transforms()
100 {
101 valT transforms_count{};
102
103 descr_.get_value(mkl_dft::config_param::NUMBER_OF_TRANSFORMS,
104 &transforms_count);
105 return transforms_count;
106 }
107
108 template <typename valT = std::int64_t>
109 void set_number_of_transforms(const valT &num)
110 {
111 descr_.set_value(mkl_dft::config_param::NUMBER_OF_TRANSFORMS, num);
112 }
113
114 // config_param::FWD_STRIDES
115 template <typename valT = std::vector<std::int64_t>>
116 const valT get_fwd_strides()
117 {
118 const typename valT::value_type dim = get_dim();
119
120 valT fwd_strides(dim + 1);
121#if defined(USE_ONEMATH)
122 // oneMath uses a C-style variadic API that expects a raw pointer
123 descr_.get_value(mkl_dft::config_param::FWD_STRIDES,
124 fwd_strides.data());
125#else
126 descr_.get_value(mkl_dft::config_param::FWD_STRIDES, &fwd_strides);
127#endif // USE_ONEMATH
128 return fwd_strides;
129 }
130
131 template <typename valT = std::vector<std::int64_t>>
132 void set_fwd_strides(const valT &strides)
133 {
134 const typename valT::value_type dim = get_dim();
135
136 if (static_cast<size_t>(dim + 1) != strides.size()) {
137 throw py::value_error(
138 "Strides length does not match descriptor's dimension");
139 }
140#if defined(USE_ONEMATH)
141 // oneMath uses a C-style variadic API that expects a raw pointer
142 descr_.set_value(mkl_dft::config_param::FWD_STRIDES, strides.data());
143#else
144 descr_.set_value(mkl_dft::config_param::FWD_STRIDES, strides);
145#endif // USE_ONEMATH
146 }
147
148 // config_param::BWD_STRIDES
149 template <typename valT = std::vector<std::int64_t>>
150 const valT get_bwd_strides()
151 {
152 const typename valT::value_type dim = get_dim();
153
154 valT bwd_strides(dim + 1);
155#if defined(USE_ONEMATH)
156 // oneMath uses a C-style variadic API that expects a raw pointer
157 descr_.get_value(mkl_dft::config_param::BWD_STRIDES,
158 bwd_strides.data());
159#else
160 descr_.get_value(mkl_dft::config_param::BWD_STRIDES, &bwd_strides);
161#endif // USE_ONEMATH
162 return bwd_strides;
163 }
164
165 template <typename valT = std::vector<std::int64_t>>
166 void set_bwd_strides(const valT &strides)
167 {
168 const typename valT::value_type dim = get_dim();
169
170 if (static_cast<size_t>(dim + 1) != strides.size()) {
171 throw py::value_error(
172 "Strides length does not match descriptor's dimension");
173 }
174#if defined(USE_ONEMATH)
175 // oneMath uses a C-style variadic API that expects a raw pointer
176 descr_.set_value(mkl_dft::config_param::BWD_STRIDES, strides.data());
177#else
178 descr_.set_value(mkl_dft::config_param::BWD_STRIDES, strides);
179#endif // USE_ONEMATH
180 }
181
182 // config_param::FWD_DISTANCE
183 template <typename valT = std::int64_t>
184 const valT get_fwd_distance()
185 {
186 valT dist = 0;
187
188 descr_.get_value(mkl_dft::config_param::FWD_DISTANCE, &dist);
189 return dist;
190 }
191
192 template <typename valT = std::int64_t>
193 void set_fwd_distance(const valT &dist)
194 {
195 descr_.set_value(mkl_dft::config_param::FWD_DISTANCE, dist);
196 }
197
198 // config_param::BWD_DISTANCE
199 template <typename valT = std::int64_t>
200 const valT get_bwd_distance()
201 {
202 valT dist = 0;
203
204 descr_.get_value(mkl_dft::config_param::BWD_DISTANCE, &dist);
205 return dist;
206 }
207
208 template <typename valT = std::int64_t>
209 void set_bwd_distance(const valT &dist)
210 {
211 descr_.set_value(mkl_dft::config_param::BWD_DISTANCE, dist);
212 }
213
214 // config_param::PLACEMENT
215 bool get_in_place()
216 {
217 mkl_dft::config_value placement;
218 descr_.get_value(mkl_dft::config_param::PLACEMENT, &placement);
219 return (placement == mkl_dft::config_value::INPLACE);
220 }
221
222 void set_in_place(const bool &in_place_request)
223 {
224 descr_.set_value(mkl_dft::config_param::PLACEMENT,
225 (in_place_request)
226 ? mkl_dft::config_value::INPLACE
227 : mkl_dft::config_value::NOT_INPLACE);
228 }
229
230 // config_param::PRECISION
231 mkl_dft::precision get_precision()
232 {
233 mkl_dft::precision fft_prec;
234
235 descr_.get_value(mkl_dft::config_param::PRECISION, &fft_prec);
236 return fft_prec;
237 }
238
239 // config_param::COMMIT_STATUS
240 bool is_committed()
241 {
242 mkl_dft::config_value committed;
243 descr_.get_value(mkl_dft::config_param::COMMIT_STATUS, &committed);
244 return (committed == mkl_dft::config_value::COMMITTED);
245 }
246
247private:
248 mkl_dft::descriptor<prec, dom> descr_;
249 std::unique_ptr<sycl::queue> queue_ptr_;
250};
251
252} // namespace dpnp::extensions::fft