xobjects 0.6.8__tar.gz → 0.6.9__tar.gz
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.
- {xobjects-0.6.8/xobjects.egg-info → xobjects-0.6.9}/PKG-INFO +1 -1
- xobjects-0.6.9/tests/test_general.py +266 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_struct.py +7 -1
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/__init__.py +1 -0
- xobjects-0.6.9/xobjects/_version.py +1 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/context.py +3 -2
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/context_cpu.py +34 -36
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/context_cupy.py +16 -22
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/context_pyopencl.py +3 -2
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/general.py +11 -3
- xobjects-0.6.9/xobjects/settings.py +308 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/struct.py +7 -10
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/test_helpers.py +8 -14
- {xobjects-0.6.8 → xobjects-0.6.9/xobjects.egg-info}/PKG-INFO +1 -1
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects.egg-info/SOURCES.txt +2 -0
- xobjects-0.6.8/xobjects/_version.py +0 -1
- {xobjects-0.6.8 → xobjects-0.6.9}/Architecture.md +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/LICENSE +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/MANIFEST.in +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/README.md +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/pyproject.toml +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/setup.cfg +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/setup.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_align.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_array.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_buffer.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_capi.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_chunk.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_common.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_context_opencl.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_hybrid_class.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_kernel.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_linked_array.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_nplike_arrays.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_ref.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_scalars.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_shared_memory.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_strides.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_string.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_to_dict.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_typeutils.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/tests/test_unionref.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/_patch_pyopencl_array.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/array.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/capi.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/headers/atomicadd.h +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/headers/common.h +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/hybrid_class.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/linkedarray.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/ref.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/scalar.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/specialize_source.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/string.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/typeutils.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects/union.py +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects.egg-info/dependency_links.txt +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects.egg-info/entry_points.txt +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects.egg-info/requires.txt +0 -0
- {xobjects-0.6.8 → xobjects-0.6.9}/xobjects.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
import xobjects as xo
|
|
8
|
+
from xobjects.general import Print
|
|
9
|
+
from xobjects.test_helpers import allow_kernel_compilation
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_print_mode_default(capsys):
|
|
13
|
+
printer = Print()
|
|
14
|
+
|
|
15
|
+
printer('visible')
|
|
16
|
+
|
|
17
|
+
assert capsys.readouterr().out == 'visible\n'
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_print_mode_suppressed(capsys):
|
|
21
|
+
printer = Print()
|
|
22
|
+
with xo.settings.override(print_mode='suppress'):
|
|
23
|
+
printer('hidden')
|
|
24
|
+
|
|
25
|
+
assert capsys.readouterr().out == ''
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_settings_control_xsuite_printer(capsys):
|
|
29
|
+
with xo.settings.override(print_mode='suppress'):
|
|
30
|
+
xo._print('hidden')
|
|
31
|
+
|
|
32
|
+
assert capsys.readouterr().out == ''
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_python_setting_overrides_environment_default(capsys):
|
|
36
|
+
with xo.settings.override(print_mode='print'):
|
|
37
|
+
xo._print('visible')
|
|
38
|
+
|
|
39
|
+
assert capsys.readouterr().out == 'visible\n'
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_invalid_print_mode_setting():
|
|
43
|
+
with pytest.raises(ValueError, match='XSUITE_PRINT_MODE.*print.*suppress'):
|
|
44
|
+
xo.settings.print_mode = 'invalid'
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_settings_override_restores_value_after_error():
|
|
48
|
+
original = xo.settings.print_mode
|
|
49
|
+
|
|
50
|
+
with pytest.raises(RuntimeError):
|
|
51
|
+
with xo.settings.override(print_mode='suppress'):
|
|
52
|
+
assert xo.settings.print_mode == 'suppress'
|
|
53
|
+
raise RuntimeError
|
|
54
|
+
|
|
55
|
+
assert xo.settings.print_mode == original
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_settings_are_discoverable():
|
|
59
|
+
expected_settings = {
|
|
60
|
+
'print_mode',
|
|
61
|
+
'progress_indicator',
|
|
62
|
+
'allow_kernel_compilation',
|
|
63
|
+
'force_kernel_compilation',
|
|
64
|
+
'show_kernel_diagnostics',
|
|
65
|
+
'cffi_forbid_compile',
|
|
66
|
+
'cffi_keep_build_files',
|
|
67
|
+
'cuda_backend',
|
|
68
|
+
'cuda_fast_compile',
|
|
69
|
+
'cuda_compiler',
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
assert expected_settings <= set(dir(xo.settings))
|
|
73
|
+
for name in expected_settings:
|
|
74
|
+
assert f'{name}=' in repr(xo.settings)
|
|
75
|
+
assert name in type(xo.settings).__doc__
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_print_mode_environment_variable_is_startup_default():
|
|
79
|
+
environment = os.environ.copy()
|
|
80
|
+
environment['XSUITE_PRINT_MODE'] = 'suppress'
|
|
81
|
+
code = (
|
|
82
|
+
'import xobjects as xo; '
|
|
83
|
+
'assert xo.settings.print_mode == "suppress"; '
|
|
84
|
+
'xo._print("hidden")')
|
|
85
|
+
|
|
86
|
+
completed = subprocess.run(
|
|
87
|
+
[sys.executable, '-c', code],
|
|
88
|
+
env=environment,
|
|
89
|
+
capture_output=True,
|
|
90
|
+
text=True,
|
|
91
|
+
check=True,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
assert completed.stdout == ''
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_print_mode_environment_variable_can_be_overridden_in_python():
|
|
98
|
+
environment = os.environ.copy()
|
|
99
|
+
environment['XSUITE_PRINT_MODE'] = 'suppress'
|
|
100
|
+
code = (
|
|
101
|
+
'import xobjects as xo; '
|
|
102
|
+
'xo.settings.print_mode = "print"; '
|
|
103
|
+
'assert xo.settings.print_mode == "print"; '
|
|
104
|
+
'xo._print("visible")')
|
|
105
|
+
|
|
106
|
+
completed = subprocess.run(
|
|
107
|
+
[sys.executable, '-c', code],
|
|
108
|
+
env=environment,
|
|
109
|
+
capture_output=True,
|
|
110
|
+
text=True,
|
|
111
|
+
check=True,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
assert completed.stdout == 'visible\n'
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_environment_change_after_import_does_not_override_python_setting(
|
|
118
|
+
capsys, monkeypatch):
|
|
119
|
+
with xo.settings.override(print_mode='print'):
|
|
120
|
+
monkeypatch.setenv('XSUITE_PRINT_MODE', 'suppress')
|
|
121
|
+
xo._print('visible')
|
|
122
|
+
|
|
123
|
+
assert capsys.readouterr().out == 'visible\n'
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@pytest.mark.parametrize('value', ['1', 'true', 'YES', 'on'])
|
|
127
|
+
def test_boolean_environment_true_values(value):
|
|
128
|
+
environment = os.environ.copy()
|
|
129
|
+
environment['XSUITE_ALLOW_KERNEL_COMPILATION'] = value
|
|
130
|
+
code = (
|
|
131
|
+
'import xobjects as xo; '
|
|
132
|
+
'assert xo.settings.allow_kernel_compilation is True; '
|
|
133
|
+
'xo.settings.allow_kernel_compilation = False; '
|
|
134
|
+
'assert xo.settings.allow_kernel_compilation is False')
|
|
135
|
+
|
|
136
|
+
subprocess.run(
|
|
137
|
+
[sys.executable, '-c', code],
|
|
138
|
+
env=environment,
|
|
139
|
+
capture_output=True,
|
|
140
|
+
text=True,
|
|
141
|
+
check=True,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@pytest.mark.parametrize('value', ['0', 'false', 'NO', 'off'])
|
|
146
|
+
def test_boolean_environment_false_values(value):
|
|
147
|
+
environment = os.environ.copy()
|
|
148
|
+
environment['XSUITE_FORCE_KERNEL_COMPILATION'] = value
|
|
149
|
+
code = (
|
|
150
|
+
'import xobjects as xo; '
|
|
151
|
+
'assert xo.settings.force_kernel_compilation is False')
|
|
152
|
+
|
|
153
|
+
subprocess.run(
|
|
154
|
+
[sys.executable, '-c', code],
|
|
155
|
+
env=environment,
|
|
156
|
+
capture_output=True,
|
|
157
|
+
text=True,
|
|
158
|
+
check=True,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def test_invalid_boolean_environment_value():
|
|
163
|
+
environment = os.environ.copy()
|
|
164
|
+
environment['XSUITE_CFFI_FORBID_COMPILE'] = 'sometimes'
|
|
165
|
+
|
|
166
|
+
completed = subprocess.run(
|
|
167
|
+
[sys.executable, '-c', 'import xobjects'],
|
|
168
|
+
env=environment,
|
|
169
|
+
capture_output=True,
|
|
170
|
+
text=True,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
assert completed.returncode != 0
|
|
174
|
+
assert 'Invalid boolean value' in completed.stderr
|
|
175
|
+
assert 'xobjects.settings.cffi_forbid_compile' in completed.stderr
|
|
176
|
+
assert 'XSUITE_CFFI_FORBID_COMPILE' in completed.stderr
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def test_runtime_settings_environment_defaults():
|
|
180
|
+
environment = os.environ.copy()
|
|
181
|
+
environment.update({
|
|
182
|
+
'XSUITE_PROGRESS_INDICATOR': 'text',
|
|
183
|
+
'XSUITE_FORCE_KERNEL_COMPILATION': 'yes',
|
|
184
|
+
'XSUITE_SHOW_KERNEL_DIAGNOSTICS': 'on',
|
|
185
|
+
'XSUITE_CFFI_FORBID_COMPILE': 'true',
|
|
186
|
+
'XSUITE_CFFI_KEEP_BUILD_FILES': '1',
|
|
187
|
+
'XSUITE_CUDA_BACKEND': 'clang',
|
|
188
|
+
'XSUITE_CUDA_FAST_COMPILE': 'false',
|
|
189
|
+
'XSUITE_CUDA_COMPILER': '/path/to/clang++',
|
|
190
|
+
})
|
|
191
|
+
code = (
|
|
192
|
+
'import xobjects as xo; '
|
|
193
|
+
'assert xo.settings.progress_indicator == "text"; '
|
|
194
|
+
'assert xo.settings.force_kernel_compilation is True; '
|
|
195
|
+
'assert xo.settings.show_kernel_diagnostics is True; '
|
|
196
|
+
'assert xo.settings.cffi_forbid_compile is True; '
|
|
197
|
+
'assert xo.settings.cffi_keep_build_files is True; '
|
|
198
|
+
'assert xo.settings.cuda_backend == "clang"; '
|
|
199
|
+
'assert xo.settings.cuda_fast_compile is False; '
|
|
200
|
+
'assert xo.settings.cuda_compiler == "/path/to/clang++"')
|
|
201
|
+
|
|
202
|
+
subprocess.run(
|
|
203
|
+
[sys.executable, '-c', code],
|
|
204
|
+
env=environment,
|
|
205
|
+
capture_output=True,
|
|
206
|
+
text=True,
|
|
207
|
+
check=True,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@pytest.mark.parametrize(
|
|
212
|
+
'allow, force, compilation_allowed',
|
|
213
|
+
[
|
|
214
|
+
(False, False, False),
|
|
215
|
+
(True, False, True),
|
|
216
|
+
(False, True, True),
|
|
217
|
+
(True, True, True),
|
|
218
|
+
],
|
|
219
|
+
)
|
|
220
|
+
def test_kernel_compilation_settings(allow, force, compilation_allowed):
|
|
221
|
+
with xo.settings.override(
|
|
222
|
+
allow_kernel_compilation=allow,
|
|
223
|
+
force_kernel_compilation=force,
|
|
224
|
+
):
|
|
225
|
+
assert xo.context_cpu.kernel_compilation_allowed(
|
|
226
|
+
xo.ContextCpu()) is compilation_allowed
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def test_user_context_environment_variable(monkeypatch):
|
|
230
|
+
monkeypatch.setenv('XOBJECTS_USER_CONTEXT', 'ContextCpu:auto')
|
|
231
|
+
context = xo.get_user_context()
|
|
232
|
+
|
|
233
|
+
assert context.openmp_enabled
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def test_test_contexts_environment_variable(monkeypatch):
|
|
237
|
+
monkeypatch.setenv(
|
|
238
|
+
'XOBJECTS_TEST_CONTEXTS',
|
|
239
|
+
'ContextCpu;ContextCpu:auto',
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
contexts = list(xo.context.get_test_contexts())
|
|
243
|
+
|
|
244
|
+
assert len(contexts) == 2
|
|
245
|
+
assert contexts[0].openmp_enabled is False
|
|
246
|
+
assert contexts[1].openmp_enabled is True
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def test_cffi_forbid_compile_setting():
|
|
250
|
+
with xo.settings.override(cffi_forbid_compile=True):
|
|
251
|
+
with pytest.raises(RuntimeError) as err:
|
|
252
|
+
xo.ContextCpu().build_kernels({})
|
|
253
|
+
|
|
254
|
+
message = str(err.value)
|
|
255
|
+
assert 'xobjects.settings.cffi_forbid_compile' in message
|
|
256
|
+
assert 'XSUITE_CFFI_FORBID_COMPILE' in message
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def test_allow_kernel_compilation_decorator_restores_state():
|
|
260
|
+
@allow_kernel_compilation(skip_when_forbid_compile=False)
|
|
261
|
+
def decorated():
|
|
262
|
+
assert xo.settings.allow_kernel_compilation is True
|
|
263
|
+
|
|
264
|
+
with xo.settings.override(allow_kernel_compilation=False):
|
|
265
|
+
decorated()
|
|
266
|
+
assert xo.settings.allow_kernel_compilation is False
|
|
@@ -6,7 +6,11 @@ import cffi
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
8
8
|
import xobjects as xo
|
|
9
|
-
from xobjects.test_helpers import
|
|
9
|
+
from xobjects.test_helpers import (
|
|
10
|
+
allow_kernel_compilation,
|
|
11
|
+
for_all_test_contexts,
|
|
12
|
+
requires_context,
|
|
13
|
+
)
|
|
10
14
|
|
|
11
15
|
|
|
12
16
|
def test_static_struct_def():
|
|
@@ -299,6 +303,7 @@ double mult_four(MyStruct stru) {
|
|
|
299
303
|
|
|
300
304
|
|
|
301
305
|
@requires_context("ContextCpu")
|
|
306
|
+
@allow_kernel_compilation
|
|
302
307
|
def test_compile_kernels_only_if_needed(tmp_path, mocker):
|
|
303
308
|
"""Test the use case of xtrack.
|
|
304
309
|
|
|
@@ -348,6 +353,7 @@ def test_compile_kernels_only_if_needed(tmp_path, mocker):
|
|
|
348
353
|
|
|
349
354
|
|
|
350
355
|
@requires_context("ContextCpu")
|
|
356
|
+
@allow_kernel_compilation
|
|
351
357
|
def test_thisclass_placeholder_on_struct():
|
|
352
358
|
test_context = xo.ContextCpu()
|
|
353
359
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.9"
|
|
@@ -207,6 +207,7 @@ class ModuleNotAvailable(object):
|
|
|
207
207
|
class XContext(ABC):
|
|
208
208
|
minimum_alignment = 1
|
|
209
209
|
allow_prebuilt_kernels = False
|
|
210
|
+
allow_kernel_compilation = False
|
|
210
211
|
|
|
211
212
|
def __init__(self):
|
|
212
213
|
self._kernels = KernelDict()
|
|
@@ -776,8 +777,8 @@ def get_test_contexts():
|
|
|
776
777
|
|
|
777
778
|
def get_user_context():
|
|
778
779
|
"""
|
|
779
|
-
Get the context
|
|
780
|
-
If not
|
|
780
|
+
Get the context specified by the environment variable
|
|
781
|
+
``XOBJECTS_USER_CONTEXT``. If it is not set, use ``ContextCpu()``.
|
|
781
782
|
|
|
782
783
|
Examples:
|
|
783
784
|
ContextPyopencl:0.0 -> ContextPyopencl(device="0.0")
|
|
@@ -13,42 +13,42 @@ from typing import Callable, Dict, List, Sequence, Tuple
|
|
|
13
13
|
import weakref
|
|
14
14
|
|
|
15
15
|
from .general import _print
|
|
16
|
+
from .settings import settings
|
|
16
17
|
|
|
17
18
|
import numpy as np
|
|
18
19
|
import scipy as sp
|
|
19
20
|
|
|
20
|
-
_forbid_compile = False
|
|
21
21
|
_suppress_warnings = False
|
|
22
|
-
allow_no_prebuilt_kernel = False
|
|
23
22
|
|
|
24
23
|
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
def _class_allows_kernel_compilation(cls):
|
|
25
|
+
for candidate in (
|
|
26
|
+
cls,
|
|
27
|
+
getattr(cls, "_DressingClass", None),
|
|
28
|
+
getattr(cls, "_XoStruct", None),
|
|
29
|
+
):
|
|
30
|
+
if candidate is None:
|
|
31
|
+
continue
|
|
32
|
+
if getattr(candidate, "allow_kernel_compilation", False):
|
|
33
|
+
return True
|
|
34
|
+
# Compatibility with classes from packages that have not migrated yet.
|
|
35
|
+
if getattr(candidate, "allow_no_prebuilt_kernel", False):
|
|
36
|
+
return True
|
|
37
|
+
return False
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
def
|
|
40
|
+
def kernel_compilation_allowed(context=None, classes=()):
|
|
40
41
|
if classes is None:
|
|
41
42
|
classes = ()
|
|
42
43
|
elif isinstance(classes, type):
|
|
43
44
|
classes = (classes,)
|
|
44
45
|
|
|
45
|
-
if
|
|
46
|
-
|
|
47
|
-
if allow_no_prebuilt_kernel:
|
|
46
|
+
if (settings.allow_kernel_compilation
|
|
47
|
+
or settings.force_kernel_compilation):
|
|
48
48
|
return True
|
|
49
|
-
if any(
|
|
49
|
+
if any(_class_allows_kernel_compilation(cls) for cls in classes):
|
|
50
50
|
return True
|
|
51
|
-
return getattr(context, "
|
|
51
|
+
return getattr(context, "allow_kernel_compilation", False)
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def _is_serial_cpu_context(context):
|
|
@@ -58,20 +58,20 @@ def _is_serial_cpu_context(context):
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def require_prebuilt_kernel(context=None, classes=()):
|
|
61
|
-
return not
|
|
61
|
+
return not kernel_compilation_allowed(
|
|
62
62
|
context, classes=classes
|
|
63
63
|
) and _is_serial_cpu_context(context)
|
|
64
64
|
|
|
65
65
|
|
|
66
|
-
def
|
|
66
|
+
def kernel_compilation_help_message():
|
|
67
67
|
return (
|
|
68
68
|
"To allow just-in-time compilation instead, as in older Xsuite "
|
|
69
|
-
"versions, set
|
|
70
|
-
"
|
|
71
|
-
"`
|
|
72
|
-
"`context.
|
|
69
|
+
"versions, set `xobjects.settings.allow_kernel_compilation = True`, "
|
|
70
|
+
"or equivalently set the environment variable "
|
|
71
|
+
"`XSUITE_ALLOW_KERNEL_COMPILATION=1`, or set "
|
|
72
|
+
"`context.allow_kernel_compilation = True`. Classes that require "
|
|
73
73
|
"just-in-time compilation can also define "
|
|
74
|
-
"`
|
|
74
|
+
"`allow_kernel_compilation = True` as a class attribute. Using "
|
|
75
75
|
"just-in-time compilation instead of prebuilt kernels may require "
|
|
76
76
|
"lengthy compilation whenever a different kernel is needed."
|
|
77
77
|
)
|
|
@@ -369,13 +369,11 @@ class ContextCpu(XContext):
|
|
|
369
369
|
cdefs = "\n".join(cls._gen_c_decl({}) for cls in classes)
|
|
370
370
|
cdefs += "\n" + extra_cdef
|
|
371
371
|
|
|
372
|
-
if
|
|
373
|
-
raise RuntimeError("Compilation is forbidden")
|
|
374
|
-
|
|
375
|
-
if os.environ.get("XOBJECTS_FORBID_COMPILE"):
|
|
372
|
+
if settings.cffi_forbid_compile:
|
|
376
373
|
raise RuntimeError(
|
|
377
|
-
"
|
|
378
|
-
"
|
|
374
|
+
"CFFI compilation is forbidden by "
|
|
375
|
+
"xobjects.settings.cffi_forbid_compile or equivalently "
|
|
376
|
+
"the environment variable XSUITE_CFFI_FORBID_COMPILE."
|
|
379
377
|
)
|
|
380
378
|
|
|
381
379
|
so_file = self.compile_kernel(
|
|
@@ -536,7 +534,7 @@ class ContextCpu(XContext):
|
|
|
536
534
|
return Path(output_file)
|
|
537
535
|
finally:
|
|
538
536
|
# Clean temp files
|
|
539
|
-
if
|
|
537
|
+
if not settings.cffi_keep_build_files:
|
|
540
538
|
files_to_remove = [
|
|
541
539
|
module_name + ".c",
|
|
542
540
|
module_name + ".o",
|
|
@@ -961,8 +959,8 @@ class FFTCpu(object):
|
|
|
961
959
|
direction="FFTW_BACKWARD",
|
|
962
960
|
flags=("FFTW_MEASURE",),
|
|
963
961
|
)
|
|
964
|
-
|
|
965
|
-
|
|
962
|
+
_print(f"fftw simd_aligned={self.fftw.simd_aligned}")
|
|
963
|
+
_print(f"ifftw simd_aligned={self.fftw.simd_aligned}")
|
|
966
964
|
else:
|
|
967
965
|
# I perform one fft to have numpy cache the plan
|
|
968
966
|
_ = np.fft.ifftn(np.fft.fftn(data, axes=axes), axes=axes)
|
|
@@ -25,18 +25,11 @@ from .context import (
|
|
|
25
25
|
sources_from_classes,
|
|
26
26
|
)
|
|
27
27
|
from .linkedarray import BaseLinkedArray
|
|
28
|
+
from .settings import settings
|
|
28
29
|
from .specialize_source import specialize_source
|
|
29
30
|
|
|
30
31
|
log = logging.getLogger(__name__)
|
|
31
32
|
|
|
32
|
-
no_fast_compile = False
|
|
33
|
-
"""Disable NVRTC fast compile tuning when building CUDA kernels.
|
|
34
|
-
|
|
35
|
-
When set to ``True``, ``ContextCupy`` does not pass ``--Ofast-compile=min``
|
|
36
|
-
to NVRTC. The ``XO_CUDA_NO_FAST_COMPILE`` environment variable provides the
|
|
37
|
-
same behavior.
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
33
|
try:
|
|
41
34
|
import cupy
|
|
42
35
|
import cupyx.scipy
|
|
@@ -399,12 +392,12 @@ class ContextCupy(XContext):
|
|
|
399
392
|
Creates a Cupy Context object, that allows performing the computations
|
|
400
393
|
on nVidia GPUs.
|
|
401
394
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
variable ``
|
|
395
|
+
``xobjects.settings.cuda_fast_compile`` controls whether NVRTC fast compile
|
|
396
|
+
tuning is enabled. By default it is ``True``, so CUDA kernels built with
|
|
397
|
+
NVRTC >= 12.9 use ``--Ofast-compile=min`` to reduce compilation time and
|
|
398
|
+
memory usage, at the cost of some runtime performance. Set
|
|
399
|
+
``xobjects.settings.cuda_fast_compile = False``, or equivalently the
|
|
400
|
+
environment variable ``XSUITE_CUDA_FAST_COMPILE=0``, to disable it.
|
|
408
401
|
|
|
409
402
|
Args:
|
|
410
403
|
default_block_size (int): CUDA thread size that is used by default
|
|
@@ -439,8 +432,8 @@ class ContextCupy(XContext):
|
|
|
439
432
|
self.default_block_size = default_block_size
|
|
440
433
|
self.default_shared_mem_size_bytes = default_shared_mem_size_bytes
|
|
441
434
|
|
|
442
|
-
if
|
|
443
|
-
backend =
|
|
435
|
+
if backend is None:
|
|
436
|
+
backend = settings.cuda_backend
|
|
444
437
|
|
|
445
438
|
if backend not in ["nvrtc", "clang"]:
|
|
446
439
|
raise ValueError(
|
|
@@ -516,9 +509,7 @@ class ContextCupy(XContext):
|
|
|
516
509
|
if self.backend == "nvrtc":
|
|
517
510
|
# NVRTC (default): add NVRTC-specific flags
|
|
518
511
|
nvrtc_args = (*extra_compile_args,)
|
|
519
|
-
fast_compile =
|
|
520
|
-
no_fast_compile or os.environ.get("XO_CUDA_NO_FAST_COMPILE")
|
|
521
|
-
)
|
|
512
|
+
fast_compile = settings.cuda_fast_compile
|
|
522
513
|
if nvrtc and nvrtc.getVersion() >= (12, 9):
|
|
523
514
|
# If supported, skip prohibitively heavy optimisations (e.g.
|
|
524
515
|
# involving cloning). This it at the expense of <20%
|
|
@@ -558,7 +549,7 @@ class ContextCupy(XContext):
|
|
|
558
549
|
return out_kernels
|
|
559
550
|
|
|
560
551
|
def _find_clang(self):
|
|
561
|
-
override =
|
|
552
|
+
override = settings.cuda_compiler
|
|
562
553
|
if override:
|
|
563
554
|
return override
|
|
564
555
|
|
|
@@ -567,8 +558,11 @@ class ContextCupy(XContext):
|
|
|
567
558
|
return found
|
|
568
559
|
|
|
569
560
|
raise RuntimeError(
|
|
570
|
-
"clang++ for the CUDA context not found. Either install clang so
|
|
571
|
-
"
|
|
561
|
+
"clang++ for the CUDA context not found. Either install clang so "
|
|
562
|
+
"that 'clang++' is on PATH, or set "
|
|
563
|
+
"xobjects.settings.cuda_compiler, or equivalently the environment "
|
|
564
|
+
"variable XSUITE_CUDA_COMPILER, to the desired clang++ "
|
|
565
|
+
"executable."
|
|
572
566
|
)
|
|
573
567
|
|
|
574
568
|
def _build_module_with_clang(self, source, extra_compile_args=()):
|
|
@@ -21,6 +21,7 @@ from .context import (
|
|
|
21
21
|
)
|
|
22
22
|
from .linkedarray import BaseLinkedArray
|
|
23
23
|
from .specialize_source import specialize_source
|
|
24
|
+
from .general import _print
|
|
24
25
|
|
|
25
26
|
log = logging.getLogger(__name__)
|
|
26
27
|
|
|
@@ -100,9 +101,9 @@ class ContextPyopencl(XContext):
|
|
|
100
101
|
@classmethod
|
|
101
102
|
def print_devices(cls):
|
|
102
103
|
for ip, platform in enumerate(cl.get_platforms()):
|
|
103
|
-
|
|
104
|
+
_print(f"Platform {ip} : {platform.name}")
|
|
104
105
|
for id, device in enumerate(platform.get_devices()):
|
|
105
|
-
|
|
106
|
+
_print(f"Device {ip}.{id}: {device.name}")
|
|
106
107
|
|
|
107
108
|
def __init__(
|
|
108
109
|
self, device=None, patch_pyopencl_array=True, minimum_alignment=None
|
|
@@ -5,13 +5,21 @@
|
|
|
5
5
|
from numpy.testing import assert_allclose as np_assert_allclose
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
8
|
+
from .settings import settings
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
class Print:
|
|
10
|
-
|
|
12
|
+
"""Configurable wrapper around :func:`print` used by Xsuite.
|
|
13
|
+
|
|
14
|
+
The behavior is controlled by ``xobjects.settings.print_mode``, or
|
|
15
|
+
equivalently the environment variable ``XSUITE_PRINT_MODE``.
|
|
16
|
+
"""
|
|
11
17
|
|
|
12
18
|
def __call__(self, *args, **kwargs):
|
|
13
|
-
if
|
|
14
|
-
|
|
19
|
+
if settings.print_mode == 'suppress':
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
print(*args, **kwargs)
|
|
15
23
|
|
|
16
24
|
|
|
17
25
|
_print = Print()
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Settings:
|
|
6
|
+
"""Process-wide settings shared by the Xsuite packages.
|
|
7
|
+
|
|
8
|
+
Available settings and their equivalent environment variables are:
|
|
9
|
+
|
|
10
|
+
``print_mode`` — ``XSUITE_PRINT_MODE``
|
|
11
|
+
Values: ``print`` (default), ``suppress``
|
|
12
|
+
Controls informational output produced by Xsuite.
|
|
13
|
+
|
|
14
|
+
``progress_indicator`` — ``XSUITE_PROGRESS_INDICATOR``
|
|
15
|
+
Values: ``tqdm`` (default), ``text``, ``suppress``
|
|
16
|
+
Selects how progress is displayed when printing is enabled.
|
|
17
|
+
|
|
18
|
+
``allow_kernel_compilation`` — ``XSUITE_ALLOW_KERNEL_COMPILATION``
|
|
19
|
+
Values: ``False`` (default), ``True``
|
|
20
|
+
Allows compilation when no compatible prebuilt kernel is available.
|
|
21
|
+
|
|
22
|
+
``force_kernel_compilation`` — ``XSUITE_FORCE_KERNEL_COMPILATION``
|
|
23
|
+
Values: ``False`` (default), ``True``
|
|
24
|
+
Always compiles kernels and skips prebuilt-kernel lookup. Intended
|
|
25
|
+
primarily for Xsuite development and debugging.
|
|
26
|
+
|
|
27
|
+
``show_kernel_diagnostics`` — ``XSUITE_SHOW_KERNEL_DIAGNOSTICS``
|
|
28
|
+
Values: ``False`` (default), ``True``
|
|
29
|
+
During prebuilt-kernel selection, reports why each candidate kernel is
|
|
30
|
+
selected or rejected.
|
|
31
|
+
|
|
32
|
+
``cffi_forbid_compile`` — ``XSUITE_CFFI_FORBID_COMPILE``
|
|
33
|
+
Values: ``False`` (default), ``True``
|
|
34
|
+
Prevents CFFI from compiling CPU kernels. Used primarily for debugging
|
|
35
|
+
and testing.
|
|
36
|
+
|
|
37
|
+
``cffi_keep_build_files`` — ``XSUITE_CFFI_KEEP_BUILD_FILES``
|
|
38
|
+
Values: ``False`` (default), ``True``
|
|
39
|
+
Keeps the intermediate files generated by CFFI. Used primarily for
|
|
40
|
+
debugging and testing.
|
|
41
|
+
|
|
42
|
+
``cuda_backend`` — ``XSUITE_CUDA_BACKEND``
|
|
43
|
+
Values: ``nvrtc`` (default), ``clang``
|
|
44
|
+
Selects the compiler backend used for CUDA kernels.
|
|
45
|
+
|
|
46
|
+
``cuda_fast_compile`` — ``XSUITE_CUDA_FAST_COMPILE``
|
|
47
|
+
Values: ``True`` (default), ``False``
|
|
48
|
+
Enables faster NVRTC compilation when supported.
|
|
49
|
+
|
|
50
|
+
``cuda_compiler`` — ``XSUITE_CUDA_COMPILER``
|
|
51
|
+
Values: ``None`` (default), executable path
|
|
52
|
+
Selects the clang++ executable used by the CUDA clang backend.
|
|
53
|
+
|
|
54
|
+
Notes
|
|
55
|
+
-----
|
|
56
|
+
The same object is exposed as ``xobjects.settings`` and
|
|
57
|
+
``xtrack.settings``. Environment variables provide its initial values when
|
|
58
|
+
Xobjects is imported. Later Python assignments take precedence and can be
|
|
59
|
+
applied temporarily with :meth:`override`.
|
|
60
|
+
|
|
61
|
+
Boolean environment variables accept ``1``/``0``, ``true``/``false``,
|
|
62
|
+
``yes``/``no``, and ``on``/``off``, case-insensitively.
|
|
63
|
+
|
|
64
|
+
``force_kernel_compilation=True`` skips prebuilt-kernel lookup and takes
|
|
65
|
+
precedence over ``allow_kernel_compilation``. When forcing is disabled,
|
|
66
|
+
``allow_kernel_compilation=True`` permits compilation only if a compatible
|
|
67
|
+
prebuilt kernel is unavailable. Compilation can also be enabled for one
|
|
68
|
+
context or element class by setting its ``allow_kernel_compilation``
|
|
69
|
+
attribute to ``True``. The legacy class attribute
|
|
70
|
+
``allow_no_prebuilt_kernel`` is temporarily recognized for compatibility
|
|
71
|
+
with packages that have not migrated yet.
|
|
72
|
+
|
|
73
|
+
Examples
|
|
74
|
+
--------
|
|
75
|
+
Allow Xsuite to compile a kernel when no compatible prebuilt kernel is
|
|
76
|
+
available:
|
|
77
|
+
|
|
78
|
+
>>> import xtrack as xt
|
|
79
|
+
>>> xt.settings.allow_kernel_compilation = True
|
|
80
|
+
|
|
81
|
+
Equivalently, set ``XSUITE_ALLOW_KERNEL_COMPILATION=1`` before starting
|
|
82
|
+
Python.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
def __init__(self):
|
|
86
|
+
object.__setattr__(self, '_definitions', {})
|
|
87
|
+
object.__setattr__(self, '_values', {})
|
|
88
|
+
|
|
89
|
+
def _register(
|
|
90
|
+
self,
|
|
91
|
+
name,
|
|
92
|
+
*,
|
|
93
|
+
default,
|
|
94
|
+
environment_variable=None,
|
|
95
|
+
choices=None,
|
|
96
|
+
environment_parser=None,
|
|
97
|
+
value_type=None,
|
|
98
|
+
):
|
|
99
|
+
if name in self._definitions:
|
|
100
|
+
raise ValueError(f'Setting {name!r} is already registered.')
|
|
101
|
+
|
|
102
|
+
definition = {
|
|
103
|
+
'environment_variable': environment_variable,
|
|
104
|
+
'choices': choices,
|
|
105
|
+
'value_type': value_type,
|
|
106
|
+
}
|
|
107
|
+
self._definitions[name] = definition
|
|
108
|
+
|
|
109
|
+
value = default
|
|
110
|
+
if (environment_variable is not None
|
|
111
|
+
and environment_variable in os.environ):
|
|
112
|
+
environment_value = os.environ[environment_variable]
|
|
113
|
+
try:
|
|
114
|
+
value = (environment_parser(environment_value)
|
|
115
|
+
if environment_parser else environment_value)
|
|
116
|
+
except (TypeError, ValueError) as err:
|
|
117
|
+
raise ValueError(
|
|
118
|
+
f'Invalid value for '
|
|
119
|
+
f'{self._setting_description(name, definition)}: '
|
|
120
|
+
f'{err}') from err
|
|
121
|
+
self._set(name, value)
|
|
122
|
+
|
|
123
|
+
def _set(self, name, value):
|
|
124
|
+
try:
|
|
125
|
+
definition = self._definitions[name]
|
|
126
|
+
except KeyError as err:
|
|
127
|
+
raise AttributeError(f'Unknown Xsuite setting {name!r}.') from err
|
|
128
|
+
|
|
129
|
+
choices = definition['choices']
|
|
130
|
+
value_type = definition['value_type']
|
|
131
|
+
setting_description = self._setting_description(name, definition)
|
|
132
|
+
if value_type is not None and not isinstance(value, value_type):
|
|
133
|
+
raise TypeError(
|
|
134
|
+
f'Invalid value {value!r} for {setting_description}; '
|
|
135
|
+
f'expected {self._type_name(value_type)}.')
|
|
136
|
+
if choices is not None and value not in choices:
|
|
137
|
+
expected = ', '.join(repr(choice) for choice in choices)
|
|
138
|
+
raise ValueError(
|
|
139
|
+
f'Invalid value {value!r} for {setting_description}; '
|
|
140
|
+
f'expected one of {expected}.')
|
|
141
|
+
|
|
142
|
+
self._values[name] = value
|
|
143
|
+
|
|
144
|
+
def __getattr__(self, name):
|
|
145
|
+
try:
|
|
146
|
+
return self._values[name]
|
|
147
|
+
except KeyError as err:
|
|
148
|
+
raise AttributeError(f'Unknown Xsuite setting {name!r}.') from err
|
|
149
|
+
|
|
150
|
+
def __setattr__(self, name, value):
|
|
151
|
+
self._set(name, value)
|
|
152
|
+
|
|
153
|
+
@contextmanager
|
|
154
|
+
def override(self, **kwargs):
|
|
155
|
+
"""Temporarily override settings and restore them on exit."""
|
|
156
|
+
previous = {}
|
|
157
|
+
for name, value in kwargs.items():
|
|
158
|
+
if name not in self._definitions:
|
|
159
|
+
raise AttributeError(f'Unknown Xsuite setting {name!r}.')
|
|
160
|
+
previous[name] = getattr(self, name)
|
|
161
|
+
|
|
162
|
+
# Validate every value before changing any setting.
|
|
163
|
+
for name, value in kwargs.items():
|
|
164
|
+
definition = self._definitions[name]
|
|
165
|
+
setting_description = self._setting_description(name, definition)
|
|
166
|
+
value_type = definition['value_type']
|
|
167
|
+
if value_type is not None and not isinstance(value, value_type):
|
|
168
|
+
raise TypeError(
|
|
169
|
+
f'Invalid value {value!r} for {setting_description}; '
|
|
170
|
+
f'expected {self._type_name(value_type)}.')
|
|
171
|
+
choices = definition['choices']
|
|
172
|
+
if choices is not None and value not in choices:
|
|
173
|
+
expected = ', '.join(repr(choice) for choice in choices)
|
|
174
|
+
raise ValueError(
|
|
175
|
+
f'Invalid value {value!r} for {setting_description}; '
|
|
176
|
+
f'expected one of {expected}.')
|
|
177
|
+
|
|
178
|
+
try:
|
|
179
|
+
for name, value in kwargs.items():
|
|
180
|
+
self._set(name, value)
|
|
181
|
+
yield self
|
|
182
|
+
finally:
|
|
183
|
+
for name, value in previous.items():
|
|
184
|
+
self._set(name, value)
|
|
185
|
+
|
|
186
|
+
def __repr__(self):
|
|
187
|
+
values = ', '.join(
|
|
188
|
+
f'{name}={getattr(self, name)!r}' for name in self._values)
|
|
189
|
+
return f'Settings({values})'
|
|
190
|
+
|
|
191
|
+
def __dir__(self):
|
|
192
|
+
return sorted(set(super().__dir__()) | set(self._definitions))
|
|
193
|
+
|
|
194
|
+
@staticmethod
|
|
195
|
+
def _type_name(value_type):
|
|
196
|
+
if isinstance(value_type, tuple):
|
|
197
|
+
return ' or '.join(tt.__name__ for tt in value_type)
|
|
198
|
+
return value_type.__name__
|
|
199
|
+
|
|
200
|
+
@staticmethod
|
|
201
|
+
def _setting_description(name, definition):
|
|
202
|
+
description = f'Python setting xobjects.settings.{name}'
|
|
203
|
+
environment_variable = definition['environment_variable']
|
|
204
|
+
if environment_variable is not None:
|
|
205
|
+
description += (
|
|
206
|
+
f' or equivalently the environment variable '
|
|
207
|
+
f'{environment_variable}'
|
|
208
|
+
)
|
|
209
|
+
return description
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _parse_boolean(value):
|
|
213
|
+
normalized = value.strip().lower()
|
|
214
|
+
if normalized in ('1', 'true', 'yes', 'on'):
|
|
215
|
+
return True
|
|
216
|
+
if normalized in ('0', 'false', 'no', 'off'):
|
|
217
|
+
return False
|
|
218
|
+
raise ValueError(
|
|
219
|
+
f'Invalid boolean value {value!r}; expected one of 1, 0, true, '
|
|
220
|
+
'false, yes, no, on, or off.')
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _parse_choice(value):
|
|
224
|
+
return value.strip().lower()
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def _parse_optional_string(value):
|
|
228
|
+
value = value.strip()
|
|
229
|
+
return value if value else None
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
settings = Settings()
|
|
233
|
+
settings._register(
|
|
234
|
+
'print_mode',
|
|
235
|
+
default='print',
|
|
236
|
+
environment_variable='XSUITE_PRINT_MODE',
|
|
237
|
+
choices=('print', 'suppress'),
|
|
238
|
+
environment_parser=_parse_choice,
|
|
239
|
+
)
|
|
240
|
+
settings._register(
|
|
241
|
+
'progress_indicator',
|
|
242
|
+
default='tqdm',
|
|
243
|
+
environment_variable='XSUITE_PROGRESS_INDICATOR',
|
|
244
|
+
choices=('tqdm', 'text', 'suppress'),
|
|
245
|
+
environment_parser=_parse_choice,
|
|
246
|
+
)
|
|
247
|
+
settings._register(
|
|
248
|
+
'allow_kernel_compilation',
|
|
249
|
+
default=False,
|
|
250
|
+
environment_variable='XSUITE_ALLOW_KERNEL_COMPILATION',
|
|
251
|
+
choices=(False, True),
|
|
252
|
+
environment_parser=_parse_boolean,
|
|
253
|
+
value_type=bool,
|
|
254
|
+
)
|
|
255
|
+
settings._register(
|
|
256
|
+
'force_kernel_compilation',
|
|
257
|
+
default=False,
|
|
258
|
+
environment_variable='XSUITE_FORCE_KERNEL_COMPILATION',
|
|
259
|
+
choices=(False, True),
|
|
260
|
+
environment_parser=_parse_boolean,
|
|
261
|
+
value_type=bool,
|
|
262
|
+
)
|
|
263
|
+
settings._register(
|
|
264
|
+
'show_kernel_diagnostics',
|
|
265
|
+
default=False,
|
|
266
|
+
environment_variable='XSUITE_SHOW_KERNEL_DIAGNOSTICS',
|
|
267
|
+
choices=(False, True),
|
|
268
|
+
environment_parser=_parse_boolean,
|
|
269
|
+
value_type=bool,
|
|
270
|
+
)
|
|
271
|
+
settings._register(
|
|
272
|
+
'cffi_forbid_compile',
|
|
273
|
+
default=False,
|
|
274
|
+
environment_variable='XSUITE_CFFI_FORBID_COMPILE',
|
|
275
|
+
choices=(False, True),
|
|
276
|
+
environment_parser=_parse_boolean,
|
|
277
|
+
value_type=bool,
|
|
278
|
+
)
|
|
279
|
+
settings._register(
|
|
280
|
+
'cffi_keep_build_files',
|
|
281
|
+
default=False,
|
|
282
|
+
environment_variable='XSUITE_CFFI_KEEP_BUILD_FILES',
|
|
283
|
+
choices=(False, True),
|
|
284
|
+
environment_parser=_parse_boolean,
|
|
285
|
+
value_type=bool,
|
|
286
|
+
)
|
|
287
|
+
settings._register(
|
|
288
|
+
'cuda_backend',
|
|
289
|
+
default='nvrtc',
|
|
290
|
+
environment_variable='XSUITE_CUDA_BACKEND',
|
|
291
|
+
choices=('nvrtc', 'clang'),
|
|
292
|
+
environment_parser=_parse_choice,
|
|
293
|
+
)
|
|
294
|
+
settings._register(
|
|
295
|
+
'cuda_fast_compile',
|
|
296
|
+
default=True,
|
|
297
|
+
environment_variable='XSUITE_CUDA_FAST_COMPILE',
|
|
298
|
+
choices=(False, True),
|
|
299
|
+
environment_parser=_parse_boolean,
|
|
300
|
+
value_type=bool,
|
|
301
|
+
)
|
|
302
|
+
settings._register(
|
|
303
|
+
'cuda_compiler',
|
|
304
|
+
default=None,
|
|
305
|
+
environment_variable='XSUITE_CUDA_COMPILER',
|
|
306
|
+
environment_parser=_parse_optional_string,
|
|
307
|
+
value_type=(str, type(None)),
|
|
308
|
+
)
|
|
@@ -59,7 +59,7 @@ from .typeutils import (
|
|
|
59
59
|
default_conf,
|
|
60
60
|
)
|
|
61
61
|
|
|
62
|
-
from .
|
|
62
|
+
from .settings import settings
|
|
63
63
|
from .scalar import Int64
|
|
64
64
|
from .array import Array
|
|
65
65
|
from .context import Source, Arg, Kernel
|
|
@@ -518,14 +518,13 @@ class Struct(metaclass=MetaStruct):
|
|
|
518
518
|
extra_classes=(),
|
|
519
519
|
extra_compile_args=(),
|
|
520
520
|
):
|
|
521
|
-
if context.allow_prebuilt_kernels
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
try:
|
|
521
|
+
if (context.allow_prebuilt_kernels
|
|
522
|
+
and not settings.force_kernel_compilation):
|
|
523
|
+
with settings.override(print_mode="suppress"):
|
|
525
524
|
try:
|
|
526
525
|
from xsuite import (
|
|
527
526
|
get_suitable_kernel,
|
|
528
|
-
|
|
527
|
+
PREBUILT_KERNELS_LOCATION,
|
|
529
528
|
)
|
|
530
529
|
|
|
531
530
|
kernel_info = get_suitable_kernel(
|
|
@@ -546,14 +545,12 @@ class Struct(metaclass=MetaStruct):
|
|
|
546
545
|
"Xsuite is required to load prebuilt kernels but could "
|
|
547
546
|
"not be imported. Please install it with "
|
|
548
547
|
f"`pip install xsuite`. "
|
|
549
|
-
f"{context_cpu.
|
|
548
|
+
f"{context_cpu.kernel_compilation_help_message()}"
|
|
550
549
|
) from err
|
|
551
|
-
finally:
|
|
552
|
-
Print.suppress = _print_state
|
|
553
550
|
if kernel_info:
|
|
554
551
|
kernels = context.kernels_from_file(
|
|
555
552
|
module_name=kernel_info["module_name"],
|
|
556
|
-
containing_dir=
|
|
553
|
+
containing_dir=PREBUILT_KERNELS_LOCATION,
|
|
557
554
|
kernel_descriptions=cls._kernels,
|
|
558
555
|
)
|
|
559
556
|
context.kernels.update(kernels)
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
from functools import wraps
|
|
7
7
|
from typing import Callable, Iterable, Union
|
|
8
|
-
import os
|
|
9
8
|
|
|
10
9
|
import pytest
|
|
11
10
|
|
|
12
11
|
from .context import get_context_from_string, get_test_contexts
|
|
12
|
+
from .settings import settings
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def _for_all_test_contexts_excluding(
|
|
@@ -108,13 +108,13 @@ def fix_random_seed(seed: int):
|
|
|
108
108
|
return decorator
|
|
109
109
|
|
|
110
110
|
|
|
111
|
-
def
|
|
111
|
+
def allow_kernel_compilation(
|
|
112
112
|
test_function=None, *, skip_when_forbid_compile=True
|
|
113
113
|
):
|
|
114
114
|
"""Allow JIT compilation for tests that intentionally compile kernels.
|
|
115
115
|
|
|
116
116
|
By default, the wrapped test is skipped when compilation is forbidden by
|
|
117
|
-
``
|
|
117
|
+
``XSUITE_CFFI_FORBID_COMPILE``. Use ``skip_when_forbid_compile=False`` when
|
|
118
118
|
the test has more specific ``skip_if_forbid_compile()`` guards inside the
|
|
119
119
|
test.
|
|
120
120
|
"""
|
|
@@ -124,15 +124,8 @@ def allow_no_prebuilt_kernels(
|
|
|
124
124
|
def wrapper(*args, **kwargs):
|
|
125
125
|
if skip_when_forbid_compile:
|
|
126
126
|
skip_if_forbid_compile()
|
|
127
|
-
|
|
128
|
-
os.environ["XSUITE_ALLOW_NO_PREBUILT_KERNELS"] = "1"
|
|
129
|
-
try:
|
|
127
|
+
with settings.override(allow_kernel_compilation=True):
|
|
130
128
|
return test_function(*args, **kwargs)
|
|
131
|
-
finally:
|
|
132
|
-
if old_value is None:
|
|
133
|
-
del os.environ["XSUITE_ALLOW_NO_PREBUILT_KERNELS"]
|
|
134
|
-
else:
|
|
135
|
-
os.environ["XSUITE_ALLOW_NO_PREBUILT_KERNELS"] = old_value
|
|
136
129
|
|
|
137
130
|
return wrapper
|
|
138
131
|
|
|
@@ -142,8 +135,9 @@ def allow_no_prebuilt_kernels(
|
|
|
142
135
|
|
|
143
136
|
|
|
144
137
|
def skip_if_forbid_compile():
|
|
145
|
-
if
|
|
138
|
+
if settings.cffi_forbid_compile:
|
|
146
139
|
pytest.skip(
|
|
147
|
-
"
|
|
148
|
-
"
|
|
140
|
+
"CFFI compilation is forbidden by "
|
|
141
|
+
"xobjects.settings.cffi_forbid_compile or equivalently the "
|
|
142
|
+
"environment variable XSUITE_CFFI_FORBID_COMPILE."
|
|
149
143
|
)
|
|
@@ -12,6 +12,7 @@ tests/test_capi.py
|
|
|
12
12
|
tests/test_chunk.py
|
|
13
13
|
tests/test_common.py
|
|
14
14
|
tests/test_context_opencl.py
|
|
15
|
+
tests/test_general.py
|
|
15
16
|
tests/test_hybrid_class.py
|
|
16
17
|
tests/test_kernel.py
|
|
17
18
|
tests/test_linked_array.py
|
|
@@ -39,6 +40,7 @@ xobjects/hybrid_class.py
|
|
|
39
40
|
xobjects/linkedarray.py
|
|
40
41
|
xobjects/ref.py
|
|
41
42
|
xobjects/scalar.py
|
|
43
|
+
xobjects/settings.py
|
|
42
44
|
xobjects/specialize_source.py
|
|
43
45
|
xobjects/string.py
|
|
44
46
|
xobjects/struct.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.6.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|