Highly Efficient FFT for Exascale: HeFFTe v2.3
heffte_common.h
1 /*
2  -- heFFTe --
3  Univ. of Tennessee, Knoxville
4  @date
5 */
6 
7 #ifndef HEFFFTE_COMMON_H
8 #define HEFFFTE_COMMON_H
9 
10 #include "heffte_geometry.h"
11 #include "heffte_trace.h"
12 
13 namespace heffte {
14 
30 namespace tag {
31 
38 struct cpu{};
45 struct gpu{};
46 
47 }
48 
53 namespace backend {
54 
59  template<typename location_tag> struct data_manipulator{};
60 
65  template<> struct data_manipulator<tag::cpu> {
67  using stream_type = void*;
69  template<typename source_type, typename destination_type>
70  static void copy_n(void*, source_type const source[], size_t num_entries, destination_type destination[]){
71  std::copy_n(source, num_entries, destination);
72  }
74  template<typename source_type, typename destination_type>
75  static void copy_n(source_type const source[], size_t num_entries, destination_type destination[]){
76  std::copy_n(source, num_entries, destination);
77  }
79  template<typename source_type, typename destination_type>
80  static void copy_device_to_host(void*, source_type const source[], size_t num_entries, destination_type destination[]){
81  std::copy_n(source, num_entries, destination);
82  }
84  template<typename source_type, typename destination_type>
85  static void copy_device_to_device(void*, source_type const source[], size_t num_entries, destination_type destination[]){
86  std::copy_n(source, num_entries, destination);
87  }
89  template<typename source_type, typename destination_type>
90  static void copy_host_to_device(void*, source_type const source[], size_t num_entries, destination_type destination[]){
91  std::copy_n(source, num_entries, destination);
92  }
93  };
94 
99  struct fftw{};
104  struct fftw_cos{};
109  struct fftw_sin{};
110 
115  struct stock{};
120  struct stock_cos{};
125  struct stock_sin{};
126 
131  struct mkl{};
136  struct mkl_cos{};
141  struct mkl_sin{};
142 
147  struct cufft{};
148 
153  struct cufft_cos{};
158  struct cufft_sin{};
159 
164  struct rocfft{};
169  struct rocfft_cos{};
174  struct rocfft_sin{};
175 
180  struct onemkl{};
185  struct onemkl_cos{};
190  struct onemkl_sin{};
191 
200  template<typename tag>
201  struct is_enabled : std::false_type{};
202 
211  template<typename backend_tag, typename std::enable_if<is_enabled<backend_tag>::value, void*>::type = nullptr>
216  template<typename T> using container = std::vector<T>;
217  };
218 
223  template<typename backend_tag, typename = void>
224  struct uses_gpu : std::false_type{};
225 
230  template<typename backend_tag>
231  struct uses_gpu<backend_tag,
232  typename std::enable_if<std::is_same<typename buffer_traits<backend_tag>::location, tag::gpu>::value, void>::type>
233  : std::true_type{};
234 
239  template<typename backend_tag>
240  inline std::string name(){ return "unknown"; }
241 
246  template<> inline std::string name<fftw>(){ return "fftw"; }
251  template<> inline std::string name<fftw_cos>(){ return "fftw-cos"; }
256  template<> inline std::string name<fftw_sin>(){ return "fftw-sin"; }
257 
262  template<> inline std::string name<stock>(){ return "stock"; }
267  template<> inline std::string name<stock_cos>(){ return "stock-cos"; }
272  template<> inline std::string name<stock_sin>(){ return "stock-sin"; }
273 
278  template<> inline std::string name<mkl>(){ return "mkl"; }
283  template<> inline std::string name<mkl_cos>(){ return "mkl-cos"; }
288  template<> inline std::string name<mkl_sin>(){ return "mkl-sin"; }
293  template<> inline std::string name<cufft>(){ return "cufft"; }
298  template<> inline std::string name<cufft_cos>(){ return "cufft-cos"; }
303  template<> inline std::string name<cufft_sin>(){ return "cufft-sin"; }
304 
309  template<> inline std::string name<rocfft>(){ return "rocfft"; }
314  template<> inline std::string name<rocfft_cos>(){ return "rocfft-cos"; }
319  template<> inline std::string name<rocfft_sin>(){ return "rocfft-sin"; }
320 
325  template<> inline std::string name<onemkl>(){ return "onemkl"; }
330  template<> inline std::string name<onemkl_cos>(){ return "onemkl-cos"; }
335  template<> inline std::string name<onemkl_sin>(){ return "onemkl-sin"; }
336 
341  template<> inline std::string name<tag::cpu>(){ return "cpu"; }
346  template<> inline std::string name<tag::gpu>(){ return "gpu"; }
347 
357  template<typename backend_tag>
360  device_instance(void* = nullptr){}
362  virtual ~device_instance() = default;
364  void* stream(){ return nullptr; }
366  void* stream() const{ return nullptr; }
368  void synchronize_device() const{}
370  using stream_type = void*;
371  };
372 
380  template<typename location_tag> struct default_backend{
382  using type = stock;
383  };
384 
389  template<typename backend_tag> struct uses_fft_types : std::true_type{};
390 
395  template<typename backend_tag, typename input, typename output, typename = void> struct check_types : std::false_type{};
396 
401  template<typename backend_tag, typename input, typename output> struct check_types<backend_tag, input, output,
402  typename std::enable_if<uses_fft_types<backend_tag>::value and (
403  (std::is_same<input, float>::value and is_ccomplex<output>::value)
404  or (std::is_same<input, double>::value and is_zcomplex<output>::value)
405  or (is_ccomplex<input>::value and is_ccomplex<output>::value)
406  or (is_zcomplex<input>::value and is_zcomplex<output>::value)
407  )>::type> : std::true_type{};
408 
413  template<> struct uses_fft_types<fftw_cos> : std::false_type{};
418  template<> struct uses_fft_types<fftw_sin> : std::false_type{};
423  template<> struct uses_fft_types<stock_cos> : std::false_type{};
428  template<> struct uses_fft_types<stock_sin> : std::false_type{};
433  template<> struct uses_fft_types<mkl_cos> : std::false_type{};
438  template<> struct uses_fft_types<mkl_sin> : std::false_type{};
443  template<> struct uses_fft_types<cufft_cos> : std::false_type{};
448  template<> struct uses_fft_types<cufft_sin> : std::false_type{};
453  template<> struct uses_fft_types<rocfft_cos> : std::false_type{};
458  template<> struct uses_fft_types<rocfft_sin> : std::false_type{};
463  template<> struct uses_fft_types<onemkl_cos> : std::false_type{};
468  template<> struct uses_fft_types<onemkl_sin> : std::false_type{};
469 
474  template<typename backend_tag, typename input, typename output> struct check_types<backend_tag, input, output,
475  typename std::enable_if<not uses_fft_types<backend_tag>::value and (
476  (std::is_same<input, float>::value and std::is_same<output, float>::value)
477  or (std::is_same<input, double>::value and std::is_same<output, double>::value)
478  )>::type> : std::true_type{};
479 
480 }
481 
487 public:
489  virtual ~executor_base() = default;
491  virtual void forward(float[], float*) const{}
493  virtual void forward(double[], double*) const{}
495  virtual void backward(float[], float*) const{}
497  virtual void backward(double[], double*) const{}
499  virtual void forward(std::complex<float>[], std::complex<float>*) const{}
501  virtual void forward(std::complex<double>[], std::complex<double>*) const{}
503  virtual void backward(std::complex<float>[], std::complex<float>*) const{}
505  virtual void backward(std::complex<double>[], std::complex<double>*) const{}
507  virtual void forward(float const[], std::complex<float>[], std::complex<float>*) const{}
509  virtual void forward(double const[], std::complex<double>[], std::complex<double>*) const{}
511  virtual void backward(std::complex<float>[], float[], std::complex<float>*) const{}
513  virtual void backward(std::complex<double>[], double[], std::complex<double>*) const{}
515  virtual int box_size() const{ return 0; }
517  virtual size_t workspace_size() const{ return 0; }
519  virtual int complex_size() const{ return box_size(); }
520 };
521 
526 template<typename scalar_type>
527 std::vector<scalar_type> make_buffer_container(void*, size_t size){
528  return std::vector<scalar_type>(size);
529 }
530 
535 enum class direction {
537  forward,
539  backward
540 };
541 
546 template<typename> struct one_dim_backend{};
547 
552 template<typename backend_tag, typename index>
553 static std::unique_ptr<typename one_dim_backend<backend_tag>::executor> make_executor(typename backend::device_instance<typename backend::buffer_traits<backend_tag>::location>::stream_type stream,
554  box3d<index> const box, int dimension){
555  return (box.empty()) ?
556  std::unique_ptr<typename one_dim_backend<backend_tag>::executor>() :
557  std::unique_ptr<typename one_dim_backend<backend_tag>::executor>(new typename one_dim_backend<backend_tag>::executor(stream, box, dimension));
558 }
563 template<typename backend_tag, typename index>
564 static std::unique_ptr<typename one_dim_backend<backend_tag>::executor> make_executor(typename backend::device_instance<typename backend::buffer_traits<backend_tag>::location>::stream_type stream,
565  box3d<index> const box, int dir1, int dir2){
566  return (box.empty()) ?
567  std::unique_ptr<typename one_dim_backend<backend_tag>::executor>() :
568  std::unique_ptr<typename one_dim_backend<backend_tag>::executor>(new typename one_dim_backend<backend_tag>::executor(stream, box, dir1, dir2));
569 }
574 template<typename backend_tag, typename index>
575 static std::unique_ptr<typename one_dim_backend<backend_tag>::executor> make_executor(typename backend::device_instance<typename backend::buffer_traits<backend_tag>::location>::stream_type stream,
576  box3d<index> const box){
577  return (box.empty()) ?
578  std::unique_ptr<typename one_dim_backend<backend_tag>::executor>() :
579  std::unique_ptr<typename one_dim_backend<backend_tag>::executor>(new typename one_dim_backend<backend_tag>::executor(stream, box));
580 }
585 template<typename backend_tag, typename index>
586 static std::unique_ptr<typename one_dim_backend<backend_tag>::executor_r2c> make_executor_r2c(typename backend::device_instance<typename backend::buffer_traits<backend_tag>::location>::stream_type stream,
587  box3d<index> const box, int dimension){
588  return (box.empty()) ?
589  std::unique_ptr<typename one_dim_backend<backend_tag>::executor_r2c>() :
590  std::unique_ptr<typename one_dim_backend<backend_tag>::executor_r2c>(new typename one_dim_backend<backend_tag>::executor_r2c(stream, box, dimension));
591 }
592 
597 template<typename backend_tag>
598 constexpr bool has_executor2d(){
599  // cosine transform variants don't have a 2D/3D version yet (due to the missing kernels)
600  // most backends are OK with the variants for 2D and 3D (stock isn't)
601  return not (std::is_same<backend_tag, backend::stock>::value
602  or std::is_same<backend_tag, backend::stock_cos>::value
603  or std::is_same<backend_tag, backend::fftw_cos>::value
604  or std::is_same<backend_tag, backend::mkl_cos>::value
605  or std::is_same<backend_tag, backend::cufft_cos>::value
606  or std::is_same<backend_tag, backend::rocfft_cos>::value
607  or std::is_same<backend_tag, backend::onemkl_cos>::value
608  or std::is_same<backend_tag, backend::stock_sin>::value
609  or std::is_same<backend_tag, backend::fftw_sin>::value
610  or std::is_same<backend_tag, backend::mkl_sin>::value
611  or std::is_same<backend_tag, backend::cufft_sin>::value
612  or std::is_same<backend_tag, backend::rocfft_sin>::value
613  or std::is_same<backend_tag, backend::onemkl_sin>::value
614  );
615 }
620 template<typename backend_tag>
621 constexpr bool has_executor3d(){
622  return not (std::is_same<backend_tag, backend::stock>::value
623  or std::is_same<backend_tag, backend::stock_cos>::value
624  or std::is_same<backend_tag, backend::fftw_cos>::value
625  or std::is_same<backend_tag, backend::mkl_cos>::value
626  or std::is_same<backend_tag, backend::cufft_cos>::value
627  or std::is_same<backend_tag, backend::rocfft_cos>::value
628  or std::is_same<backend_tag, backend::onemkl_cos>::value
629  or std::is_same<backend_tag, backend::stock_sin>::value
630  or std::is_same<backend_tag, backend::fftw_sin>::value
631  or std::is_same<backend_tag, backend::mkl_sin>::value
632  or std::is_same<backend_tag, backend::cufft_sin>::value
633  or std::is_same<backend_tag, backend::rocfft_sin>::value
634  or std::is_same<backend_tag, backend::onemkl_sin>::value
635  );
636 }
637 
642 template<typename> struct default_plan_options{};
643 
644 }
645 
646 #endif // #ifndef HEFFTE_COMMON_H
Base class for all backend executors.
Definition: heffte_common.h:486
virtual void backward(std::complex< double >[], double[], std::complex< double > *) const
Backward FFT real-to-complex, double precision.
Definition: heffte_common.h:513
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 size_t workspace_size() const
Return the workspace of the size.
Definition: heffte_common.h:517
virtual void forward(std::complex< double >[], std::complex< double > *) const
Forward FFT, double precision.
Definition: heffte_common.h:501
virtual void forward(float const[], std::complex< float >[], std::complex< float > *) const
Forward FFT real-to-complex, single precision.
Definition: heffte_common.h:507
virtual ~executor_base()=default
Virtual destructor.
virtual void forward(float[], float *) const
Forward r2r, single precision.
Definition: heffte_common.h:491
virtual void forward(double[], double *) const
Forward r2r, double precision.
Definition: heffte_common.h:493
virtual void backward(std::complex< double >[], std::complex< double > *) const
Backward FFT, double precision.
Definition: heffte_common.h:505
virtual void forward(std::complex< float >[], std::complex< float > *) const
Forward FFT, single precision.
Definition: heffte_common.h:499
virtual void backward(std::complex< float >[], float[], std::complex< float > *) const
Backward FFT real-to-complex, single precision.
Definition: heffte_common.h:511
virtual void backward(std::complex< float >[], std::complex< float > *) const
Backward FFT, single precision.
Definition: heffte_common.h:503
virtual void backward(double[], double *) const
Backward r2r, double precision.
Definition: heffte_common.h:497
virtual int box_size() const
Return the size of the box.
Definition: heffte_common.h:515
virtual void forward(double const[], std::complex< double >[], std::complex< double > *) const
Forward FFT real-to-complex, double precision.
Definition: heffte_common.h:509
std::vector< scalar_type > make_buffer_container(void *, size_t size)
Factory method to create new buffer container for the CPU backends.
Definition: heffte_common.h:527
std::string name()
Returns the human readable name of the backend.
Definition: heffte_common.h:240
constexpr bool has_executor3d()
Defines whether the executor has a 3D version (single rank).
Definition: heffte_common.h:621
constexpr bool has_executor2d()
Defines whether the executor has a 2D version (slabs).
Definition: heffte_common.h:598
direction
Indicates the direction of the FFT (internal use only).
Definition: heffte_common.h:535
@ backward
Inverse DFT transform.
@ forward
Forward DFT transform.
std::string name< cufft_cos >()
Returns the human readable name of the cuFFT backend.
Definition: heffte_common.h:298
std::string name< cufft_sin >()
Returns the human readable name of the cuFFT backend.
Definition: heffte_common.h:303
std::string name< cufft >()
Returns the human readable name of the cuFFT backend.
Definition: heffte_common.h:293
std::string name< fftw_cos >()
Returns the human readable name of the FFTW backend.
Definition: heffte_common.h:251
std::string name< fftw >()
Returns the human readable name of the FFTW backend.
Definition: heffte_common.h:246
std::string name< fftw_sin >()
Returns the human readable name of the FFTW backend.
Definition: heffte_common.h:256
std::string name< mkl_sin >()
Returns the human readable name of the MKL backend.
Definition: heffte_common.h:288
std::string name< mkl >()
Returns the human readable name of the MKL backend.
Definition: heffte_common.h:278
std::string name< mkl_cos >()
Returns the human readable name of the MKL backend.
Definition: heffte_common.h:283
std::string name< onemkl >()
Returns the human readable name of the oneMKL backend.
Definition: heffte_common.h:325
std::string name< onemkl_sin >()
Returns the human readable name of the oneMKL backend.
Definition: heffte_common.h:335
std::string name< onemkl_cos >()
Returns the human readable name of the oneMKL backend.
Definition: heffte_common.h:330
std::string name< rocfft_cos >()
Returns the human readable name of the rocFFT backend.
Definition: heffte_common.h:314
std::string name< rocfft >()
Returns the human readable name of the rocFFT backend.
Definition: heffte_common.h:309
std::string name< rocfft_sin >()
Returns the human readable name of the rocFFT backend.
Definition: heffte_common.h:319
std::string name< stock_sin >()
Returns the human readable name of the stock backend.
Definition: heffte_common.h:272
std::string name< stock >()
Returns the human readable name of the stock backend.
Definition: heffte_common.h:262
std::string name< stock_cos >()
Returns the human readable name of the stock backend.
Definition: heffte_common.h:267
Namespace containing all HeFFTe methods and classes.
Definition: heffte_backend_cuda.h:38
Defines the container for the temporary buffers.
Definition: heffte_common.h:212
tag::cpu location
Tags the raw-array location tag::cpu or tag::gpu, used by the packers.
Definition: heffte_common.h:214
std::vector< T > container
Defines the container template to use for the temporary buffers in heffte::fft3d.
Definition: heffte_common.h:216
Set to true/false type depending whether the types are compatible with the backend transform.
Definition: heffte_common.h:395
Type-tag for the Cosine Transform using the cuFFT backend.
Definition: heffte_common.h:153
Type-tag for the Sine Transform using the cuFFT backend.
Definition: heffte_common.h:158
Type-tag for the cuFFT backend.
Definition: heffte_common.h:147
static void copy_n(source_type const source[], size_t num_entries, destination_type destination[])
Wrapper around std::copy_n().
Definition: heffte_common.h:75
static void copy_device_to_device(void *, source_type const source[], size_t num_entries, destination_type destination[])
Wrapper around std::copy_n().
Definition: heffte_common.h:85
static void copy_device_to_host(void *, source_type const source[], size_t num_entries, destination_type destination[])
Wrapper around std::copy_n().
Definition: heffte_common.h:80
static void copy_n(void *, source_type const source[], size_t num_entries, destination_type destination[])
Wrapper around std::copy_n().
Definition: heffte_common.h:70
void * stream_type
The stream type for the device.
Definition: heffte_common.h:67
static void copy_host_to_device(void *, source_type const source[], size_t num_entries, destination_type destination[])
Wrapper around std::copy_n().
Definition: heffte_common.h:90
Common data-transfer operations, must be specializes for each location (cpu/gpu).
Definition: heffte_common.h:59
Defines inverse mapping from the location tag to a default backend tag.
Definition: heffte_common.h:380
Holds the auxiliary variables needed by each backend.
Definition: heffte_common.h:358
void synchronize_device() const
Syncs the execution with the queue, no-op in the CPU case.
Definition: heffte_common.h:368
void * stream_type
The type for the internal stream, the cpu uses just a void pointer.
Definition: heffte_common.h:370
void * stream()
Returns the nullptr.
Definition: heffte_common.h:364
device_instance(void *=nullptr)
Empty constructor.
Definition: heffte_common.h:360
virtual ~device_instance()=default
Default destructor.
void * stream() const
Returns the nullptr (const case).
Definition: heffte_common.h:366
Type-tag for the Cosine Transform using the FFTW backend.
Definition: heffte_common.h:104
Type-tag for the Sine Transform using the FFTW backend.
Definition: heffte_common.h:109
Type-tag for the FFTW backend.
Definition: heffte_common.h:99
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
Type-tag for the Cosine Transform using the oneMKL backend.
Definition: heffte_common.h:185
Type-tag for the Sine Transform using the oneMKL backend.
Definition: heffte_common.h:190
Type-tag for the oneMKL backend.
Definition: heffte_common.h:180
Type-tag for the Cosine Transform using the rocFFT backend.
Definition: heffte_common.h:169
Type-tag for the Sine Transform using the rocFFT backend.
Definition: heffte_common.h:174
Type-tag for the rocFFT backend.
Definition: heffte_common.h:164
Type-tag for the Cosine Transform using the stock FFT backend.
Definition: heffte_common.h:120
Type-tag for the Sine Transform using the stock FFT backend.
Definition: heffte_common.h:125
Type-tag for the stock FFT backend.
Definition: heffte_common.h:115
Defines whether the backend accepts the standard FFT real-complex or complex-complex transform.
Definition: heffte_common.h:389
Struct that specializes to true type if the location of the backend is on the gpu (false type otherwi...
Definition: heffte_common.h:224
A generic container that describes a 3d box of indexes.
Definition: heffte_geometry.h:67
bool empty() const
Returns true if the box contains no indexes.
Definition: heffte_geometry.h:84
Defines a set of default plan options for a given backend.
Definition: heffte_common.h:642
Indicates the structure that will be used by the fft backend.
Definition: heffte_common.h:546
Indicates the use of cpu backend and that all input/output data and arrays will be bound to the cpu.
Definition: heffte_common.h:38
Indicates the use of gpu backend and that all input/output data and arrays will be bound to the gpu d...
Definition: heffte_common.h:45