nvmath-python 0.5.0__cp313-cp313-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.
- nvmath/__init__.pxd +0 -0
- nvmath/__init__.py +37 -0
- nvmath/_internal/__init__.py +0 -0
- nvmath/_internal/layout.py +58 -0
- nvmath/_utils.py +363 -0
- nvmath/bindings/__init__.pxd +0 -0
- nvmath/bindings/__init__.py +44 -0
- nvmath/bindings/_internal/__init__.pxd +0 -0
- nvmath/bindings/_internal/__init__.py +0 -0
- nvmath/bindings/_internal/cublas.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublas.pxd +518 -0
- nvmath/bindings/_internal/cublasLt.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublasLt.pxd +54 -0
- nvmath/bindings/_internal/cudss.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cudss.pxd +44 -0
- nvmath/bindings/_internal/cufft.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cufft.pxd +69 -0
- nvmath/bindings/_internal/cufftMp.pxd +77 -0
- nvmath/bindings/_internal/curand.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/curand.pxd +42 -0
- nvmath/bindings/_internal/cusolver.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolver.pxd +15 -0
- nvmath/bindings/_internal/cusolverDn.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolverDn.pxd +386 -0
- nvmath/bindings/_internal/cusparse.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusparse.pxd +270 -0
- nvmath/bindings/_internal/mathdx.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/mathdx.pxd +79 -0
- nvmath/bindings/_internal/nvshmem.pxd +29 -0
- nvmath/bindings/_internal/utils.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/utils.pxd +186 -0
- nvmath/bindings/cublas.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cublas.pxd +545 -0
- nvmath/bindings/cublas.pyi +18 -0
- nvmath/bindings/cublasLt.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cublasLt.pxd +99 -0
- nvmath/bindings/cudss.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cudss.pxd +83 -0
- nvmath/bindings/cudss.pyi +249 -0
- nvmath/bindings/cufft.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cufft.pxd +114 -0
- nvmath/bindings/cufftMp.pxd +124 -0
- nvmath/bindings/curand.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/curand.pxd +71 -0
- nvmath/bindings/cusolver.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cusolver.pxd +60 -0
- nvmath/bindings/cusolverDn.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cusolverDn.pxd +410 -0
- nvmath/bindings/cusparse.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cusparse.pxd +329 -0
- nvmath/bindings/cycublas.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycublas.pxd +657 -0
- nvmath/bindings/cycublasLt.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycublasLt.pxd +1010 -0
- nvmath/bindings/cycudss.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycudss.pxd +191 -0
- nvmath/bindings/cycufft.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycufft.pxd +320 -0
- nvmath/bindings/cycufftMp.pxd +333 -0
- nvmath/bindings/cycurand.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycurand.pxd +146 -0
- nvmath/bindings/cycusolver.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolver.pxd +143 -0
- nvmath/bindings/cycusolverDn.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolverDn.pxd +414 -0
- nvmath/bindings/cycusparse.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycusparse.pxd +476 -0
- nvmath/bindings/cymathdx.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cymathdx.pxd +363 -0
- nvmath/bindings/cynvshmem.pxd +126 -0
- nvmath/bindings/mathdx.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/mathdx.pxd +131 -0
- nvmath/bindings/mathdx.pyi +686 -0
- nvmath/bindings/nvpl/__init__.pxd +0 -0
- nvmath/bindings/nvpl/__init__.py +11 -0
- nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
- nvmath/bindings/nvpl/_internal/__init__.py +0 -0
- nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
- nvmath/bindings/nvpl/cyfft.pxd +87 -0
- nvmath/bindings/nvpl/fft.pxd +100 -0
- nvmath/bindings/nvshmem.pxd +54 -0
- nvmath/device/__init__.py +23 -0
- nvmath/device/_deprecated.py +33 -0
- nvmath/device/caching.py +51 -0
- nvmath/device/common.py +131 -0
- nvmath/device/common_backend.py +125 -0
- nvmath/device/common_cuda.py +156 -0
- nvmath/device/common_mathdx.py +97 -0
- nvmath/device/common_numba.py +159 -0
- nvmath/device/common_opaque_tensor.py +128 -0
- nvmath/device/cublasdx.py +1085 -0
- nvmath/device/cublasdx_backend.py +552 -0
- nvmath/device/cublasdx_numba.py +528 -0
- nvmath/device/cufftdx.py +551 -0
- nvmath/device/cufftdx_backend.py +194 -0
- nvmath/device/cufftdx_numba.py +123 -0
- nvmath/device/curand_kernel.py +9147 -0
- nvmath/device/nvrtc.py +95 -0
- nvmath/device/patch.py +35 -0
- nvmath/device/random.py +417 -0
- nvmath/device/random_helpers.py +23 -0
- nvmath/device/random_states.py +189 -0
- nvmath/device/types.py +11 -0
- nvmath/device/vector_types_numba.py +203 -0
- nvmath/distributed/__init__.py +117 -0
- nvmath/distributed/_internal/__init__.py +0 -0
- nvmath/distributed/_internal/nvshmem.py +243 -0
- nvmath/distributed/_internal/tensor_ifc_cupy.py +111 -0
- nvmath/distributed/_internal/tensor_ifc_numpy.py +53 -0
- nvmath/distributed/_internal/tensor_ifc_torch.py +108 -0
- nvmath/distributed/_internal/tensor_wrapper.py +59 -0
- nvmath/distributed/_utils.py +152 -0
- nvmath/distributed/fft/__init__.py +6 -0
- nvmath/distributed/fft/_configuration.py +86 -0
- nvmath/distributed/fft/fft.py +1737 -0
- nvmath/distributed/reshape/__init__.py +6 -0
- nvmath/distributed/reshape/_configuration.py +39 -0
- nvmath/distributed/reshape/reshape.py +1249 -0
- nvmath/fft/__init__.py +7 -0
- nvmath/fft/_configuration.py +208 -0
- nvmath/fft/_exec_utils.py +116 -0
- nvmath/fft/_helpers.py +260 -0
- nvmath/fft/fft.py +2346 -0
- nvmath/internal/__init__.py +5 -0
- nvmath/internal/enum_utils.py +142 -0
- nvmath/internal/formatters.py +87 -0
- nvmath/internal/mem_limit.py +51 -0
- nvmath/internal/package_ifc.py +119 -0
- nvmath/internal/package_ifc_cuda.py +43 -0
- nvmath/internal/package_ifc_cupy.py +49 -0
- nvmath/internal/package_ifc_torch.py +31 -0
- nvmath/internal/package_wrapper.py +14 -0
- nvmath/internal/tensor_ifc.py +143 -0
- nvmath/internal/tensor_ifc_cupy.py +185 -0
- nvmath/internal/tensor_ifc_numpy.py +157 -0
- nvmath/internal/tensor_ifc_torch.py +115 -0
- nvmath/internal/tensor_wrapper.py +160 -0
- nvmath/internal/typemaps.py +154 -0
- nvmath/internal/utils.py +634 -0
- nvmath/linalg/__init__.py +11 -0
- nvmath/linalg/_internal/__init__.py +3 -0
- nvmath/linalg/_internal/algo_cap_ifc.py +86 -0
- nvmath/linalg/_internal/algo_config_ifc.py +87 -0
- nvmath/linalg/_internal/enum_to_tuples.py +64 -0
- nvmath/linalg/_internal/epilog_protocol.py +738 -0
- nvmath/linalg/_internal/matmul_desc_ifc.py +72 -0
- nvmath/linalg/_internal/matmul_pref_ifc.py +65 -0
- nvmath/linalg/_internal/matrix_layout_ifc.py +59 -0
- nvmath/linalg/_internal/typemaps.py +135 -0
- nvmath/linalg/_internal/utils.py +96 -0
- nvmath/linalg/advanced/__init__.py +8 -0
- nvmath/linalg/advanced/_algorithmmod.py +142 -0
- nvmath/linalg/advanced/_configuration.py +320 -0
- nvmath/linalg/advanced/helpers/__init__.py +5 -0
- nvmath/linalg/advanced/helpers/matmul.py +173 -0
- nvmath/linalg/advanced/matmulmod.py +2855 -0
- nvmath/memory.py +266 -0
- nvmath/sparse/__init__.py +18 -0
- nvmath/sparse/_internal/__init__.py +21 -0
- nvmath/sparse/_internal/common_utils.py +81 -0
- nvmath/sparse/_internal/cudss_config_ifc.py +584 -0
- nvmath/sparse/_internal/cudss_data_ifc.py +291 -0
- nvmath/sparse/_internal/cudss_utils.py +398 -0
- nvmath/sparse/_internal/sparse_csr_ifc.py +154 -0
- nvmath/sparse/_internal/sparse_format_helpers.py +88 -0
- nvmath/sparse/_internal/sparse_tensor_ifc.py +80 -0
- nvmath/sparse/advanced/__init__.py +7 -0
- nvmath/sparse/advanced/_configuration.py +150 -0
- nvmath/sparse/advanced/direct_solver.py +1705 -0
- nvmath_python-0.5.0.dist-info/METADATA +122 -0
- nvmath_python-0.5.0.dist-info/RECORD +174 -0
- nvmath_python-0.5.0.dist-info/WHEEL +5 -0
- nvmath_python-0.5.0.dist-info/licenses/LICENSE +177 -0
- nvmath_python-0.5.0.dist-info/top_level.txt +1 -0
nvmath/device/cufftdx.py
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
# Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
__all__ = ["fft", "FFTOptions"]
|
|
6
|
+
from functools import cached_property
|
|
7
|
+
import warnings
|
|
8
|
+
|
|
9
|
+
from .common import (
|
|
10
|
+
make_binary_tempfile,
|
|
11
|
+
check_in,
|
|
12
|
+
SHARED_DEVICE_DOCSTRINGS,
|
|
13
|
+
)
|
|
14
|
+
from .common_cuda import MAX_SUPPORTED_CC, get_default_code_type, Code, CodeType, ComputeCapability, Dim3
|
|
15
|
+
from .common_backend import MATHDX_TYPES_TO_NP, get_isa_version, get_lto
|
|
16
|
+
from .common_numba import NP_TYPES_TO_NUMBA_FE_TYPES
|
|
17
|
+
from .cufftdx_backend import (
|
|
18
|
+
generate_code,
|
|
19
|
+
get_int_trait,
|
|
20
|
+
get_knobs,
|
|
21
|
+
get_str_trait,
|
|
22
|
+
get_int_traits,
|
|
23
|
+
get_data_type_trait,
|
|
24
|
+
validate,
|
|
25
|
+
generate_FFT,
|
|
26
|
+
validate_execute_api,
|
|
27
|
+
)
|
|
28
|
+
from .cufftdx_numba import codegen
|
|
29
|
+
from nvmath.internal.utils import docstring_decorator
|
|
30
|
+
|
|
31
|
+
from nvmath.bindings import mathdx
|
|
32
|
+
|
|
33
|
+
CUFFTDX_DATABASE = None
|
|
34
|
+
|
|
35
|
+
FFTDX_DOCSTRING = SHARED_DEVICE_DOCSTRINGS.copy()
|
|
36
|
+
FFTDX_DOCSTRING.update(
|
|
37
|
+
{
|
|
38
|
+
"size": """\
|
|
39
|
+
The size of the FFT to calculate.""".replace("\n", " "),
|
|
40
|
+
#
|
|
41
|
+
"fft_type": """\
|
|
42
|
+
A string specifying the type of FFT operation, can be ``'c2c'``, ``'c2r'`` or ``'r2c'``.""".replace("\n", " "),
|
|
43
|
+
#
|
|
44
|
+
"direction": """\
|
|
45
|
+
A string specifying the direction of FFT, can be ``'forward'`` or ``'inverse'``. If not provided, will be ``'forward'``
|
|
46
|
+
if complex-to-real FFT is specified and ``'inverse'`` if real-to-complex FFT is specified.""".replace("\n", " "),
|
|
47
|
+
#
|
|
48
|
+
"ffts_per_block": """\
|
|
49
|
+
The number of FFTs calculated per CUDA block, optional. The default is 1. Alternatively, if provided as ``'suggested'``
|
|
50
|
+
will be set to a suggested value""".replace("\n", " "),
|
|
51
|
+
#
|
|
52
|
+
"elements_per_thread": """\
|
|
53
|
+
The number of elements per thread, optional. The default is 1. Alternatively, if provided as ``'suggested'``, will be
|
|
54
|
+
set to a suggested value. """.replace("\n", " "),
|
|
55
|
+
#
|
|
56
|
+
"real_fft_options": """\
|
|
57
|
+
A dictionary specifying the options for real FFT operation, optional.""".replace("\n", " "),
|
|
58
|
+
"execute_api": """\
|
|
59
|
+
A string specifying the signature of the function that handles problems with input in register or in shared memory buffers.
|
|
60
|
+
Could be ``'shared_memory'`` or ``'register_memory'``.""".replace("\n", " "),
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
_workspace_deprecation_warning = lambda: warnings.warn(
|
|
65
|
+
"Using workspaces is deprecated and will be removed in future release.", DeprecationWarning
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@docstring_decorator(FFTDX_DOCSTRING, skip_missing=False)
|
|
70
|
+
class FFTOptions:
|
|
71
|
+
"""
|
|
72
|
+
A class that encapsulates a partial FFT device function. A partial device function can
|
|
73
|
+
be queried for available or optimal values for some knobs (such as `ffts_per_block`
|
|
74
|
+
or `elements_per_thread`). It does not contain a compiled, ready-to-use,
|
|
75
|
+
device function until finalized using :meth:`create`.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
size (int): {size}
|
|
79
|
+
|
|
80
|
+
precision (str): {precision}
|
|
81
|
+
|
|
82
|
+
fft_type (str): {fft_type}
|
|
83
|
+
|
|
84
|
+
code_type (CodeType): {code_type}
|
|
85
|
+
|
|
86
|
+
execution (str): {execution}
|
|
87
|
+
|
|
88
|
+
direction (str): {direction}
|
|
89
|
+
|
|
90
|
+
ffts_per_block (int): {ffts_per_block}
|
|
91
|
+
|
|
92
|
+
elements_per_thread (int): {elements_per_thread}
|
|
93
|
+
|
|
94
|
+
real_fft_options (dict): {real_fft_options} User may specify the following options
|
|
95
|
+
in the dictionary:
|
|
96
|
+
|
|
97
|
+
- ``'complex_layout'``, currently supports ``'natural'``, ``'packed'``, and
|
|
98
|
+
``'full'``.
|
|
99
|
+
- ``'real_mode'``, currently supports ``'normal'`` and ``'folded``.
|
|
100
|
+
|
|
101
|
+
execute_api:
|
|
102
|
+
.. versionchanged:: 0.5.0
|
|
103
|
+
execute_api is not part of the FFT type. Pass this argument to
|
|
104
|
+
:py:func:`nvmath.device.fft` instead.
|
|
105
|
+
|
|
106
|
+
Note:
|
|
107
|
+
The class is not meant to be used directly with its constructor. Users are instead
|
|
108
|
+
advised to use :func:`fft` to create the object.
|
|
109
|
+
|
|
110
|
+
See Also:
|
|
111
|
+
The attributes of this class provide a 1:1 mapping with the CUDA C++ cuFFTDx APIs.
|
|
112
|
+
For further details, please refer to `cuFFTDx documentation
|
|
113
|
+
<https://docs.nvidia.com/cuda/cufftdx/index.html>`_.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def __init__(
|
|
117
|
+
self,
|
|
118
|
+
size,
|
|
119
|
+
precision,
|
|
120
|
+
fft_type,
|
|
121
|
+
code_type,
|
|
122
|
+
execution,
|
|
123
|
+
*,
|
|
124
|
+
direction=None,
|
|
125
|
+
ffts_per_block=None,
|
|
126
|
+
elements_per_thread=None,
|
|
127
|
+
real_fft_options=None,
|
|
128
|
+
):
|
|
129
|
+
if len(code_type) != 2:
|
|
130
|
+
raise ValueError(f"code_type should be an instance of CodeType or a 2-tuple ; got code_type = {code_type}")
|
|
131
|
+
code_type = CodeType(code_type[0], ComputeCapability(*code_type[1]))
|
|
132
|
+
if code_type.cc.major < 7:
|
|
133
|
+
raise RuntimeError(
|
|
134
|
+
f"Minimal compute capability 7.0 is required by cuFFTDx, got {code_type.cc.major}.{code_type.cc.minor}"
|
|
135
|
+
)
|
|
136
|
+
if (code_type.cc.major, code_type.cc.minor) > MAX_SUPPORTED_CC:
|
|
137
|
+
raise RuntimeError(
|
|
138
|
+
"The maximum compute capability currently supported by device "
|
|
139
|
+
f"APIs is {MAX_SUPPORTED_CC}, "
|
|
140
|
+
f"got {code_type.cc.major}.{code_type.cc.minor}"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
#
|
|
144
|
+
# Check that the knobs are, individually, valid
|
|
145
|
+
#
|
|
146
|
+
|
|
147
|
+
validate(
|
|
148
|
+
size=size,
|
|
149
|
+
precision=precision,
|
|
150
|
+
fft_type=fft_type,
|
|
151
|
+
code_type=code_type,
|
|
152
|
+
execution=execution,
|
|
153
|
+
direction=direction,
|
|
154
|
+
ffts_per_block=ffts_per_block,
|
|
155
|
+
elements_per_thread=elements_per_thread,
|
|
156
|
+
real_fft_options=real_fft_options,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
if direction is None and fft_type == "r2c":
|
|
160
|
+
direction = "forward"
|
|
161
|
+
elif direction is None and fft_type == "c2r":
|
|
162
|
+
direction = "inverse"
|
|
163
|
+
|
|
164
|
+
#
|
|
165
|
+
# Traits set by input
|
|
166
|
+
#
|
|
167
|
+
|
|
168
|
+
self._precision = precision
|
|
169
|
+
self._fft_type = fft_type
|
|
170
|
+
self._direction = direction
|
|
171
|
+
self._size = size
|
|
172
|
+
self._execution = execution
|
|
173
|
+
self._ffts_per_block = ffts_per_block
|
|
174
|
+
self._elements_per_thread = elements_per_thread
|
|
175
|
+
self._real_fft_options = real_fft_options
|
|
176
|
+
self._code_type = code_type
|
|
177
|
+
|
|
178
|
+
#
|
|
179
|
+
# Update suggested traits
|
|
180
|
+
#
|
|
181
|
+
|
|
182
|
+
if elements_per_thread == "suggested":
|
|
183
|
+
self._elements_per_thread = self._suggested_elements_per_thread
|
|
184
|
+
|
|
185
|
+
if ffts_per_block == "suggested":
|
|
186
|
+
self._ffts_per_block = self._suggested_ffts_per_block
|
|
187
|
+
|
|
188
|
+
@property
|
|
189
|
+
def elements_per_thread(self):
|
|
190
|
+
return self._elements_per_thread
|
|
191
|
+
|
|
192
|
+
@property
|
|
193
|
+
def precision(self):
|
|
194
|
+
return self._precision
|
|
195
|
+
|
|
196
|
+
@property
|
|
197
|
+
def ffts_per_block(self):
|
|
198
|
+
return self._ffts_per_block
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
def fft_type(self):
|
|
202
|
+
return self._fft_type
|
|
203
|
+
|
|
204
|
+
@property
|
|
205
|
+
def direction(self):
|
|
206
|
+
return self._direction
|
|
207
|
+
|
|
208
|
+
@property
|
|
209
|
+
def size(self):
|
|
210
|
+
return self._size
|
|
211
|
+
|
|
212
|
+
@property
|
|
213
|
+
def execution(self):
|
|
214
|
+
return self._execution
|
|
215
|
+
|
|
216
|
+
@property
|
|
217
|
+
def real_fft_options(self):
|
|
218
|
+
return self._real_fft_options
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def code_type(self):
|
|
222
|
+
return self._code_type
|
|
223
|
+
|
|
224
|
+
#
|
|
225
|
+
# Extensions
|
|
226
|
+
#
|
|
227
|
+
|
|
228
|
+
def valid(self, *knobs):
|
|
229
|
+
if not (set(knobs) <= {"ffts_per_block", "elements_per_thread"}):
|
|
230
|
+
raise ValueError(f"Unsupported knob. Only valid knobs are ffts_per_block and elements_per_thread but got {knobs}")
|
|
231
|
+
|
|
232
|
+
return self._get_knobs(*knobs)
|
|
233
|
+
|
|
234
|
+
def definition(self):
|
|
235
|
+
dd = {
|
|
236
|
+
"size": self.size,
|
|
237
|
+
"precision": self.precision,
|
|
238
|
+
"fft_type": self.fft_type,
|
|
239
|
+
"code_type": self.code_type,
|
|
240
|
+
"execution": self.execution,
|
|
241
|
+
"direction": self.direction,
|
|
242
|
+
"ffts_per_block": self.ffts_per_block,
|
|
243
|
+
"elements_per_thread": self.elements_per_thread,
|
|
244
|
+
"real_fft_options": self.real_fft_options,
|
|
245
|
+
}
|
|
246
|
+
return dd
|
|
247
|
+
|
|
248
|
+
def create(self, **kwargs):
|
|
249
|
+
dd = self.definition()
|
|
250
|
+
dd.update(**kwargs)
|
|
251
|
+
return fft(**dd)
|
|
252
|
+
|
|
253
|
+
#
|
|
254
|
+
# Private implementations
|
|
255
|
+
#
|
|
256
|
+
|
|
257
|
+
def _suggested(self, what):
|
|
258
|
+
# Generate full PTX
|
|
259
|
+
h = generate_FFT(
|
|
260
|
+
size=self.size,
|
|
261
|
+
precision=self.precision,
|
|
262
|
+
fft_type=self.fft_type,
|
|
263
|
+
direction=self.direction,
|
|
264
|
+
ffts_per_block=(None if self.ffts_per_block == "suggested" else self.ffts_per_block),
|
|
265
|
+
elements_per_thread=(None if self.elements_per_thread == "suggested" else self.elements_per_thread),
|
|
266
|
+
real_fft_options=frozenset(self.real_fft_options.items()) if self.real_fft_options else None,
|
|
267
|
+
code_type=self.code_type,
|
|
268
|
+
execution=self.execution,
|
|
269
|
+
# TODO: remove after migrating to libmathdx 0.2.2+
|
|
270
|
+
execute_api="register_memory",
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
if what == "elements_per_thread":
|
|
274
|
+
return get_int_trait(h.descriptor, mathdx.CufftdxTraitType.ELEMENTS_PER_THREAD)
|
|
275
|
+
|
|
276
|
+
if what == "suggested_ffts_per_block":
|
|
277
|
+
return get_int_trait(h.descriptor, mathdx.CufftdxTraitType.SUGGESTED_FFTS_PER_BLOCK)
|
|
278
|
+
|
|
279
|
+
raise Exception(f"Unknown suggested option '{what}'")
|
|
280
|
+
|
|
281
|
+
@cached_property
|
|
282
|
+
def _suggested_ffts_per_block(self):
|
|
283
|
+
return self._suggested("suggested_ffts_per_block")
|
|
284
|
+
|
|
285
|
+
@cached_property
|
|
286
|
+
def _suggested_elements_per_thread(self):
|
|
287
|
+
return self._suggested("elements_per_thread")
|
|
288
|
+
|
|
289
|
+
def _get_knobs(self, *knobs):
|
|
290
|
+
if not (set(knobs) <= {"ffts_per_block", "elements_per_thread"}):
|
|
291
|
+
raise ValueError(f"Unsupported knob. Only valid knobs are ffts_per_block and elements_per_thread but got {knobs}")
|
|
292
|
+
|
|
293
|
+
h = generate_FFT(
|
|
294
|
+
size=self.size,
|
|
295
|
+
precision=self.precision,
|
|
296
|
+
fft_type=self.fft_type,
|
|
297
|
+
direction=self.direction,
|
|
298
|
+
ffts_per_block=self.ffts_per_block,
|
|
299
|
+
elements_per_thread=self.elements_per_thread,
|
|
300
|
+
real_fft_options=frozenset(self.real_fft_options.items()) if self.real_fft_options else None,
|
|
301
|
+
code_type=self.code_type,
|
|
302
|
+
execution=self.execution,
|
|
303
|
+
# TODO: remove after migrating to libmathdx 0.2.2+
|
|
304
|
+
execute_api="register_memory",
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
return get_knobs(h.descriptor, knobs)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
class FFTOptionsComplete(FFTOptions):
|
|
311
|
+
def __init__(self, **kwargs):
|
|
312
|
+
FFTOptions.__init__(self, **kwargs)
|
|
313
|
+
|
|
314
|
+
h = generate_FFT(
|
|
315
|
+
size=self.size,
|
|
316
|
+
precision=self.precision,
|
|
317
|
+
fft_type=self.fft_type,
|
|
318
|
+
direction=self.direction,
|
|
319
|
+
code_type=self.code_type,
|
|
320
|
+
execution=self.execution,
|
|
321
|
+
ffts_per_block=self.ffts_per_block if self.execution == "Block" else None,
|
|
322
|
+
elements_per_thread=self.elements_per_thread if self.execution == "Block" else None,
|
|
323
|
+
real_fft_options=frozenset(self.real_fft_options.items()) if self.real_fft_options else None,
|
|
324
|
+
# TODO: remove after migrating to libmathdx 0.2.2+
|
|
325
|
+
execute_api="register_memory",
|
|
326
|
+
).descriptor
|
|
327
|
+
|
|
328
|
+
self._value_type = MATHDX_TYPES_TO_NP[get_data_type_trait(h, mathdx.CufftdxTraitType.VALUE_TYPE)]
|
|
329
|
+
self._input_type = MATHDX_TYPES_TO_NP[get_data_type_trait(h, mathdx.CufftdxTraitType.INPUT_TYPE)]
|
|
330
|
+
self._output_type = MATHDX_TYPES_TO_NP[get_data_type_trait(h, mathdx.CufftdxTraitType.OUTPUT_TYPE)]
|
|
331
|
+
|
|
332
|
+
self._storage_size = get_int_trait(h, mathdx.CufftdxTraitType.STORAGE_SIZE)
|
|
333
|
+
self._stride = get_int_trait(h, mathdx.CufftdxTraitType.STRIDE)
|
|
334
|
+
self._elements_per_thread = get_int_trait(h, mathdx.CufftdxTraitType.ELEMENTS_PER_THREAD)
|
|
335
|
+
self._implicit_type_batching = get_int_trait(h, mathdx.CufftdxTraitType.IMPLICIT_TYPE_BATCHING)
|
|
336
|
+
|
|
337
|
+
self._workspace_size = 0
|
|
338
|
+
if self.execution == "Block":
|
|
339
|
+
self._block_dim = Dim3(*get_int_traits(h, mathdx.CufftdxTraitType.BLOCK_DIM, 3))
|
|
340
|
+
self._shared_memory_size = get_int_trait(h, mathdx.CufftdxTraitType.SHARED_MEMORY_SIZE)
|
|
341
|
+
self._ffts_per_block = get_int_trait(h, mathdx.CufftdxTraitType.FFTS_PER_BLOCK)
|
|
342
|
+
else:
|
|
343
|
+
self._block_dim = None
|
|
344
|
+
self._shared_memory_size = None
|
|
345
|
+
self._ffts_per_block = None
|
|
346
|
+
|
|
347
|
+
@property
|
|
348
|
+
def value_type(self):
|
|
349
|
+
return self._value_type
|
|
350
|
+
|
|
351
|
+
@property
|
|
352
|
+
def input_type(self):
|
|
353
|
+
return self._input_type
|
|
354
|
+
|
|
355
|
+
@property
|
|
356
|
+
def output_type(self):
|
|
357
|
+
return self._output_type
|
|
358
|
+
|
|
359
|
+
@property
|
|
360
|
+
def storage_size(self):
|
|
361
|
+
return self._storage_size
|
|
362
|
+
|
|
363
|
+
@property
|
|
364
|
+
def shared_memory_size(self):
|
|
365
|
+
return self._shared_memory_size
|
|
366
|
+
|
|
367
|
+
@property
|
|
368
|
+
def stride(self):
|
|
369
|
+
return self._stride
|
|
370
|
+
|
|
371
|
+
@property
|
|
372
|
+
def block_dim(self):
|
|
373
|
+
return self._block_dim
|
|
374
|
+
|
|
375
|
+
@property
|
|
376
|
+
def requires_workspace(self):
|
|
377
|
+
_workspace_deprecation_warning()
|
|
378
|
+
return False
|
|
379
|
+
|
|
380
|
+
@property
|
|
381
|
+
def workspace_size(self):
|
|
382
|
+
return self._workspace_size
|
|
383
|
+
|
|
384
|
+
@property
|
|
385
|
+
def implicit_type_batching(self):
|
|
386
|
+
return self._implicit_type_batching
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
class FFTCompiled(FFTOptionsComplete):
|
|
390
|
+
def __init__(self, **kwargs):
|
|
391
|
+
execute_api = kwargs.pop("execute_api", None)
|
|
392
|
+
super().__init__(**kwargs)
|
|
393
|
+
|
|
394
|
+
# Fixup typo introduced in earlier versions.
|
|
395
|
+
if execute_api == "registry_memory":
|
|
396
|
+
warnings.warn(
|
|
397
|
+
"The execute_api 'registry_memory' is deprecated and will be "
|
|
398
|
+
"removed in future releases. "
|
|
399
|
+
"Please use 'register_memory' instead.",
|
|
400
|
+
DeprecationWarning,
|
|
401
|
+
)
|
|
402
|
+
execute_api = "register_memory"
|
|
403
|
+
|
|
404
|
+
validate_execute_api(self.execution, execute_api)
|
|
405
|
+
|
|
406
|
+
if execute_api is None:
|
|
407
|
+
execute_api = "register_memory"
|
|
408
|
+
|
|
409
|
+
self._execute_api = execute_api
|
|
410
|
+
|
|
411
|
+
h = generate_FFT(
|
|
412
|
+
size=self.size,
|
|
413
|
+
precision=self.precision,
|
|
414
|
+
fft_type=self.fft_type,
|
|
415
|
+
direction=self.direction,
|
|
416
|
+
code_type=self.code_type,
|
|
417
|
+
execution=self.execution,
|
|
418
|
+
ffts_per_block=self.ffts_per_block if self.execution == "Block" else None,
|
|
419
|
+
elements_per_thread=self.elements_per_thread if self.execution == "Block" else None,
|
|
420
|
+
real_fft_options=frozenset(self.real_fft_options.items()) if self.real_fft_options else None,
|
|
421
|
+
execute_api=execute_api,
|
|
422
|
+
).descriptor
|
|
423
|
+
|
|
424
|
+
code = generate_code(h, self.code_type.cc)
|
|
425
|
+
|
|
426
|
+
# Compile
|
|
427
|
+
lto_fn = get_lto(code.descriptor)
|
|
428
|
+
isa_version = get_isa_version(code.descriptor)
|
|
429
|
+
|
|
430
|
+
self._ltos = [Code(self.code_type, isa_version, lto_fn)]
|
|
431
|
+
|
|
432
|
+
self._symbol = get_str_trait(h, mathdx.CufftdxTraitType.SYMBOL_NAME)
|
|
433
|
+
|
|
434
|
+
@cached_property
|
|
435
|
+
def _tempfiles(self):
|
|
436
|
+
"""
|
|
437
|
+
Create temporary files for the LTO functions.
|
|
438
|
+
"""
|
|
439
|
+
return [make_binary_tempfile(lto.data, ".ltoir") for lto in self._ltos]
|
|
440
|
+
|
|
441
|
+
@property
|
|
442
|
+
def files(self):
|
|
443
|
+
return [v.name for v in self._tempfiles]
|
|
444
|
+
|
|
445
|
+
@property
|
|
446
|
+
def symbol(self):
|
|
447
|
+
return self._symbol
|
|
448
|
+
|
|
449
|
+
@property
|
|
450
|
+
def codes(self):
|
|
451
|
+
return self._ltos
|
|
452
|
+
|
|
453
|
+
def workspace(self):
|
|
454
|
+
_workspace_deprecation_warning()
|
|
455
|
+
raise NotImplementedError("Workspace not supported yet")
|
|
456
|
+
|
|
457
|
+
@property
|
|
458
|
+
def execute_api(self):
|
|
459
|
+
return self._execute_api
|
|
460
|
+
|
|
461
|
+
def definition(self):
|
|
462
|
+
dd = super().definition()
|
|
463
|
+
dd.update(execute_api=self.execute_api)
|
|
464
|
+
return dd
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
class FFTNumba(FFTCompiled):
|
|
468
|
+
def __init__(self, **kwargs):
|
|
469
|
+
if "code_type" not in kwargs:
|
|
470
|
+
kwargs["code_type"] = get_default_code_type()
|
|
471
|
+
|
|
472
|
+
FFTCompiled.__init__(self, **kwargs)
|
|
473
|
+
|
|
474
|
+
codegen(
|
|
475
|
+
{
|
|
476
|
+
"value_type": self.value_type,
|
|
477
|
+
"symbol": self._symbol,
|
|
478
|
+
"execute_api": self._execute_api,
|
|
479
|
+
"execution": self.execution,
|
|
480
|
+
},
|
|
481
|
+
self,
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
def __call__(self, *args):
|
|
485
|
+
raise Exception("__call__ should not be called directly outside of a numba.cuda.jit(...) kernel.")
|
|
486
|
+
|
|
487
|
+
@property
|
|
488
|
+
def value_type(self):
|
|
489
|
+
return NP_TYPES_TO_NUMBA_FE_TYPES[super(FFTCompiled, self).value_type]
|
|
490
|
+
|
|
491
|
+
@property
|
|
492
|
+
def input_type(self):
|
|
493
|
+
return NP_TYPES_TO_NUMBA_FE_TYPES[super(FFTCompiled, self).input_type]
|
|
494
|
+
|
|
495
|
+
@property
|
|
496
|
+
def output_type(self):
|
|
497
|
+
return NP_TYPES_TO_NUMBA_FE_TYPES[super(FFTCompiled, self).output_type]
|
|
498
|
+
|
|
499
|
+
@property
|
|
500
|
+
def extensions(self):
|
|
501
|
+
raise NotImplementedError("Extensions not supported yet")
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
@docstring_decorator(FFTDX_DOCSTRING, skip_missing=False)
|
|
505
|
+
def fft(*, compiler=None, **kwargs):
|
|
506
|
+
"""
|
|
507
|
+
Create an :class:`FFTOptions` object that encapsulates a compiled and ready-to-use FFT
|
|
508
|
+
device function.
|
|
509
|
+
|
|
510
|
+
Args:
|
|
511
|
+
size (int): {size}
|
|
512
|
+
|
|
513
|
+
precision (str): {precision}
|
|
514
|
+
|
|
515
|
+
fft_type (str): {fft_type}
|
|
516
|
+
|
|
517
|
+
compiler (str): {compiler}
|
|
518
|
+
|
|
519
|
+
code_type (CodeType): {code_type}. Optional if compiler is specified as ``'numba'``.
|
|
520
|
+
|
|
521
|
+
execution (str): {execution}
|
|
522
|
+
|
|
523
|
+
direction (str): {direction}
|
|
524
|
+
|
|
525
|
+
ffts_per_block (int): {ffts_per_block}
|
|
526
|
+
|
|
527
|
+
elements_per_thread (int): {elements_per_thread}
|
|
528
|
+
|
|
529
|
+
real_fft_options (dict): {real_fft_options} User may specify the following options
|
|
530
|
+
in the dictionary:
|
|
531
|
+
|
|
532
|
+
- ``'complex_layout'``, currently supports ``'natural'``, ``'packed'``, and
|
|
533
|
+
``'full'``.
|
|
534
|
+
- ``'real_mode'``, currently supports ``'normal'`` and ``'folded'``.
|
|
535
|
+
|
|
536
|
+
execute_api (str): {execute_api}
|
|
537
|
+
|
|
538
|
+
See Also:
|
|
539
|
+
The attributes of :class:`FFTOptions` provide a 1:1 mapping with the CUDA C++
|
|
540
|
+
cuFFTDx APIs. For further details, please refer to `cuFFTDx documentation
|
|
541
|
+
<https://docs.nvidia.com/cuda/cufftdx/index.html>`_.
|
|
542
|
+
|
|
543
|
+
Examples:
|
|
544
|
+
Examples can be found in the `nvmath/examples/device
|
|
545
|
+
<https://github.com/NVIDIA/nvmath-python/tree/main/examples/device>`_ directory.
|
|
546
|
+
"""
|
|
547
|
+
check_in("compiler", compiler, [None, "numba"])
|
|
548
|
+
if compiler is None:
|
|
549
|
+
return FFTCompiled(**kwargs)
|
|
550
|
+
elif compiler == "numba":
|
|
551
|
+
return FFTNumba(**kwargs)
|