
CuPy GPU 离散傅里叶变换完全指南cupyx.scipy.fft 模块 API 与代码兼容特性深度解析【免费下载链接】cupyNumPy SciPy for GPU项目地址: https://gitcode.com/GitHub_Trending/cu/cupy本指南系统讲解 CuPy 中面向 SciPy API 的 GPU 离散傅里叶变换模块cupyx.scipy.fft它覆盖快速傅里叶变换FFT、离散余弦/正弦变换DCT/DST、快速汉克尔变换FHT以及频移与频率轴等辅助函数。读完本文你将掌握该模块的完整函数清单、每个函数的参数语义n、axis、norm、overwrite_x、plan并理解 cuFFT plan 复用、scipy.fft后端机制、多 GPU 开关等五项代码兼容特性在源码层的实现方式从而在 GPU 上写出与 SciPy 等价且高性能的 FFT 代码。模块概览与文档定位cupyx.scipy.fft是 CuPy 对 SciPyscipy.fft的 GPU 实现其官方 API 参考位于仓库的 docs/source/reference/scipy_fft.rst对应更详细的使用指南见 docs/source/user_guide/fft.rst。模块入口文件 cupyx/scipy/fft/init.py 展示了其内部组织方式FFT 系列fft/ifft/fft2/rfft/hfft等 18 个函数来自 cupyx/scipy/fft/_fft.pyDCT/DST 系列dct/idct/dctn/dstn等 8 个函数来自 cupyx/scipy/fft/_realtransforms.pyFHT 系列fht/ifht来自 cupyx/scipy/fft/_fftlog.pynext_fast_len来自 cupyx/scipy/fft/_helper.pyfftshift、ifftshift、fftfreq、rfftfreq直接复用cupy.fft同名实现get_fft_plan从cupyx.scipy.fftpack导入其定义见 cupyx/scipy/fftpack/_fft.py。也就是说这个模块是一个「薄封装层」它不重新发明算法而是把 cuFFT 的能力以 SciPy 兼容的签名暴露给用户同时保留 CuPy 特有的 plan 管理与多 GPU 控制。快速傅里叶变换FFT函数族模块提供与scipy.fft完全对应的 18 个 FFT 函数类别函数复数输入一维fft、ifft复数输入二维fft2、ifft2复数输入 N 维fftn、ifftn实数输入一维rfft、irfft实数输入二维rfft2、irfft2实数输入 N 维rfftn、irfftn厄米对称输入hfft、ihfft、hfft2、ihfft2、hfftn、ihfftn以最常用的fft为例其完整签名为fft(x, nNone, axis-1, normNone, overwrite_xFalse, *, planNone)各参数语义如下x待变换的cupy.ndarrayn变换轴上的输出长度。None时取输入沿axis的长度若给定输入会被截断或零填充axis执行 FFT 的轴默认-1最后一维norm归一化模式取值backward、ortho或forward。默认None是backward的别名——对应 DFT 公式中正变换无缩放、逆变换缩放1/n的惯例ortho使正逆变换各缩放1/sqrt(n)forward则将1/n放到正变换上overwrite_x为True时允许破坏输入x的内容见下文兼容特性 2plan关键字专用参数传入由cupyx.scipy.fftpack.get_fft_plan生成的 cuFFT plan见下文兼容特性 1。None时 CuPy 自动生成 plan。从源码可见fft/ifft最终调用cupy.fft._fft._fft并分别指定cufft.CUFFT_FORWARD与cufft.CUFFT_INVERSE方向见 cupyx/scipy/fft/_fft.py。而fft2直接转发给fftn、rfft2转发给rfftn说明 N 维实现是唯一真实入口二维只是默认axes(-2, -1)的特例。实数 FFT 与输出形状规则实数输入的rfft只返回正频率分量含奈奎斯特频率因此输出更紧凑沿变换轴长度为n//2 1。对应地rfftn的输出最后一条变换轴长度为s[-1]//2 1见 cupyx/scipy/fft/_fft.pyirfftn在未指定s时输出最后一条变换轴长度为2*(m-1)其中m是输入最后一条变换轴的长度见 cupyx/scipy/fft/_fft.py。源码在内部使用 cuFFT 的R2C实数到复数与C2R复数到实数变换类型rfft调用_fft(..., cufft.CUFFT_FORWARD, R2C, ...)irfft调用_fft(..., cufft.CUFFT_INVERSE, C2R, ...)见 cupyx/scipy/fft/_fft.py 与 cupyx/scipy/fft/_fft.py。厄米对称 FFThfft 与 ihfft 的实现技巧hfft计算具有厄米对称性信号的 FFT其输出为实数。值得注意的是从源码看它并非调用独立的 cuFFT 例程而是通过共轭 实数 FFT 组合实现# hfft: 先共轭再走 irfft并交换归一化方向 return irfft(x.conj(), n, axis, _swap_direction(norm))ihfft则对应实现为rfft(x, n, axis, _swap_direction(norm)).conj()见 cupyx/scipy/fft/_fft.py。hfft2/ihfft2/hfftn/ihfftn也采用完全相同的套路分别基于irfft2/rfft2/irfftn/rfftn组合。这一点对使用者有两个直接含义这四个函数当前不支持plan参数传入非None的 plan 会抛出NotImplementedError源码中标注了# TODO(leofang): support R2C C2R plansoverwrite_x参数在hfft2/ihfft2/hfftn/ihfftn中同样未生效文档标注 currently not supported。离散余弦与正弦变换DCT / DST模块提供 8 个 DCT/DST 函数dct、idct、dctn、idctn、dst、idst、dstn、idstn。它们全部实现在 cupyx/scipy/fft/_realtransforms.py。支持范围仅类型 II 与 III一个重要的边界条件对应关联文档兼容特性 5目前只实现了类型 II 和类型 III 的 DCT/DST类型 I 与类型 IV 不可用。源码对此有明确约束if type in [1, 4]: raise NotImplementedError(Only DCT-II and DCT-III have been implemented.)其变换对关系为正变换dct(..., type2)的逆是idct(..., type2)而idct内部实际调用的是 DCT-III 例程——因为「DCT-III 是 DCT-II 的逆」反过来idct(type3)则调用 DCT-II 例程见 cupyx/scipy/fft/_realtransforms.py。dst/idst的逻辑与此对称。底层实现用 FFT 计算实到实变换cuFFT 本身不提供实到实real-to-real变换。_realtransforms.py文件头部的模块文档解释了解决思路长度 N 的 DCT 可以用长度 N 的 FFT 加上若干乘法与重排来计算实现参考了 Makhoul1980、Narasimha Peterson1978等经典工作并做了小幅修改以匹配 SciPy 的归一化约定DST 则通过对 DCT 做简单改动得到参考 Shao Johnson 2008。从源码结构可以还原 DCT-II 正变换的核心流水线cupyx/scipy/fft/_realtransforms.py_cook_shape处理n的截断/零填充_reshuffle_dct2将输入按奇偶下标重排DST 时对奇数下标取负把 DCT 变成可被 FFT 处理的形式根据norm计算归一化因子_get_dct_norm_factor调用模块内的_fft.fft做一次复数 FFT乘上由 ElementwiseKernel_mult_factor_dct2生成的旋转因子与缩放因子取实部cupy.realortho模式下再对第 0 个元素做sqrt(2)/2修正。也就是说DCT/DST 虽然走的是纯 Python cuFFT 组合路径但每一步都编译为 GPU kernel没有 CPU 回程。同时要注意DCT/DST 系列函数的签名里没有plan参数对应关联文档兼容特性 1 的例外说明这是当前实现的明确限制。归一化约定norm参数控制缩放方式与 SciPy 语义一致backward默认正变换无缩放逆变换缩放1/Northo正逆变换各缩放1/sqrt(2N)量级因子使变换矩阵正交化对一维数组dct(x, normortho)等价于 MATLAB 的dct(x)forward1/N缩放施加到正变换上逆变换无缩放。N 维 DCT/DSTdctn/idctn/dstn/idstn是沿多个轴可分离地应用一维变换_init_nd_shape_and_axes负责解析s输出形状元素为 -1 表示沿用输入对应维度与axes变换轴缺省为最后len(s)个轴随后循环对每个轴调用一维dct/idct等见 cupyx/scipy/fft/_realtransforms.py。此外对于复数输入这些函数会分别在实部与虚部上独立应用变换再合并。快速汉克尔变换FHT / FFTLog模块提供fht与ifht两个函数实现在 cupyx/scipy/fft/_fftlog.py实现紧密跟随 Hamilton2000的 Fortran 代码即 FFTLog 算法fht(a, dln, mu, offset0.0, bias0.0) ifht(A, dln, mu, offset0.0, bias0.0)参数含义a/A实数、周期、均匀对数间隔的输入数组多维时沿最后一维变换dln输入数组的均匀对数间隔mu汉克尔变换的阶数可为任意正负实数offset输出数组均匀对数间隔的偏移量可通过scipy.special.fhtoffset计算最优值bias幂律偏置power law bias的指数用于处理变换的奇异性。从源码看算法分三步先按bias对输入数组施加指数偏置再计算 FHT 系数数组u通过loggamma等特殊函数在 GPU 上生成见 cupyx/scipy/fft/_fftlog.py最后经rfft→ 乘/除系数 →irfft→ 反转的流程完成变换见 cupyx/scipy/fft/_fftlog.py。当变换或其逆为奇异时系数为inf或0函数会发出singular transform; consider changing the bias之类的警告并尽力修正后继续计算。辅助函数模块提供 5 个辅助函数其中 4 个直接复用cupy.fft函数用途fftshift将零频分量移到数组中心ifftshiftfftshift的逆操作fftfreq返回 FFT 采样频率rfftfreq返回实数 FFT 采样频率仅正频率next_fast_len计算下一个「快速」变换长度next_fast_len是唯一在模块内自研实现的辅助函数cupyx/scipy/fft/_helper.py。它以(2, 3, 5, 7)为素数因子集合用带记忆化的递归求最小的 target的「光滑数」。文档特别说明了两点其real参数仅用于兼容 SciPy 接口、实际不起作用并且返回值可能与scipy.fft.next_fast_len不同——因为 pocketfft 的素数因子集合与 cuFFT 的不同。这是选取 FFT 长度、避免性能回退的实用工具。代码兼容特性源码级解析关联文档列出 5 条与 SciPy 的代码兼容特性下面逐条结合源码展开。特性 1cuFFT plan 复用DCT/DST 除外cupyx.scipy.fft的所有 FFT 函数都接受关键字专用参数plan可复用一个已有的 cuFFT plan 来加速计算。plan 由cupyx.scipy.fftpack.get_fft_plan生成from cupyx.scipy.fft import get_fft_plan import cupy as cp a cp.random.random((4, 64, 64)).astype(cp.complex64) plan get_fft_plan(a, axes(1, 2), value_typeC2C) # 批量、C2C、二维变换get_fft_plan的参数包括aC 或 F 连续的输入数组、shape输出形状缺省取输入沿axes的长度、axes至多 3 个相邻轴且必须包含数组首轴或末轴、value_typeC2C复数到复数默认R2C实数到复数C2R复数到实数。返回的 plan 是cupy.cuda.cufft.Plan1d一维或PlanNdN 维。plan 的用法有两种见 docs/source/user_guide/fft.rst# 方式一显式传给 cupyx.scipy.fft 的 API其余参数必须与生成 plan 时一致 out cupyx.scipy.fft.fft2(a, axes(1, 2), planplan) # 方式二作为上下文管理器用于 cupy.fft API with plan: out cp.fft.fft2(a, axes(1, 2))生成 plan 时指定的形状、轴、value_type必须与后续变换调用完全匹配否则结果不可预期。例外DCT 与 DST 目前不支持plan参数见前文。另外需要配套说明的是当不需要手工管理 plan 时CuPy 自 v8 起默认启用内置 plan 缓存按设备、按线程隔离可通过cp.fft.config.get_plan_cache()查看命中情况这解释了为什么大多数情况下即使不传plan也能获得良好的复用性能详见 docs/source/user_guide/fft.rst。特性 2overwrite_x 语义与原地 FFT 的正确写法与scipy.fft一致所有 FFT 函数都有可选的overwrite_x参数默认False其语义是置为True时输入数组x可能而非必然被任意覆写。因此若要实现「原地」FFT正确做法始终是重新赋值给输入变量x cupyx.scipy.fft.fft(x, ..., overwrite_xTrue, ...)overwrite_xTrue允许实现层复用输入缓冲区、减少内存分配但源码也提醒例如 DCT/DST 的实现虽然接受该参数实际从不真正原地执行变换docstring 注明 In practice, the current implementation never performs the transform in-place。若依赖覆写行为来省内存请以各函数实际实现为准。特性 3作为 scipy.fft 的后端cupyx.scipy.fft实现了scipy.fft的 uarray 后端协议源码见 cupyx/scipy/fft/_fft.py模块级定义__ua_domain__ numpy.scipy.fft并通过__ua_convert__在需要时将 NumPy 数组转换为cupy.ndarraycoerceTrue时__ua_function__则把 SciPy 函数分派到本模块的实现表_implemented。所有 FFT/DCT/DST/FHT 函数都通过_implements(...)装饰器注册到这张表里。因此可以注册为scipy.fft的后端让scipy.fft同时处理 numpy 与 cupy 数组对应文档引用 docs/source/user_guide/fft.rstimport cupy as cp import cupyx.scipy.fft as cufft import scipy.fft # 一次性使用上下文管理器 a cp.random.random(100).astype(cp.complex64) with scipy.fft.set_backend(cufft): b scipy.fft.fft(a) # 等价于 cufft.fft(a) # 或全局注册 scipy.fft.set_global_backend(cufft) b scipy.fft.fft(a)注意若要在后端模式下使用显式plan参数需要 SciPy 1.5.0 及以上版本。这样便可在几乎不改动既有 SciPy 代码的情况下获得 GPU 加速。特性 4use_multi_gpus 多 GPU 开关布尔开关cupy.fft.config.use_multi_gpus同样作用于本模块的 FFT 函数。该开关定义于 cupy/fft/_config.py是一个contextvars.ContextVar默认False意味着它的生效范围可被上下文隔离。置为True后FFT 会跨多个 GPU 分片执行更重要的是手动调用cupyx.scipy.fftpack.get_fft_plan创建 plan 时也会尊重该开关——即自动生成多 GPU plan。反之在使用 plan 时cupy/fft/_fft.py会校验config.use_multi_gpus与 plan 的gpus属性是否一致避免单/多 GPU 语义错配见 cupy/fft/_fft.py。多 GPU 相关的高级控制设备列表等属实验性功能详见参考文档 docs/source/reference/fft.rst。特性 5DCT/DST 仅支持类型 II 与 III已在前文详述类型 I 与类型 IV 会抛出NotImplementedError使用前请确认变换类型在支持范围内见 cupyx/scipy/fft/_realtransforms.py。一个端到端示例综合以上内容下面是一个同时体现 plan 复用、overwrite_x与scipy.fft后端的完整示例import cupy as cp import cupyx.scipy.fft as cpx_fft from cupyx.scipy.fft import get_fft_plan # 1) 基本一维 FFT自动 plan x cp.random.random(1024).astype(cp.float32) X cpx_fft.rfft(x) # 输出长度 1024//2 1 513 xr cpx_fft.irfft(X, n1024) # 逆变换回实数 # 2) 显式 plan 复用批量二维 C2C a cp.random.random((4, 64, 64)).astype(cp.complex64) plan get_fft_plan(a, axes(1, 2), value_typeC2C) out cpx_fft.fft2(a, axes(1, 2), planplan) # 显式传 plan # 3) 借助 scipy.fft 后端透明加速既有代码 import scipy.fft scipy.fft.set_global_backend(cpx_fft) b cp.random.random(100).astype(cp.complex64) c scipy.fft.fft(b) # 等价于 cpx_fft.fft(b) # 4) 频移与频率轴 spec cpx_fft.fftshift(X) # 零频移到中心 freqs cpx_fft.rfftfreq(1024, d1.0) # 对应的频率坐标总结cupyx.scipy.fft以 SciPy 兼容签名为骨架把 cuFFT 的完整能力C2C/R2C/C2R、plan 缓存、多 GPU接入 CuPy 生态并在 DCT/DST通过 FFT 组合实现与 FHTFFTLog 算法上补齐了 cuFFT 原生不支持的实到实与对数间隔变换。使用时重点记住三个边界DCT/DST 仅支持类型 II/III 且无plan参数、hfft/ihfft系列暂不支持 plan、overwrite_xTrue只表示「允许覆写」而非保证原地。围绕这些约束你可以在 GPU 上放心地把 SciPy 的 FFT 代码平移到 CuPy并进一步通过 plan 复用获得可控的性能。【免费下载链接】cupyNumPy SciPy for GPU项目地址: https://gitcode.com/GitHub_Trending/cu/cupy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考