Skip to content

CudaNufftPipeline

class CudaNufftPipeline

Full GPU NUFFT pipeline — all intermediates stay on-device.

Both chains fold the centered-DFT fftshift/ifftshift into the index arithmetic of the kernel that already touches the grid on that side of the FFT, mirroring the Metal backend's Phase 2 fold (see MetalNufftPipeline.mm's nufft_forward_impl/nufft_adjoint_impl). There are no standalone shift kernel launches in either chain below — each arrow that would otherwise be a circshift pass is a shift baked into the adjacent kernel's read or write index instead:

Forward (image → k-space): deapodize → zero_pad(+ifftshift write) → cuFFT → gridding_forward(+fftshift read)

Adjoint (k-space → image): gridding_adjoint(+ifftshift write) → cuIFFT → crop_center(+fftshift read) → deapodize

Write-side folds (zero_pad, gridding_adjoint scatter) apply the shift as-is to the destination index; gather-side folds (gridding_forward, crop_center) apply the inverted offset (dim − s) % dim to the source index, computed at the call site in forward_device()/adjoint_device().

kernel_circshift_2d/3d (CudaNufftPipeline.cu) remain defined — the pipeline itself no longer dispatches them, but they stay available for any external caller that still wants a standalone circular shift.

Only input and output cross the PCIe bus (one cudaMemcpy each direction).

Functions

Name Description
forward Forward NUFFT: host pointers (copies H2D and D2H)
adjoint Adjoint NUFFT: host pointers (copies H2D and D2H)
forward_device Forward NUFFT: device pointers (no transfers — data stays on GPU)
adjoint_device Adjoint NUFFT: device pointers (no transfers — data stays on GPU)
forward_device_batched Batched forward NUFFT: numBatch independent transforms through one batched cuFFT plan + batched support/gridding kernel launches. Device layout mirrors CudaDftPipeline's batched contract: slice b's image lives at d_imagesIn + b2imageNumElems (interleaved complex, contiguous), slice b's samples at d_samplesOut + b2numSamples. numBatch == 1 is legal but forward_device() is the direct path for that case.
adjoint_device_batched Batched adjoint NUFFT: numBatch independent transforms, contiguous per-slice device layout (see forward_device_batched). Slice b's samples at d_samplesIn + b2numSamples, slice b's image output at d_imagesOut + b2imageNumElems.

Function Details

adjoint

void adjoint(const float* samplesIn, float* imageOut)

Adjoint NUFFT: host pointers (copies H2D and D2H)

adjoint_device

void adjoint_device(const float* d_samplesIn, float* d_imageOut)

Adjoint NUFFT: device pointers (no transfers — data stays on GPU)

adjoint_device_batched

void adjoint_device_batched(const float* d_samplesIn, float* d_imagesOut, int numBatch)

Batched adjoint NUFFT: numBatch independent transforms, contiguous per-slice device layout (see forward_device_batched). Slice b's samples at d_samplesIn + b2numSamples, slice b's image output at d_imagesOut + b2imageNumElems.

forward

void forward(const float* imageIn, float* samplesOut)

Forward NUFFT: host pointers (copies H2D and D2H)

forward_device

void forward_device(const float* d_imageIn, float* d_samplesOut)

Forward NUFFT: device pointers (no transfers — data stays on GPU)

forward_device_batched

void forward_device_batched(const float* d_imagesIn, float* d_samplesOut, int numBatch)

Batched forward NUFFT: numBatch independent transforms through one batched cuFFT plan + batched support/gridding kernel launches.

Device layout mirrors CudaDftPipeline's batched contract: slice b's image lives at d_imagesIn + b2imageNumElems (interleaved complex, contiguous), slice b's samples at d_samplesOut + b2numSamples. numBatch == 1 is legal but forward_device() is the direct path for that case.