DPNP C++ backend kernel library 0.21.0dev3
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 descr_.commit(q);
65 queue_ptr_ = std::make_unique<sycl::queue>(q);
66 }
67
68 descr_type &get_descriptor() { return descr_; }
69
70 const sycl::queue &get_queue() const
71 {
72 if (queue_ptr_) {
73 return *queue_ptr_;
74 }
75 else {
76 throw std::runtime_error(
77 "Attempt to get queue when it is not yet set");
78 }
79 }
80
81 // config_param::DIMENSION
82 template <typename valT = std::int64_t>
83 const valT get_dim()
84 {
85 valT dim = -1;
86 descr_.get_value(mkl_dft::config_param::DIMENSION, &dim);
87
88 return dim;
89 }
90
91 // config_param::NUMBER_OF_TRANSFORMS
92 template <typename valT = std::int64_t>
93 const valT get_number_of_transforms()
94 {
95 valT transforms_count{};
96
97 descr_.get_value(mkl_dft::config_param::NUMBER_OF_TRANSFORMS,
98 &transforms_count);
99 return transforms_count;
100 }
101
102 template <typename valT = std::int64_t>
103 void set_number_of_transforms(const valT &num)
104 {
105 descr_.set_value(mkl_dft::config_param::NUMBER_OF_TRANSFORMS, num);
106 }
107
108 // config_param::FWD_STRIDES
109 template <typename valT = std::vector<std::int64_t>>
110 const valT get_fwd_strides()
111 {
112 const typename valT::value_type dim = get_dim();
113
114 valT fwd_strides(dim + 1);
115#if defined(USE_ONEMATH)
116 // oneMath uses a C-style variadic API that expects a raw pointer
117 descr_.get_value(mkl_dft::config_param::FWD_STRIDES,
118 fwd_strides.data());
119#else
120 descr_.get_value(mkl_dft::config_param::FWD_STRIDES, &fwd_strides);
121#endif // USE_ONEMATH
122 return fwd_strides;
123 }
124
125 template <typename valT = std::vector<std::int64_t>>
126 void set_fwd_strides(const valT &strides)
127 {
128 const typename valT::value_type dim = get_dim();
129
130 if (static_cast<size_t>(dim + 1) != strides.size()) {
131 throw py::value_error(
132 "Strides length does not match descriptor's dimension");
133 }
134#if defined(USE_ONEMATH)
135 // oneMath uses a C-style variadic API that expects a raw pointer
136 descr_.set_value(mkl_dft::config_param::FWD_STRIDES, strides.data());
137#else
138 descr_.set_value(mkl_dft::config_param::FWD_STRIDES, strides);
139#endif // USE_ONEMATH
140 }
141
142 // config_param::BWD_STRIDES
143 template <typename valT = std::vector<std::int64_t>>
144 const valT get_bwd_strides()
145 {
146 const typename valT::value_type dim = get_dim();
147
148 valT bwd_strides(dim + 1);
149#if defined(USE_ONEMATH)
150 // oneMath uses a C-style variadic API that expects a raw pointer
151 descr_.get_value(mkl_dft::config_param::BWD_STRIDES,
152 bwd_strides.data());
153#else
154 descr_.get_value(mkl_dft::config_param::BWD_STRIDES, &bwd_strides);
155#endif // USE_ONEMATH
156 return bwd_strides;
157 }
158
159 template <typename valT = std::vector<std::int64_t>>
160 void set_bwd_strides(const valT &strides)
161 {
162 const typename valT::value_type dim = get_dim();
163
164 if (static_cast<size_t>(dim + 1) != strides.size()) {
165 throw py::value_error(
166 "Strides length does not match descriptor's dimension");
167 }
168#if defined(USE_ONEMATH)
169 // oneMath uses a C-style variadic API that expects a raw pointer
170 descr_.set_value(mkl_dft::config_param::BWD_STRIDES, strides.data());
171#else
172 descr_.set_value(mkl_dft::config_param::BWD_STRIDES, strides);
173#endif // USE_ONEMATH
174 }
175
176 // config_param::FWD_DISTANCE
177 template <typename valT = std::int64_t>
178 const valT get_fwd_distance()
179 {
180 valT dist = 0;
181
182 descr_.get_value(mkl_dft::config_param::FWD_DISTANCE, &dist);
183 return dist;
184 }
185
186 template <typename valT = std::int64_t>
187 void set_fwd_distance(const valT &dist)
188 {
189 descr_.set_value(mkl_dft::config_param::FWD_DISTANCE, dist);
190 }
191
192 // config_param::BWD_DISTANCE
193 template <typename valT = std::int64_t>
194 const valT get_bwd_distance()
195 {
196 valT dist = 0;
197
198 descr_.get_value(mkl_dft::config_param::BWD_DISTANCE, &dist);
199 return dist;
200 }
201
202 template <typename valT = std::int64_t>
203 void set_bwd_distance(const valT &dist)
204 {
205 descr_.set_value(mkl_dft::config_param::BWD_DISTANCE, dist);
206 }
207
208 // config_param::PLACEMENT
209 bool get_in_place()
210 {
211 mkl_dft::config_value placement;
212 descr_.get_value(mkl_dft::config_param::PLACEMENT, &placement);
213 return (placement == mkl_dft::config_value::INPLACE);
214 }
215
216 void set_in_place(const bool &in_place_request)
217 {
218 descr_.set_value(mkl_dft::config_param::PLACEMENT,
219 (in_place_request)
220 ? mkl_dft::config_value::INPLACE
221 : mkl_dft::config_value::NOT_INPLACE);
222 }
223
224 // config_param::PRECISION
225 mkl_dft::precision get_precision()
226 {
227 mkl_dft::precision fft_prec;
228
229 descr_.get_value(mkl_dft::config_param::PRECISION, &fft_prec);
230 return fft_prec;
231 }
232
233 // config_param::COMMIT_STATUS
234 bool is_committed()
235 {
236 mkl_dft::config_value committed;
237 descr_.get_value(mkl_dft::config_param::COMMIT_STATUS, &committed);
238 return (committed == mkl_dft::config_value::COMMITTED);
239 }
240
241private:
242 mkl_dft::descriptor<prec, dom> descr_;
243 std::unique_ptr<sycl::queue> queue_ptr_;
244};
245
246} // namespace dpnp::extensions::fft