Loading...
Searching...
No Matches
init.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * GPUFFTGrid — vendor-neutral GPU FFT grid interface.
5 *
6 * Extends the existing FFTGrid interface with single-precision (FP32)
7 * FFT capabilities for mixed-precision GPU computation. Provides both
8 * FP64 (inherited from FFTGrid) and FP32 (new) forward/inverse transforms.
9 *
10 * Each concrete implementation owns its own vendor FFT handles (e.g.,
11 * cuFFT plans or FFTW/vDSP plans).
12 *
13 * No CUDA headers. No Metal headers. Vendor-neutral interface only.
14 * Concrete implementations live in:
15 * - cuda.hpp / cuda.cpp (CudaGPUFFTGrid — cuFFT)
16 * - metal.hpp / metal.cpp (MetalGPUFFTGrid — FFTW FP64 + vDSP FP32)
17 */
18
23
24#include <complex>
25#include <memory>
26
27namespace q3 {
28
29/**
30 * GPUFFTGrid lives in q3::gpu (not q3::execution::gpu) because it belongs to layer_3
31 * (representation), while q3::execution is in layer_0 (core). Keeping it in q3::gpu
32 * avoids an upward layer dependency.
33 */
34namespace gpu {
35
36class GPUFFTGrid : public FFTGrid {
37 public:
38 /**
39 * Construct a GPU FFT grid backed by the given device.
40 *
41 * FFT plans are created during init(), not in the constructor.
42 * The device backend is stored for memory management and
43 * synchronization.
44 *
45 * @param device_backend Shared pointer to the GPU device backend.
46 * Must not be null.
47 */
48 explicit GPUFFTGrid(std::shared_ptr<execution::gpu::device::GPUDeviceBackend> device_backend)
49 : device_backend_(std::move(device_backend)) {}
50
51 ~GPUFFTGrid() override = default;
52
53 // ── Single-precision (FP32) FFT operations ───────────────────────────
54
55 /**
56 * Forward single-precision FFT: real-space → reciprocal-space (unnormalized).
57 *
58 * @param data In-out: single-precision complex grid data.
59 */
60 virtual void forward_single(ComplexSingle* data) const = 0;
61
62 /**
63 * Inverse single-precision FFT without normalization (raw backward).
64 *
65 * @param data In-out: single-precision complex grid data.
66 */
67 virtual void inverse_raw_single(ComplexSingle* data) const = 0;
68
69 /**
70 * Batched forward single-precision FFT on multiple contiguous grids.
71 *
72 * Each grid is total_grid_points() contiguous ComplexSingle values.
73 * Default loops over forward_single(); CUDA overrides with cufftPlanMany.
74 *
75 * @param data Pointer to batch_size contiguous FFT grids.
76 * @param batch_size Number of grids to transform.
77 */
78 virtual void forward_single_batch(ComplexSingle* data, int batch_size) const {
79 int grid_size = total_grid_points();
80 for (int batch_index = 0; batch_index < batch_size; ++batch_index) {
81 forward_single(data + batch_index * grid_size);
82 }
83 }
84
85 /**
86 * Batched inverse single-precision FFT on multiple contiguous grids.
87 *
88 * Each grid is total_grid_points() contiguous ComplexSingle values.
89 * Default loops over inverse_raw_single(); CUDA overrides with cufftPlanMany.
90 *
91 * @param data Pointer to batch_size contiguous FFT grids.
92 * @param batch_size Number of grids to transform.
93 */
94 virtual void inverse_raw_single_batch(ComplexSingle* data, int batch_size) const {
95 int grid_size = total_grid_points();
96 for (int batch_index = 0; batch_index < batch_size; ++batch_index) {
97 inverse_raw_single(data + batch_index * grid_size);
98 }
99 }
100
101 // ── Double-precision (FP64) FFT operations ───────────────────────────
102
103 /**
104 * Forward FFT (FP64). On CUDA, delegates to cuFFT. On Metal, falls back to
105 * CPU FFTW since Apple GPUs lack native FP64 compute.
106 *
107 * Default implementation delegates to the base FFTGrid (CPU FFTW).
108 * Subclasses with native FP64 GPU FFT support should override.
109 */
110 virtual void forward_transform(Complex* data) const {
111 // Delegates via virtual dispatch to the concrete subclass (e.g., SerialFFTGrid).
112 this->forward(data);
113 }
114
115 /**
116 * Inverse FFT (FP64). On CUDA, delegates to cuFFT. On Metal, falls back to
117 * CPU FFTW since Apple GPUs lack native FP64 compute.
118 *
119 * Default implementation delegates to the base FFTGrid (CPU FFTW).
120 * Subclasses with native FP64 GPU FFT support should override.
121 */
122 virtual void inverse_transform(Complex* data) const {
123 // Delegates via virtual dispatch to the concrete subclass (e.g., SerialFFTGrid).
124 this->inverse_raw(data);
125 }
126
127 /**
128 * Batched forward FP64 FFT on multiple contiguous grids.
129 *
130 * Each grid is total_grid_points() contiguous Complex values.
131 * Default loops over forward_transform(); CUDA overrides with cufftPlanMany.
132 *
133 * @param data Pointer to batch_size contiguous FFT grids.
134 * @param batch_size Number of grids to transform.
135 */
136 virtual void forward_transform_batch(Complex* data, int batch_size) const {
137 int grid_size = total_grid_points();
138 for (int batch_index = 0; batch_index < batch_size; ++batch_index) {
139 forward_transform(data + batch_index * grid_size);
140 }
141 }
142
143 /**
144 * Batched inverse FP64 FFT on multiple contiguous grids.
145 *
146 * Each grid is total_grid_points() contiguous Complex values.
147 * Default loops over inverse_transform(); CUDA overrides with cufftPlanMany.
148 *
149 * @param data Pointer to batch_size contiguous FFT grids.
150 * @param batch_size Number of grids to transform.
151 */
152 virtual void inverse_transform_batch(Complex* data, int batch_size) const {
153 int grid_size = total_grid_points();
154 for (int batch_index = 0; batch_index < batch_size; ++batch_index) {
155 inverse_transform(data + batch_index * grid_size);
156 }
157 }
158
159 /**
160 * Access the underlying GPU device backend.
161 */
165
166 /**
167 * Access the underlying GPU device backend (const).
168 */
172
173 protected:
174 std::shared_ptr<execution::gpu::device::GPUDeviceBackend> device_backend_;
175};
176
177} // namespace gpu
178} // namespace q3
virtual void forward(Complex *data) const =0
virtual int total_grid_points() const =0
virtual void inverse_raw(Complex *data) const =0
virtual void forward_transform(Complex *data) const
Definition init.hpp:110
virtual void inverse_raw_single_batch(ComplexSingle *data, int batch_size) const
Definition init.hpp:94
const execution::gpu::device::GPUDeviceBackend & device_backend() const
Definition init.hpp:169
std::shared_ptr< execution::gpu::device::GPUDeviceBackend > device_backend_
Definition init.hpp:174
virtual void forward_single(ComplexSingle *data) const =0
execution::gpu::device::GPUDeviceBackend & device_backend()
Definition init.hpp:162
virtual void inverse_raw_single(ComplexSingle *data) const =0
virtual void forward_transform_batch(Complex *data, int batch_size) const
Definition init.hpp:136
virtual void forward_single_batch(ComplexSingle *data, int batch_size) const
Definition init.hpp:78
virtual void inverse_transform(Complex *data) const
Definition init.hpp:122
GPUFFTGrid(std::shared_ptr< execution::gpu::device::GPUDeviceBackend > device_backend)
Definition init.hpp:48
virtual void inverse_transform_batch(Complex *data, int batch_size) const
Definition init.hpp:152
~GPUFFTGrid() override=default
std::complex< float > ComplexSingle
std::complex< double > Complex