7 #ifndef HEFFTE_BACKEND_MKL_H
8 #define HEFFTE_BACKEND_MKL_H
10 #include "heffte_r2r_executor.h"
12 #ifdef Heffte_ENABLE_MKL
58 template<>
struct is_ccomplex<float _Complex> : std::true_type{};
63 template<>
struct is_zcomplex<double _Complex> : std::true_type{};
69 inline void check_error(MKL_LONG status, std::string
const &function_name){
71 throw std::runtime_error(function_name +
" failed with status: " + std::to_string(status));
83 template<
typename scalar_type>
93 plan_mkl(
int size,
int howmanyffts,
int stride,
int dist) :
plan(nullptr){
94 static_assert(std::is_same<scalar_type, std::complex<float>>::value
95 or std::is_same<scalar_type, std::complex<double>>::value,
96 "plan_mkl requires std::complex scalar_type with float or double, see plan_mkl_r2c for real types");
98 check_error( DftiCreateDescriptor(&
plan, (std::is_same<scalar_type, std::complex<float>>::value) ?
99 DFTI_SINGLE : DFTI_DOUBLE,
100 DFTI_COMPLEX, 1,
static_cast<MKL_LONG
>(size)),
"mkl plan create" );
101 check_error( DftiSetValue(
plan, DFTI_NUMBER_OF_TRANSFORMS,
static_cast<MKL_LONG
>(howmanyffts)),
"mkl set howmany");
102 check_error( DftiSetValue(
plan, DFTI_PLACEMENT, DFTI_INPLACE),
"mkl set in place");
103 MKL_LONG lstride[] = {0,
static_cast<MKL_LONG
>(stride)};
104 check_error( DftiSetValue(
plan, DFTI_INPUT_STRIDES, lstride),
"mkl set istride");
105 check_error( DftiSetValue(
plan, DFTI_OUTPUT_STRIDES, lstride),
"mkl set ostride");
106 check_error( DftiSetValue(
plan, DFTI_INPUT_DISTANCE,
static_cast<MKL_LONG
>(dist)),
"mkl set idist");
107 check_error( DftiSetValue(
plan, DFTI_OUTPUT_DISTANCE,
static_cast<MKL_LONG
>(dist)),
"mkl set odist");
119 plan_mkl(
size_t size1,
size_t size2, std::array<MKL_LONG, 2>
const &embed,
size_t howmanyffts,
size_t dist) :
plan(nullptr){
120 static_assert(std::is_same<scalar_type, std::complex<float>>::value
121 or std::is_same<scalar_type, std::complex<double>>::value,
122 "plan_mkl requires std::complex scalar_type with float or double, see plan_mkl_r2c for real types");
124 MKL_LONG size[] = {
static_cast<MKL_LONG
>(size1),
static_cast<MKL_LONG
>(size2)};
125 check_error( DftiCreateDescriptor(&
plan, (std::is_same<scalar_type, std::complex<float>>::value) ?
126 DFTI_SINGLE : DFTI_DOUBLE,
127 DFTI_COMPLEX, 2, size),
"mkl plan create 2d" );
128 check_error( DftiSetValue(
plan, DFTI_NUMBER_OF_TRANSFORMS,
static_cast<MKL_LONG
>(howmanyffts)),
"mkl set howmany");
129 check_error( DftiSetValue(
plan, DFTI_PLACEMENT, DFTI_INPLACE),
"mkl set in place");
130 MKL_LONG lstride[] = {0,
static_cast<MKL_LONG
>(embed[0]),
static_cast<MKL_LONG
>(embed[1])};
131 check_error( DftiSetValue(
plan, DFTI_INPUT_STRIDES, lstride),
"mkl set istride");
132 check_error( DftiSetValue(
plan, DFTI_OUTPUT_STRIDES, lstride),
"mkl set ostride");
133 check_error( DftiSetValue(
plan, DFTI_INPUT_DISTANCE,
static_cast<MKL_LONG
>(dist)),
"mkl set idist");
134 check_error( DftiSetValue(
plan, DFTI_OUTPUT_DISTANCE,
static_cast<MKL_LONG
>(dist)),
"mkl set odist");
146 MKL_LONG size[] = {
static_cast<MKL_LONG
>(size3),
static_cast<MKL_LONG
>(size2),
static_cast<MKL_LONG
>(size1)};
147 check_error( DftiCreateDescriptor(&
plan, (std::is_same<scalar_type, std::complex<float>>::value) ?
148 DFTI_SINGLE : DFTI_DOUBLE,
149 DFTI_COMPLEX, 3, size),
"mkl plan create 3d" );
150 check_error( DftiSetValue(
plan, DFTI_NUMBER_OF_TRANSFORMS, 1),
"mkl set howmany");
151 check_error( DftiSetValue(
plan, DFTI_PLACEMENT, DFTI_INPLACE),
"mkl set in place");
158 operator DFTI_DESCRIPTOR_HANDLE()
const{
return plan; }
184 template<
typename index>
186 size(box.size[dimension]), size2(0),
189 dist((dimension == box.order[0]) ? size : 1),
190 blocks((dimension == box.order[1]) ? box.osize(2) : 1),
191 block_stride(box.osize(0) * box.osize(1)),
192 total_size(box.count()),
196 template<
typename index>
198 size(box.size[std::min(dir1, dir2)]), size2(box.size[std::max(dir1, dir2)]),
199 blocks(1), block_stride(0), total_size(box.count())
204 if (std::min(odir1, odir2) == 0 and std::max(odir1, odir2) == 1){
207 embed = {
static_cast<MKL_LONG
>(stride),
static_cast<MKL_LONG
>(size)};
208 howmanyffts = box.
size[2];
209 }
else if (std::min(odir1, odir2) == 1 and std::max(odir1, odir2) == 2){
210 stride = box.
size[0];
212 embed = {
static_cast<MKL_LONG
>(stride),
static_cast<MKL_LONG
>(size) *
static_cast<MKL_LONG
>(stride)};
213 howmanyffts = box.
size[0];
217 embed = {
static_cast<MKL_LONG
>(stride),
static_cast<MKL_LONG
>(box.
size[1]) *
static_cast<MKL_LONG
>(box.
size[0])};
218 howmanyffts = box.
size[1];
222 template<
typename index>
224 size(box.size[0]), size2(box.size[1]), howmanyffts(box.size[2]),
226 blocks(1), block_stride(0),
227 total_size(box.count()),
232 void forward(std::complex<float> data[], std::complex<float>*)
const override{
234 for(
int i=0; i<blocks; i++){
235 float _Complex* block_data =
reinterpret_cast<float _Complex*
>(data + i * block_stride);
236 DftiComputeForward(*cplan, block_data);
240 void backward(std::complex<float> data[], std::complex<float>*)
const override{
242 for(
int i=0; i<blocks; i++){
243 float _Complex* block_data =
reinterpret_cast<float _Complex*
>(data + i * block_stride);
244 DftiComputeBackward(*cplan, block_data);
248 void forward(std::complex<double> data[], std::complex<double>*)
const override{
250 for(
int i=0; i<blocks; i++){
251 double _Complex* block_data =
reinterpret_cast<double _Complex*
>(data + i * block_stride);
252 DftiComputeForward(*zplan, block_data);
256 void backward(std::complex<double> data[], std::complex<double>*)
const override{
258 for(
int i=0; i<blocks; i++){
259 double _Complex* block_data =
reinterpret_cast<double _Complex*
>(data + i * block_stride);
260 DftiComputeBackward(*zplan, block_data);
265 void forward(
float const indata[], std::complex<float> outdata[], std::complex<float> *workspace)
const override{
266 for(
int i=0; i<total_size; i++) outdata[i] = std::complex<float>(indata[i]);
270 void backward(std::complex<float> indata[],
float outdata[], std::complex<float> *workspace)
const override{
272 for(
int i=0; i<total_size; i++) outdata[i] = std::real(indata[i]);
275 void forward(
double const indata[], std::complex<double> outdata[], std::complex<double> *workspace)
const override{
276 for(
int i=0; i<total_size; i++) outdata[i] = std::complex<double>(indata[i]);
280 void backward(std::complex<double> indata[],
double outdata[], std::complex<double> *workspace)
const override{
282 for(
int i=0; i<total_size; i++) outdata[i] = std::real(indata[i]);
286 int box_size()
const override{
return total_size; }
292 template<
typename scalar_type>
298 plan = std::unique_ptr<plan_mkl<scalar_type>>(
new plan_mkl<scalar_type>(size, howmanyffts, stride, dist));
300 plan = std::unique_ptr<plan_mkl<scalar_type>>(
new plan_mkl<scalar_type>(size, size2, embed, howmanyffts, dist));
304 int size, size2, howmanyffts, stride, dist, blocks, block_stride, total_size;
305 std::array<MKL_LONG, 2> embed;
306 mutable std::unique_ptr<plan_mkl<std::complex<float>>> cplan;
307 mutable std::unique_ptr<plan_mkl<std::complex<double>>> zplan;
314 template<
typename scalar_type, direction dir>
327 static_assert(std::is_same<scalar_type, float>::value or std::is_same<scalar_type, double>::value,
328 "plan_mkl_r2c requires scalar_type with float or double, see plan_mkl for complex types");
330 check_error( DftiCreateDescriptor(&
plan, (std::is_same<scalar_type,float>::value) ?
331 DFTI_SINGLE : DFTI_DOUBLE,
332 DFTI_REAL, 1,
static_cast<MKL_LONG
>(size)),
"mkl create r2c");
333 check_error( DftiSetValue(
plan, DFTI_NUMBER_OF_TRANSFORMS,
static_cast<MKL_LONG
>(howmanyffts)),
"mkl set howmany r2c");
334 check_error( DftiSetValue(
plan, DFTI_PLACEMENT, DFTI_NOT_INPLACE),
"mkl set not in place r2c");
335 check_error( DftiSetValue(
plan, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX),
"mkl conj storage cc");
336 MKL_LONG lstride[] = {0,
static_cast<MKL_LONG
>(stride)};
337 check_error( DftiSetValue(
plan, DFTI_INPUT_STRIDES, lstride),
"mkl set istride r2c");
338 check_error( DftiSetValue(
plan, DFTI_OUTPUT_STRIDES, lstride),
"mkl set ostride r2c");
340 check_error( DftiSetValue(
plan, DFTI_INPUT_DISTANCE,
static_cast<MKL_LONG
>(rdist)),
"mkl set rdist r2c");
341 check_error( DftiSetValue(
plan, DFTI_OUTPUT_DISTANCE,
static_cast<MKL_LONG
>(cdist)),
"mkl set cdist r2c");
343 check_error( DftiSetValue(
plan, DFTI_OUTPUT_DISTANCE,
static_cast<MKL_LONG
>(rdist)),
"mkl set back rdist r2c");
344 check_error( DftiSetValue(
plan, DFTI_INPUT_DISTANCE,
static_cast<MKL_LONG
>(cdist)),
"mkl set back cdist r2c");
353 operator DFTI_DESCRIPTOR_HANDLE()
const{
return plan; }
377 template<
typename index>
379 size(box.size[dimension]),
382 blocks((dimension == box.order[1]) ? box.osize(2) : 1),
383 rdist((dimension == box.order[0]) ? size : 1),
384 cdist((dimension == box.order[0]) ? size/2 + 1 : 1),
385 rblock_stride(box.osize(0) * box.osize(1)),
386 cblock_stride(box.osize(0) * (box.osize(1)/2 + 1)),
388 csize(box.r2c(dimension).count())
392 void forward(
float const indata[], std::complex<float> outdata[], std::complex<float>*)
const override{
394 for(
int i=0; i<blocks; i++){
395 float *rdata =
const_cast<float*
>(indata + i * rblock_stride);
396 float _Complex* cdata =
reinterpret_cast<float _Complex*
>(outdata + i * cblock_stride);
397 DftiComputeForward(*sforward, rdata, cdata);
401 void backward(std::complex<float> indata[],
float outdata[], std::complex<float>*)
const override{
402 make_plan(sbackward);
403 for(
int i=0; i<blocks; i++){
404 float _Complex* cdata =
const_cast<float _Complex*
>(
reinterpret_cast<float _Complex const*
>(indata + i * cblock_stride));
405 DftiComputeBackward(*sbackward, cdata, outdata + i * rblock_stride);
409 void forward(
double const indata[], std::complex<double> outdata[], std::complex<double>*)
const override{
411 for(
int i=0; i<blocks; i++){
412 double *rdata =
const_cast<double*
>(indata + i * rblock_stride);
413 double _Complex* cdata =
reinterpret_cast<double _Complex*
>(outdata + i * cblock_stride);
414 DftiComputeForward(*dforward, rdata, cdata);
418 void backward(std::complex<double> indata[],
double outdata[], std::complex<double>*)
const override{
419 make_plan(dbackward);
420 for(
int i=0; i<blocks; i++){
421 double _Complex* cdata =
const_cast<double _Complex*
>(
reinterpret_cast<double _Complex const*
>(indata + i * cblock_stride));
422 DftiComputeBackward(*dbackward, cdata, outdata + i * rblock_stride);
435 template<
typename scalar_type, direction dir>
440 int size, howmanyffts, stride, blocks;
441 int rdist, cdist, rblock_stride, cblock_stride, rsize, csize;
442 mutable std::unique_ptr<plan_mkl_r2c<float, direction::forward>> sforward;
443 mutable std::unique_ptr<plan_mkl_r2c<double, direction::forward>> dforward;
444 mutable std::unique_ptr<plan_mkl_r2c<float, direction::backward>> sbackward;
445 mutable std::unique_ptr<plan_mkl_r2c<double, direction::backward>> dbackward;
491 static const bool use_reorder =
false;
499 static const bool use_reorder =
true;
507 static const bool use_reorder =
true;
Base class for all backend executors.
Definition: heffte_common.h:486
virtual int complex_size() const
Return the size of the complex-box (r2c executors).
Definition: heffte_common.h:519
virtual void backward(float[], float *) const
Backward r2r, single precision.
Definition: heffte_common.h:495
virtual void forward(float[], float *) const
Forward r2r, single precision.
Definition: heffte_common.h:491
Wrapper to mkl API for real-to-complex transform with shortening of the data.
Definition: heffte_backend_mkl.h:366
int box_size() const override
Returns the size of the box with real data.
Definition: heffte_backend_mkl.h:427
int complex_size() const override
Returns the size of the box with complex coefficients.
Definition: heffte_backend_mkl.h:429
void forward(double const indata[], std::complex< double > outdata[], std::complex< double > *) const override
Forward transform, double precision.
Definition: heffte_backend_mkl.h:409
void forward(float const indata[], std::complex< float > outdata[], std::complex< float > *) const override
Forward transform, single precision.
Definition: heffte_backend_mkl.h:392
size_t workspace_size() const override
Return the size of the needed workspace.
Definition: heffte_backend_mkl.h:431
mkl_executor_r2c(void *, box3d< index > const box, int dimension)
Constructor defines the box and the dimension of reduction.
Definition: heffte_backend_mkl.h:378
void backward(std::complex< double > indata[], double outdata[], std::complex< double > *) const override
Backward transform, double precision.
Definition: heffte_backend_mkl.h:418
void backward(std::complex< float > indata[], float outdata[], std::complex< float > *) const override
Backward transform, single precision.
Definition: heffte_backend_mkl.h:401
Wrapper around the MKL API.
Definition: heffte_backend_mkl.h:175
virtual void backward(float[], float *) const
Bring forth method that have not been overloaded.
Definition: heffte_common.h:495
void forward(std::complex< double > data[], std::complex< double > *) const override
Forward fft, double-complex case.
Definition: heffte_backend_mkl.h:248
void forward(std::complex< float > data[], std::complex< float > *) const override
Forward fft, float-complex case.
Definition: heffte_backend_mkl.h:232
size_t workspace_size() const override
Return the size of the needed workspace.
Definition: heffte_backend_mkl.h:288
void forward(double const indata[], std::complex< double > outdata[], std::complex< double > *workspace) const override
Converts the deal data to complex and performs double-complex forward transform.
Definition: heffte_backend_mkl.h:275
virtual void forward(float[], float *) const
Bring forth method that have not been overloaded.
Definition: heffte_common.h:491
mkl_executor(void *, box3d< index > const box)
Merges three FFTs into one.
Definition: heffte_backend_mkl.h:223
int box_size() const override
Returns the size of the box.
Definition: heffte_backend_mkl.h:286
void backward(std::complex< double > indata[], double outdata[], std::complex< double > *workspace) const override
Performs backward double-complex transform and truncates the complex part of the result.
Definition: heffte_backend_mkl.h:280
mkl_executor(void *, box3d< index > const box, int dir1, int dir2)
Merges two FFTs into one.
Definition: heffte_backend_mkl.h:197
mkl_executor(void *, box3d< index > const box, int dimension)
Constructor, specifies the box and dimension.
Definition: heffte_backend_mkl.h:185
void backward(std::complex< float > data[], std::complex< float > *) const override
Backward fft, float-complex case.
Definition: heffte_backend_mkl.h:240
void backward(std::complex< double > data[], std::complex< double > *) const override
Backward fft, double-complex case.
Definition: heffte_backend_mkl.h:256
void forward(float const indata[], std::complex< float > outdata[], std::complex< float > *workspace) const override
Converts the deal data to complex and performs float-complex forward transform.
Definition: heffte_backend_mkl.h:265
void backward(std::complex< float > indata[], float outdata[], std::complex< float > *workspace) const override
Performs backward float-complex transform and truncates the complex part of the result.
Definition: heffte_backend_mkl.h:270
int fft1d_get_howmany(box3d< index > const box, int const dimension)
Return the number of 1-D ffts contained in the box in the given dimension.
Definition: heffte_geometry.h:159
int fft1d_get_stride(box3d< index > const box, int const dimension)
Return the stride of the 1-D ffts contained in the box in the given dimension.
Definition: heffte_geometry.h:169
@ forward
Forward DFT transform.
void check_error(MKL_LONG status, std::string const &function_name)
Checks the status of a call to the MKL backend.
Definition: heffte_backend_mkl.h:69
Namespace containing all HeFFTe methods and classes.
Definition: heffte_backend_cuda.h:38
Defines inverse mapping from the location tag to a default backend tag.
Definition: heffte_common.h:380
Allows to define whether a specific backend interface has been enabled.
Definition: heffte_common.h:201
Type-tag for the Cosine Transform using the MKL FFT backend.
Definition: heffte_common.h:136
Type-tag for the Sine Transform using the MKL FFT backend.
Definition: heffte_common.h:141
Type-tag for the MKL backend.
Definition: heffte_common.h:131
A generic container that describes a 3d box of indexes.
Definition: heffte_geometry.h:67
std::array< index, 3 > const size
The number of indexes in each direction.
Definition: heffte_geometry.h:129
int find_order(int dir) const
Returns the effective order of the direction (dir), 0 -> fast, 1 -> mid, 2 -> slow.
Definition: heffte_geometry.h:121
Defines a set of default plan options for a given backend.
Definition: heffte_common.h:642
Struct to specialize to allow HeFFTe to recognize custom single precision complex types.
Definition: heffte_utils.h:251
Struct to specialize to allow HeFFTe to recognize custom double precision complex types.
Definition: heffte_utils.h:269
void executor_r2c
Defines the real-to-complex executor.
Definition: heffte_backend_mkl.h:470
void executor_r2c
Defines the real-to-complex executor.
Definition: heffte_backend_mkl.h:482
Indicates the structure that will be used by the fft backend.
Definition: heffte_common.h:546
Unlike the C2C plan R2C is non-symmetric and it requires that the direction is built into the plan.
Definition: heffte_backend_mkl.h:315
DFTI_DESCRIPTOR_HANDLE plan
Identical to the float-complex specialization.
Definition: heffte_backend_mkl.h:355
plan_mkl_r2c(int size, int howmanyffts, int stride, int rdist, int cdist)
Constructor taking into account the different sizes for the real and complex parts.
Definition: heffte_backend_mkl.h:325
~plan_mkl_r2c()
Identical to the float-complex specialization.
Definition: heffte_backend_mkl.h:351
Base plan for backend::mkl, works only for float and double complex.
Definition: heffte_backend_mkl.h:84
plan_mkl(int size, int howmanyffts, int stride, int dist)
Constructor, takes inputs identical to MKL FFT descriptors.
Definition: heffte_backend_mkl.h:93
~plan_mkl()
Destructor, deletes the plan.
Definition: heffte_backend_mkl.h:156
plan_mkl(size_t size1, size_t size2, std::array< MKL_LONG, 2 > const &embed, size_t howmanyffts, size_t dist)
Constructor, takes inputs identical to MKL FFT descriptors.
Definition: heffte_backend_mkl.h:119
DFTI_DESCRIPTOR_HANDLE plan
The MKL opaque structure (pointer to struct).
Definition: heffte_backend_mkl.h:160
plan_mkl(int size1, int size2, int size3)
Constructor, takes inputs identical to MKL FFT descriptors.
Definition: heffte_backend_mkl.h:145
Template algorithm for the Sine and Cosine transforms.
Definition: heffte_r2r_executor.h:135