20#include <hip/hip_runtime.h>
21#include <hipfft/hipfft.h>
33void check_hipfft_error(hipfftResult result,
const char* operation) {
34 if (result != HIPFFT_SUCCESS) {
35 throw std::runtime_error(std::string(
"HIPGPUFFTGrid: ") + operation +
36 " failed with result " + std::to_string(
static_cast<int>(result)));
54 if (plan_fp64_ != 0) {
55 hipfftDestroy(plan_fp64_);
57 if (plan_fp32_ != 0) {
58 hipfftDestroy(plan_fp32_);
60 if (device_buffer_fp32_ !=
nullptr) {
61 hipFree(device_buffer_fp32_);
63 if (device_buffer_fp64_ !=
nullptr) {
64 hipFree(device_buffer_fp64_);
66 if (plan_fp32_batch_ != 0) {
67 hipfftDestroy(plan_fp32_batch_);
69 if (device_buffer_fp32_batch_ !=
nullptr) {
70 hipFree(device_buffer_fp32_batch_);
72 if (plan_fp64_batch_ != 0) {
73 hipfftDestroy(plan_fp64_batch_);
75 if (device_buffer_fp64_batch_ !=
nullptr) {
76 hipFree(device_buffer_fp64_batch_);
85 bool use_measured_planning =
false)
override {
87 serial_fft_grid_.
init(dimension_1, dimension_2, dimension_3, use_measured_planning);
91 hipfftPlan3d(&plan_fp64_, dimension_1, dimension_2, dimension_3, HIPFFT_Z2Z),
96 hipfftPlan3d(&plan_fp32_, dimension_1, dimension_2, dimension_3, HIPFFT_C2C),
102 const size_t buffer_size_fp32 =
103 static_cast<size_t>(total_grid_points_cached_) *
sizeof(hipfftComplex);
104 hipMalloc(&device_buffer_fp32_, buffer_size_fp32);
106 const size_t buffer_size_fp64 =
107 static_cast<size_t>(total_grid_points_cached_) *
sizeof(hipfftDoubleComplex);
108 hipMalloc(&device_buffer_fp64_, buffer_size_fp64);
131 serial_fft_grid_.
forward(data);
134 serial_fft_grid_.
inverse(data);
175 const size_t buffer_size =
176 static_cast<size_t>(total_grid_points_cached_) *
sizeof(hipfftComplex);
177 hipMemcpy(device_buffer_fp32_, data, buffer_size, hipMemcpyDefault);
180 hipfftExecC2C(plan_fp32_, device_buffer_fp32_, device_buffer_fp32_, HIPFFT_FORWARD),
181 "hipfftExecC2C forward");
183 hipMemcpy(data, device_buffer_fp32_, buffer_size, hipMemcpyDefault);
193 const size_t buffer_size =
194 static_cast<size_t>(total_grid_points_cached_) *
sizeof(hipfftComplex);
195 hipMemcpy(device_buffer_fp32_, data, buffer_size, hipMemcpyDefault);
198 hipfftExecC2C(plan_fp32_, device_buffer_fp32_, device_buffer_fp32_, HIPFFT_BACKWARD),
199 "hipfftExecC2C inverse");
201 hipMemcpy(data, device_buffer_fp32_, buffer_size, hipMemcpyDefault);
213 const size_t buffer_size =
214 static_cast<size_t>(total_grid_points_cached_) *
sizeof(hipfftDoubleComplex);
215 hipMemcpy(device_buffer_fp64_, data, buffer_size, hipMemcpyDefault);
218 hipfftExecZ2Z(plan_fp64_, device_buffer_fp64_, device_buffer_fp64_, HIPFFT_FORWARD),
219 "hipfftExecZ2Z forward");
221 hipMemcpy(data, device_buffer_fp64_, buffer_size, hipMemcpyDefault);
231 const size_t buffer_size =
232 static_cast<size_t>(total_grid_points_cached_) *
sizeof(hipfftDoubleComplex);
233 hipMemcpy(device_buffer_fp64_, data, buffer_size, hipMemcpyDefault);
236 hipfftExecZ2Z(plan_fp64_, device_buffer_fp64_, device_buffer_fp64_, HIPFFT_BACKWARD),
237 "hipfftExecZ2Z inverse");
239 hipMemcpy(data, device_buffer_fp64_, buffer_size, hipMemcpyDefault);
257 ensure_batch_resources(batch_size);
259 const size_t buffer_size =
260 static_cast<size_t>(total_grid_points_cached_) * batch_size *
sizeof(hipfftComplex);
261 hipMemcpy(device_buffer_fp32_batch_, data, buffer_size, hipMemcpyDefault);
263 check_hipfft_error(hipfftExecC2C(plan_fp32_batch_,
264 device_buffer_fp32_batch_,
265 device_buffer_fp32_batch_,
267 "hipfftExecC2C batched forward");
269 hipMemcpy(data, device_buffer_fp32_batch_, buffer_size, hipMemcpyDefault);
279 ensure_batch_resources(batch_size);
281 const size_t buffer_size =
282 static_cast<size_t>(total_grid_points_cached_) * batch_size *
sizeof(hipfftComplex);
283 hipMemcpy(device_buffer_fp32_batch_, data, buffer_size, hipMemcpyDefault);
285 check_hipfft_error(hipfftExecC2C(plan_fp32_batch_,
286 device_buffer_fp32_batch_,
287 device_buffer_fp32_batch_,
289 "hipfftExecC2C batched inverse");
291 hipMemcpy(data, device_buffer_fp32_batch_, buffer_size, hipMemcpyDefault);
302 ensure_batch_resources_fp64(batch_size);
304 const size_t buffer_size =
static_cast<size_t>(total_grid_points_cached_) * batch_size *
305 sizeof(hipfftDoubleComplex);
306 hipMemcpy(device_buffer_fp64_batch_, data, buffer_size, hipMemcpyDefault);
308 check_hipfft_error(hipfftExecZ2Z(plan_fp64_batch_,
309 device_buffer_fp64_batch_,
310 device_buffer_fp64_batch_,
312 "hipfftExecZ2Z batched forward");
314 hipMemcpy(data, device_buffer_fp64_batch_, buffer_size, hipMemcpyDefault);
323 ensure_batch_resources_fp64(batch_size);
325 const size_t buffer_size =
static_cast<size_t>(total_grid_points_cached_) * batch_size *
326 sizeof(hipfftDoubleComplex);
327 hipMemcpy(device_buffer_fp64_batch_, data, buffer_size, hipMemcpyDefault);
329 check_hipfft_error(hipfftExecZ2Z(plan_fp64_batch_,
330 device_buffer_fp64_batch_,
331 device_buffer_fp64_batch_,
333 "hipfftExecZ2Z batched inverse");
335 hipMemcpy(data, device_buffer_fp64_batch_, buffer_size, hipMemcpyDefault);
340 hipfftHandle plan_fp64_ = 0;
341 hipfftHandle plan_fp32_ = 0;
344 hipfftComplex* device_buffer_fp32_ =
nullptr;
345 hipfftDoubleComplex* device_buffer_fp64_ =
nullptr;
346 int total_grid_points_cached_ = 0;
349 mutable hipfftHandle plan_fp32_batch_ = 0;
350 mutable hipfftComplex* device_buffer_fp32_batch_ =
nullptr;
351 mutable int current_fp32_batch_size_ = 0;
354 mutable hipfftHandle plan_fp64_batch_ = 0;
355 mutable hipfftDoubleComplex* device_buffer_fp64_batch_ =
nullptr;
356 mutable int current_fp64_batch_size_ = 0;
361 void ensure_batch_resources(
int batch_size)
const {
362 if (batch_size == current_fp32_batch_size_) {
366 if (plan_fp32_batch_ != 0) {
367 hipfftDestroy(plan_fp32_batch_);
368 plan_fp32_batch_ = 0;
370 if (device_buffer_fp32_batch_ !=
nullptr) {
371 hipFree(device_buffer_fp32_batch_);
372 device_buffer_fp32_batch_ =
nullptr;
378 int distance = total_grid_points_cached_;
380 check_hipfft_error(hipfftPlanMany(&plan_fp32_batch_,
391 "hipfftPlanMany FP32 batch");
393 const size_t buffer_size =
394 static_cast<size_t>(total_grid_points_cached_) * batch_size *
sizeof(hipfftComplex);
395 hipMalloc(&device_buffer_fp32_batch_, buffer_size);
397 current_fp32_batch_size_ = batch_size;
403 void ensure_batch_resources_fp64(
int batch_size)
const {
404 if (batch_size == current_fp64_batch_size_) {
408 if (plan_fp64_batch_ != 0) {
409 hipfftDestroy(plan_fp64_batch_);
410 plan_fp64_batch_ = 0;
412 if (device_buffer_fp64_batch_ !=
nullptr) {
413 hipFree(device_buffer_fp64_batch_);
414 device_buffer_fp64_batch_ =
nullptr;
420 int distance = total_grid_points_cached_;
422 check_hipfft_error(hipfftPlanMany(&plan_fp64_batch_,
433 "hipfftPlanMany FP64 batch");
435 const size_t buffer_size =
static_cast<size_t>(total_grid_points_cached_) * batch_size *
436 sizeof(hipfftDoubleComplex);
437 hipMalloc(&device_buffer_fp64_batch_, buffer_size);
439 current_fp64_batch_size_ = batch_size;
443std::unique_ptr<GPUFFTGrid>
445 return std::make_unique<HIPGPUFFTGrid>(std::move(device_backend));
void inverse(Complex *data) const override
int local_grid_points() const override
int local_offset() const override
void forward(Complex *data) const override
void execute_forward_on_buffers() const override
void reduce_g_space(Complex *, int) const override
int grid_dimension_3() const override
int grid_dimension_1() const override
void init(int dimension_1, int dimension_2, int dimension_3, bool use_measured_planning=false) override
void inverse_raw(Complex *data) const override
Complex * output_buffer() const override
Complex * input_buffer() const override
void execute_inverse_raw_on_buffers() const override
int total_grid_points() const override
int grid_dimension_2() const override
int g_vector_to_fft_grid_index(int miller_1, int miller_2, int miller_3) const override
void prepare_forward_from_output() const override
execution::gpu::device::GPUDeviceBackend & device_backend()
~HIPGPUFFTGrid() override
Complex * input_buffer() const override
Complex * output_buffer() const override
void reduce_g_space(Complex *data, int number_of_elements) const override
int g_vector_to_fft_grid_index(int miller_1, int miller_2, int miller_3) const override
HIPGPUFFTGrid(std::shared_ptr< execution::gpu::device::GPUDeviceBackend > device_backend)
void forward_single(ComplexSingle *data) const override
void inverse(Complex *data) const override
void inverse_transform(Complex *data) const override
void inverse_raw_single(ComplexSingle *data) const override
void inverse_raw_single_batch(ComplexSingle *data, int batch_size) const override
void execute_inverse_raw_on_buffers() const override
int local_offset() const override
int local_grid_points() const override
void forward_transform_batch(Complex *data, int batch_size) const override
void prepare_forward_from_output() const override
int grid_dimension_2() const override
void forward_single_batch(ComplexSingle *data, int batch_size) const override
void inverse_transform_batch(Complex *data, int batch_size) const override
int grid_dimension_3() const override
void forward_transform(Complex *data) const override
void forward(Complex *data) const override
int total_grid_points() const override
void init(int dimension_1, int dimension_2, int dimension_3, bool use_measured_planning=false) override
void inverse_raw(Complex *data) const override
void execute_forward_on_buffers() const override
int grid_dimension_1() const override
std::unique_ptr< GPUFFTGrid > create_hip_gpu_fft_grid(std::shared_ptr< execution::gpu::device::GPUDeviceBackend > device_backend)
std::complex< float > ComplexSingle
std::complex< double > Complex