nvmath-python 0.9.0__cp314-cp314-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. nvmath/__init__.pxd +0 -0
  2. nvmath/__init__.py +45 -0
  3. nvmath/_internal/__init__.py +0 -0
  4. nvmath/_internal/attribute_ifc_factory.py +330 -0
  5. nvmath/_internal/layout.py +70 -0
  6. nvmath/_internal/templates.py +383 -0
  7. nvmath/_utils.py +150 -0
  8. nvmath/bindings/__init__.py +51 -0
  9. nvmath/bindings/_internal/__init__.pxd +0 -0
  10. nvmath/bindings/_internal/__init__.py +0 -0
  11. nvmath/bindings/_internal/cublas.cp314-win_amd64.pyd +0 -0
  12. nvmath/bindings/_internal/cublas.pxd +530 -0
  13. nvmath/bindings/_internal/cublasLt.cp314-win_amd64.pyd +0 -0
  14. nvmath/bindings/_internal/cublasLt.pxd +59 -0
  15. nvmath/bindings/_internal/cublasMp.pxd +52 -0
  16. nvmath/bindings/_internal/cudss.cp314-win_amd64.pyd +0 -0
  17. nvmath/bindings/_internal/cudss.pxd +47 -0
  18. nvmath/bindings/_internal/cufft.cp314-win_amd64.pyd +0 -0
  19. nvmath/bindings/_internal/cufft.pxd +70 -0
  20. nvmath/bindings/_internal/cufftMp.pxd +77 -0
  21. nvmath/bindings/_internal/curand.cp314-win_amd64.pyd +0 -0
  22. nvmath/bindings/_internal/curand.pxd +42 -0
  23. nvmath/bindings/_internal/cusolver.cp314-win_amd64.pyd +0 -0
  24. nvmath/bindings/_internal/cusolver.pxd +15 -0
  25. nvmath/bindings/_internal/cusolverDn.cp314-win_amd64.pyd +0 -0
  26. nvmath/bindings/_internal/cusolverDn.pxd +406 -0
  27. nvmath/bindings/_internal/cusparse.cp314-win_amd64.pyd +0 -0
  28. nvmath/bindings/_internal/cusparse.pxd +277 -0
  29. nvmath/bindings/_internal/cusparseLt.cp314-win_amd64.pyd +0 -0
  30. nvmath/bindings/_internal/cusparseLt.pxd +48 -0
  31. nvmath/bindings/_internal/cutensor.cp314-win_amd64.pyd +0 -0
  32. nvmath/bindings/_internal/cutensor.pxd +58 -0
  33. nvmath/bindings/_internal/mathdx.cp314-win_amd64.pyd +0 -0
  34. nvmath/bindings/_internal/mathdx.pxd +116 -0
  35. nvmath/bindings/_internal/nvshmem.pxd +29 -0
  36. nvmath/bindings/_internal/utils.cp314-win_amd64.pyd +0 -0
  37. nvmath/bindings/_internal/utils.pxd +179 -0
  38. nvmath/bindings/_internal/utils.pyi +10 -0
  39. nvmath/bindings/cublas.cp314-win_amd64.pyd +0 -0
  40. nvmath/bindings/cublas.pxd +558 -0
  41. nvmath/bindings/cublas.pyi +746 -0
  42. nvmath/bindings/cublasLt.cp314-win_amd64.pyd +0 -0
  43. nvmath/bindings/cublasLt.pxd +109 -0
  44. nvmath/bindings/cublasLt.pyi +1337 -0
  45. nvmath/bindings/cublasMp.pxd +85 -0
  46. nvmath/bindings/cublasMp.pyi +219 -0
  47. nvmath/bindings/cudss.cp314-win_amd64.pyd +0 -0
  48. nvmath/bindings/cudss.pxd +86 -0
  49. nvmath/bindings/cudss.pyi +282 -0
  50. nvmath/bindings/cufft.cp314-win_amd64.pyd +0 -0
  51. nvmath/bindings/cufft.pxd +118 -0
  52. nvmath/bindings/cufft.pyi +241 -0
  53. nvmath/bindings/cufftMp.pxd +124 -0
  54. nvmath/bindings/cufftMp.pyi +260 -0
  55. nvmath/bindings/curand.cp314-win_amd64.pyd +0 -0
  56. nvmath/bindings/curand.pxd +71 -0
  57. nvmath/bindings/curand.pyi +159 -0
  58. nvmath/bindings/cusolver.cp314-win_amd64.pyd +0 -0
  59. nvmath/bindings/cusolver.pxd +62 -0
  60. nvmath/bindings/cusolver.pyi +242 -0
  61. nvmath/bindings/cusolverDn.cp314-win_amd64.pyd +0 -0
  62. nvmath/bindings/cusolverDn.pxd +430 -0
  63. nvmath/bindings/cusolverDn.pyi +416 -0
  64. nvmath/bindings/cusparse.cp314-win_amd64.pyd +0 -0
  65. nvmath/bindings/cusparse.pxd +338 -0
  66. nvmath/bindings/cusparse.pyi +659 -0
  67. nvmath/bindings/cusparseLt.cp314-win_amd64.pyd +0 -0
  68. nvmath/bindings/cusparseLt.pxd +99 -0
  69. nvmath/bindings/cusparseLt.pyi +198 -0
  70. nvmath/bindings/cutensor.cp314-win_amd64.pyd +0 -0
  71. nvmath/bindings/cutensor.pxd +98 -0
  72. nvmath/bindings/cutensor.pyi +294 -0
  73. nvmath/bindings/cycublas.cp314-win_amd64.pyd +0 -0
  74. nvmath/bindings/cycublas.pxd +684 -0
  75. nvmath/bindings/cycublasLt.cp314-win_amd64.pyd +0 -0
  76. nvmath/bindings/cycublasLt.pxd +1055 -0
  77. nvmath/bindings/cycublasMp.pxd +183 -0
  78. nvmath/bindings/cycudss.cp314-win_amd64.pyd +0 -0
  79. nvmath/bindings/cycudss.pxd +224 -0
  80. nvmath/bindings/cycufft.cp314-win_amd64.pyd +0 -0
  81. nvmath/bindings/cycufft.pxd +326 -0
  82. nvmath/bindings/cycufftMp.pxd +334 -0
  83. nvmath/bindings/cycurand.cp314-win_amd64.pyd +0 -0
  84. nvmath/bindings/cycurand.pxd +146 -0
  85. nvmath/bindings/cycusolver.cp314-win_amd64.pyd +0 -0
  86. nvmath/bindings/cycusolver.pxd +154 -0
  87. nvmath/bindings/cycusolverDn.cp314-win_amd64.pyd +0 -0
  88. nvmath/bindings/cycusolverDn.pxd +446 -0
  89. nvmath/bindings/cycusparse.cp314-win_amd64.pyd +0 -0
  90. nvmath/bindings/cycusparse.pxd +470 -0
  91. nvmath/bindings/cycusparseLt.cp314-win_amd64.pyd +0 -0
  92. nvmath/bindings/cycusparseLt.pxd +150 -0
  93. nvmath/bindings/cycutensor.cp314-win_amd64.pyd +0 -0
  94. nvmath/bindings/cycutensor.pxd +192 -0
  95. nvmath/bindings/cymathdx.cp314-win_amd64.pyd +0 -0
  96. nvmath/bindings/cymathdx.pxd +552 -0
  97. nvmath/bindings/cynvshmem.pxd +126 -0
  98. nvmath/bindings/mathdx.cp314-win_amd64.pyd +0 -0
  99. nvmath/bindings/mathdx.pxd +182 -0
  100. nvmath/bindings/mathdx.pyi +1244 -0
  101. nvmath/bindings/nvpl/__init__.pxd +0 -0
  102. nvmath/bindings/nvpl/__init__.py +13 -0
  103. nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
  104. nvmath/bindings/nvpl/_internal/__init__.py +0 -0
  105. nvmath/bindings/nvpl/_internal/blas.cp314-win_amd64.pyd +0 -0
  106. nvmath/bindings/nvpl/_internal/blas.pxd +125 -0
  107. nvmath/bindings/nvpl/_internal/fft.cp314-win_amd64.pyd +0 -0
  108. nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
  109. nvmath/bindings/nvpl/blas.cp314-win_amd64.pyd +0 -0
  110. nvmath/bindings/nvpl/blas.pxd +85 -0
  111. nvmath/bindings/nvpl/blas.pyi +122 -0
  112. nvmath/bindings/nvpl/cyblas.cp314-win_amd64.pyd +0 -0
  113. nvmath/bindings/nvpl/cyblas.pxd +166 -0
  114. nvmath/bindings/nvpl/cyfft.cp314-win_amd64.pyd +0 -0
  115. nvmath/bindings/nvpl/cyfft.pxd +92 -0
  116. nvmath/bindings/nvpl/fft.cp314-win_amd64.pyd +0 -0
  117. nvmath/bindings/nvpl/fft.pxd +100 -0
  118. nvmath/bindings/nvpl/fft.pyi +100 -0
  119. nvmath/bindings/nvshmem.pxd +54 -0
  120. nvmath/bindings/nvshmem.pyi +179 -0
  121. nvmath/device/__init__.py +21 -0
  122. nvmath/device/_deprecated.py +33 -0
  123. nvmath/device/common.py +313 -0
  124. nvmath/device/common_backend.py +131 -0
  125. nvmath/device/common_cuda.py +201 -0
  126. nvmath/device/common_numba.py +310 -0
  127. nvmath/device/common_opaque_tensor.py +201 -0
  128. nvmath/device/cublasdx.py +1805 -0
  129. nvmath/device/cublasdx_backend.py +807 -0
  130. nvmath/device/cublasdx_numba.py +1612 -0
  131. nvmath/device/cufftdx.py +510 -0
  132. nvmath/device/cufftdx_backend.py +196 -0
  133. nvmath/device/cufftdx_numba.py +196 -0
  134. nvmath/device/curand_kernel.py +9147 -0
  135. nvmath/device/cusolverdx.py +2690 -0
  136. nvmath/device/cusolverdx_backend.py +440 -0
  137. nvmath/device/cusolverdx_numba.py +1624 -0
  138. nvmath/device/llvm_array.py +29 -0
  139. nvmath/device/random.py +445 -0
  140. nvmath/device/random_helpers.py +23 -0
  141. nvmath/device/random_states.py +187 -0
  142. nvmath/device/types.py +147 -0
  143. nvmath/device/vector_types_numba.py +203 -0
  144. nvmath/distributed/__init__.py +205 -0
  145. nvmath/distributed/_internal/__init__.py +0 -0
  146. nvmath/distributed/_internal/nvshmem.py +302 -0
  147. nvmath/distributed/_internal/tensor_ifc.py +67 -0
  148. nvmath/distributed/_internal/tensor_ifc_cupy.py +62 -0
  149. nvmath/distributed/_internal/tensor_ifc_host_device.py +165 -0
  150. nvmath/distributed/_internal/tensor_ifc_numpy.py +41 -0
  151. nvmath/distributed/_internal/tensor_ifc_torch.py +141 -0
  152. nvmath/distributed/_internal/tensor_wrapper.py +78 -0
  153. nvmath/distributed/_utils.py +167 -0
  154. nvmath/distributed/distribution.py +770 -0
  155. nvmath/distributed/fft/__init__.py +7 -0
  156. nvmath/distributed/fft/_configuration.py +79 -0
  157. nvmath/distributed/fft/fft.py +2801 -0
  158. nvmath/distributed/linalg/__init__.py +12 -0
  159. nvmath/distributed/linalg/_internal/__init__.py +3 -0
  160. nvmath/distributed/linalg/_internal/epilog_protocol.py +496 -0
  161. nvmath/distributed/linalg/_internal/matmul_desc_ifc.py +28 -0
  162. nvmath/distributed/linalg/advanced/__init__.py +8 -0
  163. nvmath/distributed/linalg/advanced/_configuration.py +166 -0
  164. nvmath/distributed/linalg/advanced/matmulmod.py +2908 -0
  165. nvmath/distributed/process_group.py +408 -0
  166. nvmath/distributed/reshape/__init__.py +6 -0
  167. nvmath/distributed/reshape/_configuration.py +39 -0
  168. nvmath/distributed/reshape/reshape.py +1256 -0
  169. nvmath/fft/__init__.py +7 -0
  170. nvmath/fft/_configuration.py +208 -0
  171. nvmath/fft/_exec_utils.py +109 -0
  172. nvmath/fft/_helpers.py +237 -0
  173. nvmath/fft/fft.py +2903 -0
  174. nvmath/internal/__init__.pxd +3 -0
  175. nvmath/internal/__init__.py +10 -0
  176. nvmath/internal/_bindings.cp314-win_amd64.pyd +0 -0
  177. nvmath/internal/_bindings.pxd +12 -0
  178. nvmath/internal/_device_utils.py +54 -0
  179. nvmath/internal/enum_utils.py +142 -0
  180. nvmath/internal/formatters.py +87 -0
  181. nvmath/internal/mem_limit.py +51 -0
  182. nvmath/internal/memory.cp314-win_amd64.pyd +0 -0
  183. nvmath/internal/memory.pxd +10 -0
  184. nvmath/internal/memory.pyi +46 -0
  185. nvmath/internal/ndbuffer/__init__.pxd +3 -0
  186. nvmath/internal/ndbuffer/__init__.py +7 -0
  187. nvmath/internal/ndbuffer/copy_kernel/args.h +34 -0
  188. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/array_view.h +52 -0
  189. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/elementwise.h +68 -0
  190. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/grid_indexer.h +69 -0
  191. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/transposed.h +240 -0
  192. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/type_utils.h +39 -0
  193. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/utils.h +132 -0
  194. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/vec.h +159 -0
  195. nvmath/internal/ndbuffer/copy_kernel/elementwise.h +53 -0
  196. nvmath/internal/ndbuffer/copy_kernel/transposed.h +58 -0
  197. nvmath/internal/ndbuffer/copy_kernel.cp314-win_amd64.pyd +0 -0
  198. nvmath/internal/ndbuffer/copy_kernel.pxd +9 -0
  199. nvmath/internal/ndbuffer/copy_kernel.pyi +9 -0
  200. nvmath/internal/ndbuffer/data_layout.cp314-win_amd64.pyd +0 -0
  201. nvmath/internal/ndbuffer/data_layout.pxd +72 -0
  202. nvmath/internal/ndbuffer/data_layout.pyi +23 -0
  203. nvmath/internal/ndbuffer/jit.cp314-win_amd64.pyd +0 -0
  204. nvmath/internal/ndbuffer/jit.pxd +7 -0
  205. nvmath/internal/ndbuffer/jit.pyi +6 -0
  206. nvmath/internal/ndbuffer/ndbuffer.cp314-win_amd64.pyd +0 -0
  207. nvmath/internal/ndbuffer/ndbuffer.pxd +36 -0
  208. nvmath/internal/ndbuffer/ndbuffer.pyi +41 -0
  209. nvmath/internal/ndbuffer/package_utils.cp314-win_amd64.pyd +0 -0
  210. nvmath/internal/ndbuffer/package_utils.pxd +11 -0
  211. nvmath/internal/ndbuffer/package_utils.pyi +12 -0
  212. nvmath/internal/package_ifc.py +147 -0
  213. nvmath/internal/package_ifc_cuda.py +49 -0
  214. nvmath/internal/package_ifc_cupy.py +49 -0
  215. nvmath/internal/package_ifc_torch.py +31 -0
  216. nvmath/internal/package_wrapper.py +14 -0
  217. nvmath/internal/tensor_ifc.py +194 -0
  218. nvmath/internal/tensor_ifc_cupy.py +241 -0
  219. nvmath/internal/tensor_ifc_ndbuffer.py +153 -0
  220. nvmath/internal/tensor_ifc_numpy.py +183 -0
  221. nvmath/internal/tensor_ifc_torch.py +176 -0
  222. nvmath/internal/tensor_wrapper.py +157 -0
  223. nvmath/internal/typemaps.py +162 -0
  224. nvmath/internal/utils.py +771 -0
  225. nvmath/linalg/__init__.py +46 -0
  226. nvmath/linalg/_internal/__init__.py +3 -0
  227. nvmath/linalg/_internal/algo_cap_ifc.py +82 -0
  228. nvmath/linalg/_internal/algo_config_ifc.py +43 -0
  229. nvmath/linalg/_internal/batch.py +217 -0
  230. nvmath/linalg/_internal/enum_to_tuples.py +64 -0
  231. nvmath/linalg/_internal/epilog_protocol.py +766 -0
  232. nvmath/linalg/_internal/layout.py +624 -0
  233. nvmath/linalg/_internal/matmul_desc_ifc.py +28 -0
  234. nvmath/linalg/_internal/matmul_pref_ifc.py +27 -0
  235. nvmath/linalg/_internal/matrix_layout_ifc.py +26 -0
  236. nvmath/linalg/_internal/typemaps.py +144 -0
  237. nvmath/linalg/_internal/utils.py +134 -0
  238. nvmath/linalg/advanced/__init__.py +8 -0
  239. nvmath/linalg/advanced/_algorithmmod.py +149 -0
  240. nvmath/linalg/advanced/_configuration.py +349 -0
  241. nvmath/linalg/advanced/helpers/__init__.py +5 -0
  242. nvmath/linalg/advanced/helpers/matmul.py +1348 -0
  243. nvmath/linalg/advanced/matmulmod.py +3937 -0
  244. nvmath/linalg/generic/__init__.py +43 -0
  245. nvmath/linalg/generic/_configuration/__init__.py +37 -0
  246. nvmath/linalg/generic/_configuration/layout.py +263 -0
  247. nvmath/linalg/generic/_configuration/match.py +609 -0
  248. nvmath/linalg/generic/_configuration/qualifiers.py +494 -0
  249. nvmath/linalg/generic/_configuration/wrap.py +217 -0
  250. nvmath/linalg/generic/_dtype.py +15 -0
  251. nvmath/linalg/generic/matmulmod.py +1060 -0
  252. nvmath/memory.py +282 -0
  253. nvmath/sparse/__init__.py +38 -0
  254. nvmath/sparse/_internal/__init__.py +21 -0
  255. nvmath/sparse/_internal/common_utils.py +144 -0
  256. nvmath/sparse/_internal/cudss_config_ifc.py +741 -0
  257. nvmath/sparse/_internal/cudss_data_ifc.py +399 -0
  258. nvmath/sparse/_internal/cudss_utils.py +445 -0
  259. nvmath/sparse/_internal/cusparse_utils.py +382 -0
  260. nvmath/sparse/_internal/sparse_bsc_ifc.py +300 -0
  261. nvmath/sparse/_internal/sparse_bsr_ifc.py +303 -0
  262. nvmath/sparse/_internal/sparse_coo_ifc.py +254 -0
  263. nvmath/sparse/_internal/sparse_csc_ifc.py +266 -0
  264. nvmath/sparse/_internal/sparse_csr_ifc.py +266 -0
  265. nvmath/sparse/_internal/sparse_dia_ifc.py +239 -0
  266. nvmath/sparse/_internal/sparse_format_helpers.py +601 -0
  267. nvmath/sparse/_internal/sparse_tensor_ifc.py +121 -0
  268. nvmath/sparse/_internal/sparse_ust_ifc.py +146 -0
  269. nvmath/sparse/_internal/utils.py +56 -0
  270. nvmath/sparse/advanced/__init__.py +7 -0
  271. nvmath/sparse/advanced/_configuration.py +230 -0
  272. nvmath/sparse/advanced/direct_solver.py +1884 -0
  273. nvmath/sparse/generic/__init__.py +7 -0
  274. nvmath/sparse/generic/_configuration.py +129 -0
  275. nvmath/sparse/generic/_helpers.py +137 -0
  276. nvmath/sparse/generic/_thunks.py +21 -0
  277. nvmath/sparse/generic/matmulmod.py +2426 -0
  278. nvmath/sparse/ust/__init__.py +7 -0
  279. nvmath/sparse/ust/_converters.py +378 -0
  280. nvmath/sparse/ust/_drawer.py +552 -0
  281. nvmath/sparse/ust/_emitter.py +553 -0
  282. nvmath/sparse/ust/_jit.py +212 -0
  283. nvmath/sparse/ust/_kernel.py +346 -0
  284. nvmath/sparse/ust/_semiring.py +71 -0
  285. nvmath/sparse/ust/_utils.py +102 -0
  286. nvmath/sparse/ust/interfaces/__init__.py +0 -0
  287. nvmath/sparse/ust/interfaces/torch_interface.py +476 -0
  288. nvmath/sparse/ust/semiring_ops.py +71 -0
  289. nvmath/sparse/ust/tensor.py +1027 -0
  290. nvmath/sparse/ust/tensor_drawer.py +552 -0
  291. nvmath/sparse/ust/tensor_emitter.py +558 -0
  292. nvmath/sparse/ust/tensor_format.py +935 -0
  293. nvmath/sparse/ust/tensor_jit.py +212 -0
  294. nvmath/sparse/ust/tensor_kernel.py +348 -0
  295. nvmath/sparse/ust/tensor_utils.py +380 -0
  296. nvmath/tensor/__init__.py +6 -0
  297. nvmath/tensor/_configuration.py +95 -0
  298. nvmath/tensor/_internal/__init__.py +3 -0
  299. nvmath/tensor/_internal/cutensor_config_ifc.py +247 -0
  300. nvmath/tensor/_internal/cutensor_utils.py +162 -0
  301. nvmath/tensor/_internal/data.py +43 -0
  302. nvmath/tensor/_internal/einsum_parser.py +444 -0
  303. nvmath/tensor/_internal/typemaps.py +96 -0
  304. nvmath/tensor/contract.py +1861 -0
  305. nvmath_python-0.9.0.dist-info/METADATA +127 -0
  306. nvmath_python-0.9.0.dist-info/RECORD +309 -0
  307. nvmath_python-0.9.0.dist-info/WHEEL +5 -0
  308. nvmath_python-0.9.0.dist-info/licenses/LICENSE +177 -0
  309. nvmath_python-0.9.0.dist-info/top_level.txt +2 -0
nvmath/fft/__init__.py ADDED
@@ -0,0 +1,7 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from ._configuration import * # noqa: F403
6
+ from ._helpers import * # noqa: F403
7
+ from .fft import * # noqa: F403
@@ -0,0 +1,208 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ __all__ = ["FFTDirection", "FFTOptions", "DeviceCallable", "ExecutionCUDA", "ExecutionCPU"]
6
+
7
+ import warnings
8
+ from dataclasses import dataclass, field
9
+ from enum import IntEnum
10
+ from logging import Logger
11
+ from typing import Literal
12
+
13
+ from nvmath.memory import BaseCUDAMemoryManager
14
+
15
+
16
+ @dataclass
17
+ class ExecutionCUDA:
18
+ """
19
+ A data class for providing GPU execution options to the :class:`FFT` object and the
20
+ family of wrapper functions :func:`fft`, :func:`ifft`, :func:`rfft`, and :func:`irfft`.
21
+
22
+ Attributes:
23
+ device_id: CUDA device ordinal (only used if the operand resides on the CPU). The
24
+ default value is 0.
25
+
26
+ .. seealso::
27
+ :class:`ExecutionCPU`, :class:`FFT`, :func:`fft`, :func:`ifft`, :func:`rfft`, and
28
+ :func:`irfft`.
29
+ """
30
+
31
+ name: Literal["cuda"] = field(default="cuda", init=False)
32
+ # If not specified, it defaults to the deprecated FFTOptions.device_id or 0
33
+ # Keep None as an option to differentiate between the user-provided 0 and the default 0.
34
+ device_id: int | None = None
35
+
36
+
37
+ @dataclass
38
+ class ExecutionCPU:
39
+ """
40
+ A data class for providing CPU execution options to the :class:`FFT` object and the
41
+ family of wrapper functions :func:`fft`, :func:`ifft`, :func:`rfft`, and :func:`irfft`.
42
+
43
+ Attributes:
44
+ num_threads: The number of CPU threads used to execute the plan.
45
+ If not specified, defaults to the number of CPU cores available to the
46
+ process.
47
+
48
+ .. seealso::
49
+ :class:`ExecutionCUDA`, :class:`FFT`, :func:`fft`, :func:`ifft`, :func:`rfft`, and
50
+ :func:`irfft`.
51
+ """
52
+
53
+ name: Literal["cpu"] = field(default="cpu", init=False)
54
+ num_threads: int | None = None
55
+
56
+
57
+ @dataclass
58
+ class FFTOptions:
59
+ """
60
+ A data class for providing options to the :class:`FFT` object and the family of wrapper
61
+ functions :func:`fft`, :func:`ifft`, :func:`rfft`, and :func:`irfft`.
62
+
63
+ Attributes:
64
+ fft_type: The type of FFT to perform, available options include ``'C2C'``,
65
+ ``'C2R'``, and ``'R2C'``. The default is ``'C2C'`` for complex input and
66
+ ``'R2C'`` for real input.
67
+
68
+ inplace: Specify if the operation is in-place (`True` or `False`). The operand is
69
+ overwritten by the result if ``inplace`` is `True`. The default is `False`.
70
+
71
+ last_axis_parity: For complex-to-real FFT (corresponding to ``fft_type='C2R'``),
72
+ specify whether the size of the last axis in the result should be even or odd.
73
+ The even size is calculated as :math:`2 * (m - 1)`, where :math:`m` is the the
74
+ size of the last axis of the operand, and the odd size is calculated as :math:`2
75
+ * (m - 1) + 1`. The specified value should be either ``'even'`` or ``'odd'``,
76
+ with the default being ``'even'``.
77
+
78
+ result_layout: The layout to use for the result, either ``'natural'`` or
79
+ ``'optimized'``. For the ``'natural'`` option, the result layout is the same as
80
+ that of the operand. The default is ``'optimized'``, which generally provides
81
+ much better performance and should be used if the user doesn't care about the
82
+ result layout matching the operand layout. However in rare cases, depending on
83
+ the device type, shape and strides of the operand, and the FFT dimensions, the
84
+ ``'natural'`` layout may perform better. This option is ignored if ``inplace``
85
+ is specified to be True.
86
+
87
+ device_id: CUDA device ordinal (used if the operand resides on the CPU).
88
+ Device 0 will be used if not specified.
89
+
90
+ .. deprecated:: 0.2.0
91
+ The ``device_id`` should be specified as ``execution`` option,
92
+ see :attr:`ExecutionCUDA.device_id`.
93
+
94
+
95
+ logger (logging.Logger): Python Logger object. The root logger will be used if a
96
+ logger object is not provided.
97
+
98
+ blocking: A flag specifying the behavior of the execution functions and methods,
99
+ such as :func:`fft` and :meth:`FFT.execute`. When ``blocking`` is `True`, the
100
+ execution methods do not return until the operation is complete. When
101
+ ``blocking`` is ``"auto"``, the methods return immediately when the input tensor
102
+ is on the GPU and ``execution`` is set to 'CUDA'. The execution methods always
103
+ block when the input tensor is on the CPU or ``execution`` is specified to 'CPU'
104
+ to ensure that the user doesn't inadvertently use the result before it becomes
105
+ available. The default is ``"auto"``.
106
+
107
+ allocator: An object that supports the :class:`BaseCUDAMemoryManager` protocol, used
108
+ to draw device memory. If an allocator is not provided, a memory allocator from
109
+ the library package will be used (:func:`torch.cuda.caching_allocator_alloc` for
110
+ PyTorch operands, :func:`cupy.cuda.alloc` otherwise). Currently, CPU execution
111
+ does not allow specifying a memory pool.
112
+
113
+ .. seealso::
114
+ :class:`ExecutionCUDA`, :class:`ExecutionCPU`, :class:`FFT`, :func:`fft`,
115
+ :func:`ifft`, :func:`rfft`, and :func:`irfft`.
116
+ """
117
+
118
+ fft_type: Literal["C2C", "C2R", "R2C"] | None = None
119
+ inplace: bool = False
120
+ last_axis_parity: Literal["even", "odd"] = "even"
121
+ result_layout: Literal["natural", "optimized"] = "optimized"
122
+ device_id: int | None = None
123
+ logger: Logger | None = None
124
+ blocking: Literal[True, "auto"] = "auto"
125
+ allocator: BaseCUDAMemoryManager | None = None
126
+
127
+ def __post_init__(self):
128
+ valid_fft_types = [None, "C2C", "C2R", "R2C"]
129
+ if self.fft_type not in valid_fft_types:
130
+ raise ValueError(f"The value specified for 'fft_type' must be one of {valid_fft_types}.")
131
+
132
+ if not isinstance(self.inplace, bool):
133
+ raise ValueError("The value specified for 'inplace' must be of type bool (True or False).")
134
+
135
+ valid_last_axis_parity = ["even", "odd"]
136
+ if self.last_axis_parity not in valid_last_axis_parity:
137
+ raise ValueError(f"The value specified for 'last_axis_parity' must be one of {valid_last_axis_parity}.")
138
+
139
+ valid_result_layout_options = ["natural", "optimized"]
140
+ if self.result_layout not in valid_result_layout_options:
141
+ raise ValueError(f"The value specified for 'result_layout' must be one of {valid_result_layout_options}.")
142
+
143
+ if self.blocking not in (True, "auto"):
144
+ raise ValueError("The value specified for 'blocking' must be either True or 'auto'.")
145
+
146
+ if self.device_id is not None:
147
+ msg = "`FFTOptions.device_id` is deprecated. Use `ExecutionCUDA.device_id` instead."
148
+ warnings.warn(msg, DeprecationWarning)
149
+
150
+
151
+ @dataclass
152
+ class DeviceCallable:
153
+ """A data class capturing LTO-IR callables.
154
+
155
+ Attributes:
156
+ ltoir: A device-callable function in LTO-IR format, which can be provided as as
157
+ either as a :class:`bytes` object or as a pointer to the LTO-IR as Python
158
+ :class:`int`.
159
+
160
+ size: The size of the LTO-IR callable. If not specified and a :class:`bytes` object
161
+ is passed for ``ltoir``, the size is calculated from it. If a pointer is
162
+ provided for the LTO-IR, `size` must be specified.
163
+
164
+ data: A device pointer to user data used in the callback. The default is None,
165
+ which means a null pointer will be used in the callback.
166
+
167
+ .. seealso::
168
+ :meth:`FFT.plan`, :func:`fft`, :func:`ifft`, :func:`rfft`, and :func:`irfft`.
169
+ """
170
+
171
+ ltoir: int | bytes | None = None
172
+ size: int | None = None
173
+ data: int | None = None
174
+
175
+ def __post_init__(self):
176
+ if self.ltoir is None:
177
+ return
178
+ if not isinstance(self.ltoir, int | bytes):
179
+ raise ValueError(
180
+ "The LTO-IR code must be provided as a bytes object or as a Python int "
181
+ "representing the pointer to the LTO-IR code."
182
+ )
183
+ if isinstance(self.ltoir, int) and self.size is None:
184
+ raise ValueError(
185
+ "The size of the LTO-IR code specified as a pointer must be explicitly provided using the 'size' option."
186
+ )
187
+ if isinstance(self.ltoir, bytes):
188
+ self.size = len(self.ltoir)
189
+ if not isinstance(self.size, int):
190
+ raise ValueError(f"Invalid size value: {self.size}.")
191
+ if self.data is None:
192
+ self.data = 0
193
+ if not isinstance(self.data, int):
194
+ raise ValueError("The 'data' attribute must be a Python int representing a device pointer to user data.")
195
+
196
+
197
+ KeywordArgType = dict
198
+
199
+
200
+ class FFTDirection(IntEnum):
201
+ """An IntEnum class specifying the direction of the transform.
202
+
203
+ .. seealso::
204
+ :meth:`FFT.execute`, :func:`fft`
205
+ """
206
+
207
+ FORWARD = -1
208
+ INVERSE = 1
@@ -0,0 +1,109 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import os
6
+
7
+ from nvmath.bindings import cufft # type: ignore
8
+ from nvmath.bindings._internal import utils as _bindings_utils # type: ignore
9
+ from nvmath.fft import _configuration
10
+
11
+ IS_EXEC_GPU_AVAILABLE = False
12
+ IS_EXEC_CPU_AVAILABLE = False
13
+ NUM_THREADS_DEFAULT = None
14
+
15
+
16
+ def _get_num_threads_default():
17
+ global NUM_THREADS_DEFAULT
18
+ if NUM_THREADS_DEFAULT is None:
19
+ if os.name == "posix":
20
+ num_threads = len(os.sched_getaffinity(0))
21
+ else:
22
+ # `sched_getaffinity` is not supported on Windows
23
+ num_threads = os.cpu_count() or 1
24
+ num_threads = max(1, num_threads // 2)
25
+ NUM_THREADS_DEFAULT = num_threads
26
+ return NUM_THREADS_DEFAULT
27
+
28
+
29
+ def _check_init_cufft():
30
+ global IS_EXEC_GPU_AVAILABLE
31
+ if not IS_EXEC_GPU_AVAILABLE:
32
+ try:
33
+ cufft.get_version()
34
+ except (
35
+ _bindings_utils.FunctionNotFoundError,
36
+ _bindings_utils.NotSupportedError,
37
+ RuntimeError,
38
+ ) as e:
39
+ raise RuntimeError(
40
+ "The FFT CUDA execution is not available. "
41
+ "Please check if CUDA toolkit and cuFFT are installed and visible to nvmath."
42
+ ) from e
43
+
44
+ IS_EXEC_GPU_AVAILABLE = True
45
+
46
+
47
+ def _check_init_fftw():
48
+ global IS_EXEC_CPU_AVAILABLE
49
+ if not IS_EXEC_CPU_AVAILABLE:
50
+ from nvmath.bindings.nvpl import fft as _fftw
51
+ from nvmath.bindings.nvpl._internal import fft as _internal_fftw
52
+
53
+ env_lib_name = os.environ.get("NVMATH_FFT_CPU_LIBRARY")
54
+
55
+ if env_lib_name:
56
+ _internal_fftw._set_lib_so_names((env_lib_name,))
57
+ try:
58
+ _internal_fftw._inspect_function_pointers()
59
+ loaded_lib_name = _internal_fftw._get_current_lib_so_name()
60
+ except (
61
+ _bindings_utils.FunctionNotFoundError,
62
+ _bindings_utils.NotSupportedError,
63
+ RuntimeError,
64
+ ) as e:
65
+ raise RuntimeError(
66
+ "The FFT CPU execution is not available, because no FFTW-compatible "
67
+ "library was found. Please make sure to install optional dependency required "
68
+ "for FFT execution (NVPL on aarch64 platforms or MKL on x86_64 platforms). "
69
+ "Users can use other FFTW3-compatible libraries. In order to do that, please "
70
+ "specify the library name as "
71
+ "`NVMATH_FFT_CPU_LIBRARY=some_fftw3_compatible_lib.so` and make sure "
72
+ "the library can be found within current `LD_LIBRARY_PATH`"
73
+ ) from e
74
+
75
+ if env_lib_name:
76
+ assert env_lib_name == loaded_lib_name
77
+
78
+ lib_nvpl = "libnvpl_fftw.so"
79
+ if not loaded_lib_name.startswith(lib_nvpl):
80
+ _fftw.init_threads_float()
81
+ _fftw.init_threads_double()
82
+
83
+ IS_EXEC_CPU_AVAILABLE = True
84
+
85
+
86
+ def _cross_setup_execution_and_options(
87
+ options: _configuration.FFTOptions,
88
+ execution: _configuration.ExecutionCUDA | _configuration.ExecutionCPU,
89
+ ):
90
+ if execution.name == "cpu":
91
+ _check_init_fftw()
92
+ if options.device_id is not None:
93
+ raise ValueError("The 'device_id' is not a valid option when 'execution' is specified to be 'cpu'.")
94
+ if execution.num_threads is None:
95
+ execution.num_threads = _get_num_threads_default()
96
+ if not isinstance(execution.num_threads, int) or execution.num_threads <= 0:
97
+ raise ValueError("The 'num_threads' must be a positive integer")
98
+ else:
99
+ assert execution.name == "cuda"
100
+ _check_init_cufft()
101
+ if execution.device_id is None:
102
+ execution.device_id = options.device_id or 0
103
+ elif options.device_id is not None and execution.device_id != options.device_id:
104
+ raise ValueError(
105
+ f"Got conflicting 'device_id' passed in 'execution' ({execution.device_id}) "
106
+ f"and 'options' ({options.device_id}). It should be passed as 'execution' "
107
+ f"configuration only."
108
+ )
109
+ return options, execution
nvmath/fft/_helpers.py ADDED
@@ -0,0 +1,237 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ __all__ = ["compile_prolog", "compile_epilog"]
6
+
7
+ import functools
8
+
9
+ from nvmath.bindings import cufft as _cufft # type: ignore
10
+
11
+ # Currently supported element data types for FFT callback functions.
12
+ VALID_DTYPES = {"float32": "Real", "float64": "DoubleReal", "complex64": "Complex", "complex128": "DoubleComplex"}
13
+
14
+ # Python <> CUDA magled types.
15
+ TYPE_MAP = {
16
+ "float32": "f", # float
17
+ "float64": "d", # double
18
+ "complex64": "6float2", # float2
19
+ "complex128": "7double2", # double2
20
+ }
21
+
22
+
23
+ def _check_numba_available():
24
+ try:
25
+ import numba # noqa: F401
26
+ except ModuleNotFoundError as e:
27
+ raise RuntimeError("Numba is required to compile FFT prolog and epilog functions.") from e
28
+
29
+
30
+ def _compile(
31
+ function, element_dtype, user_info_dtype, *, name=None, phase=None, representation="ltoir", compute_capability=None
32
+ ):
33
+ _check_numba_available()
34
+
35
+ import numba
36
+ import numba.cuda
37
+
38
+ assert phase in ["Load", "Store"], "Internal error."
39
+
40
+ if element_dtype not in VALID_DTYPES:
41
+ raise ValueError(
42
+ f"The specified operand data type '{element_dtype}' is not currently supported. "
43
+ f"It must be one of {VALID_DTYPES.keys()}."
44
+ )
45
+
46
+ data_type = getattr(numba.cuda.types.types, element_dtype)
47
+
48
+ if user_info_dtype in VALID_DTYPES:
49
+ info_type = getattr(numba.cuda.types.types, user_info_dtype)
50
+ elif isinstance(user_info_dtype, numba.types.Type):
51
+ info_type = user_info_dtype
52
+ else:
53
+ raise ValueError(
54
+ f"The specified user information data type '{user_info_dtype}' is not supported. "
55
+ f"It must be a Numba custom type or one of {VALID_DTYPES.keys()}."
56
+ )
57
+
58
+ dataptr_type = numba.types.CPointer(data_type)
59
+ infoptr_type = numba.types.CPointer(info_type)
60
+ offset_type = numba.types.uint64
61
+ smemptr_type = dataptr_type
62
+
63
+ if phase == "Load":
64
+ insert = ""
65
+ return_type = data_type
66
+ signature = numba.core.typing.signature(return_type, dataptr_type, offset_type, infoptr_type, smemptr_type)
67
+ else:
68
+ insert = TYPE_MAP[element_dtype]
69
+ return_type = numba.types.void
70
+ signature = numba.core.typing.signature(return_type, dataptr_type, offset_type, data_type, infoptr_type, smemptr_type)
71
+
72
+ if name is None:
73
+ snippet = VALID_DTYPES[element_dtype]
74
+ length = 16 + len(phase) + len(snippet)
75
+ # the signature of callbacks differs - the offset argument
76
+ # changed type from size_t to unsigned long long int
77
+ offset_dtype = "m" if _cufft.get_version() < 11300 else "y"
78
+ name = f"_Z{length}cufftJITCallback{phase}{snippet}Pv{offset_dtype}{insert}S_S_"
79
+
80
+ if compute_capability is None:
81
+ compute_capability = numba.cuda.get_current_device().compute_capability
82
+ else:
83
+ if not isinstance(compute_capability, str):
84
+ raise ValueError(
85
+ f"The compute capability must be specified as a string ('80', '89', ...). "
86
+ f"The provided value {compute_capability} is invalid."
87
+ )
88
+ cc_number = int(compute_capability)
89
+ compute_capability = (cc_number // 10, cc_number % 10)
90
+
91
+ return numba.cuda.compile(
92
+ function,
93
+ signature,
94
+ debug=None,
95
+ lineinfo=False,
96
+ device=True,
97
+ fastmath=False,
98
+ cc=compute_capability,
99
+ opt=True,
100
+ abi="c",
101
+ abi_info={"abi_name": name},
102
+ output=representation,
103
+ forceinline=False,
104
+ launch_bounds=None,
105
+ )[0]
106
+
107
+
108
+ compile_prolog = functools.wraps(_compile)(functools.partial(_compile, phase="Load"))
109
+ compile_epilog = functools.wraps(_compile)(functools.partial(_compile, phase="Store"))
110
+
111
+ SHARED_FFT_HELPER_DOCUMENTATION = {
112
+ "element_dtype": """The data type of the ``data_in`` argument, one of ``['float32', 'float64', 'complex64',
113
+ 'complex128']``. It must have the same data type as that of the FFT operand for prolog functions or the FFT
114
+ result for epilog functions.""",
115
+ "user_info_dtype": """The data type of the ``user_info`` argument. It must be one of ``['float32', 'float64',
116
+ 'complex64', 'complex128']`` or an object of type :class:`numba.types.Type`. The offset is computed based on
117
+ the memory layout (shape and strides) of the operand (input for prolog, output for epilog). If the user
118
+ would like to pass additional tensor as `user_info` and access it based on the offset, it is crucial to know
119
+ memory layout of the operand. Please note, the actual layout of the input tensor may differ from the layout
120
+ of the tensor passed to fft call. To learn the memory layout of the input or output, please use stateful FFT
121
+ API and :meth:`nvmath.fft.FFT.get_input_layout` :meth:`nvmath.fft.FFT.get_output_layout` respectively.
122
+
123
+ .. note::
124
+ Currently, in the callback, the position of the element in the input and output operands are described
125
+ with a single flat offset, even if the original operand is multi-dimensional tensor.
126
+
127
+ """,
128
+ "compute_capability": """The target compute capability, specified as a string (``'80'``, ``'89'``, ...). The
129
+ default is the compute capability of the current device. For cuFFT in CUDA Toolkit 12.8, 12.9
130
+ on Blackwell devices (compute capability 12.0), the default
131
+ compute capability of the current device may fail to compile. As a workaround, ``'50'``
132
+ can be specified.""",
133
+ }
134
+
135
+ compile_prolog.__doc__ = """
136
+ compile_prolog(prolog_fn, element_dtype, user_info_dtype, *, compute_capability=None)
137
+
138
+ Compile a Python function to LTO-IR to provide as a prolog function for
139
+ :func:`~nvmath.fft.fft` and :meth:`~nvmath.fft.FFT.plan`.
140
+
141
+ Args:
142
+ prolog_fn: The prolog function to be compiled to LTO-IR. It must have the signature:
143
+ ``prolog_fn(data_in, offset, user_info, reserved_for_future_use)``, and it
144
+ essentially returns transformed ``data_in`` at ``offset``.
145
+
146
+ element_dtype: {element_dtype}
147
+
148
+ user_info_dtype: {user_info_dtype}
149
+
150
+ compute_capability: {compute_capability}
151
+
152
+ Returns:
153
+ The function compiled to LTO-IR as `bytes` object.
154
+
155
+ .. seealso::
156
+ :func:`~nvmath.fft.fft`, :meth:`~nvmath.fft.FFT.plan`,
157
+ :func:`~nvmath.fft.compile_epilog`.
158
+
159
+ Notes:
160
+ - The user must ensure that the specified argument types meet the requirements
161
+ listed above.
162
+ """.format(**SHARED_FFT_HELPER_DOCUMENTATION)
163
+ compile_prolog.__name__ = "compile_prolog"
164
+
165
+ compile_epilog.__doc__ = """
166
+ compile_epilog(epilog_fn, element_dtype, user_info_dtype, *, compute_capability=None)
167
+
168
+ Compile a Python function to LTO-IR to provide as an epilog function for
169
+ :func:`~nvmath.fft.fft` and :meth:`~nvmath.fft.FFT.plan`.
170
+
171
+ Args:
172
+ epilog_fn: The epilog function to be compiled to LTO-IR. It must have the signature:
173
+ ``epilog_fn(data_out, offset, data, user_info, reserved_for_future_use)``, and
174
+ it essentially stores transformed ``data`` into ``data_out`` at ``offset``.
175
+
176
+ element_dtype: {element_dtype}
177
+
178
+ user_info_dtype: {user_info_dtype}
179
+
180
+ compute_capability: {compute_capability}
181
+
182
+ Returns:
183
+ The function compiled to LTO-IR as `bytes` object.
184
+
185
+ .. seealso::
186
+ :func:`~nvmath.fft.fft`, :meth:`~nvmath.fft.FFT.plan`,
187
+ :func:`~nvmath.fft.compile_prolog`.
188
+
189
+ Examples:
190
+
191
+ The cuFFT library expects the end user to manage scaling of the outputs, so in order
192
+ to replicate the ``norm`` option found in `other Python FFT libraries
193
+ <https://numpy.org/doc/stable/reference/routines.fft.html#normalization>`_ we can
194
+ define an epilog which performs the scaling.
195
+
196
+ >>> import cupy as cp
197
+ >>> import nvmath
198
+ >>> import math
199
+
200
+ Create the data for a batched 1-D FFT.
201
+
202
+ >>> B, N = 256, 1024
203
+ >>> a = cp.random.rand(B, N, dtype=cp.float64) + 1j * cp.random.rand(B, N, dtype=cp.float64)
204
+
205
+ Compute a normalization factor that will create unitary transforms.
206
+
207
+ >>> norm_factor = 1.0 / math.sqrt(N)
208
+
209
+ Define the epilog function for the FFT.
210
+
211
+ >>> def rescale(data_out, offset, data, user_info, unused):
212
+ ... data_out[offset] = data * norm_factor
213
+
214
+ Compile the epilog to LTO-IR. In a system with GPUs that have different compute
215
+ capability, the `compute_capability` option must be specified to the
216
+ `compile_prolog` or `compile_epilog` helpers. Alternatively, the epilog can be
217
+ compiled in the context of the device where the FFT to which the epilog is provided
218
+ is executed. In this case we use the current device context, where the operands have
219
+ been created.
220
+
221
+ >>> with cp.cuda.Device():
222
+ ... epilog = nvmath.fft.compile_epilog(rescale, "complex128", "complex128")
223
+
224
+ Perform the forward FFT, applying the rescaling as a epilog.
225
+
226
+ >>> r = nvmath.fft.fft(a, axes=[-1], epilog=dict(ltoir=epilog))
227
+
228
+ Test that the fused FFT run result matches the result of other libraries.
229
+
230
+ >>> s = cp.fft.fftn(a, axes=[-1], norm="ortho")
231
+ >>> assert cp.allclose(r, s)
232
+
233
+ Notes:
234
+ - The user must ensure that the specified argument types meet the requirements
235
+ listed above.
236
+ """.format(**SHARED_FFT_HELPER_DOCUMENTATION)
237
+ compile_epilog.__name__ = "compile_epilog"