dendra 0.27.2__py3-none-any.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.
- dendra/__init__.py +257 -0
- dendra/__main__.py +5 -0
- dendra/_bootstrap.py +217 -0
- dendra/cli.py +51 -0
- dendra/const.py +34 -0
- dendra/data/__init__.py +5 -0
- dendra/data/h5.py +145 -0
- dendra/diagnostics.py +367 -0
- dendra/func/__init__.py +53 -0
- dendra/func/_binding.py +116 -0
- dendra/func/_callbacks.py +1326 -0
- dendra/func/_compiled.py +394 -0
- dendra/func/_execution.py +94 -0
- dendra/func/_lowered.py +163 -0
- dendra/func/_population.py +11505 -0
- dendra/func/_runners.py +1257 -0
- dendra/func/_scan.py +185 -0
- dendra/func/_scan_autograd.py +57 -0
- dendra/func/_scan_compat.py +233 -0
- dendra/func/_stimuli.py +1574 -0
- dendra/func/_types.py +227 -0
- dendra/helpers.py +849 -0
- dendra/models/__init__.py +31 -0
- dendra/models/_class_declarations.py +173 -0
- dendra/models/_morphology_scene.py +536 -0
- dendra/models/analysis/__init__.py +139 -0
- dendra/models/analysis/activation_witness.py +211 -0
- dendra/models/analysis/batched_threshold_protocol.py +373 -0
- dendra/models/analysis/branch_conditioned_metrics.py +738 -0
- dendra/models/analysis/callback_horizon.py +134 -0
- dendra/models/analysis/callback_margin.py +262 -0
- dendra/models/analysis/descriptors.py +6532 -0
- dendra/models/analysis/event_margin_training.py +283 -0
- dendra/models/analysis/firing_rate_trajectory.py +179 -0
- dendra/models/analysis/hard_threshold_gradient.py +252 -0
- dendra/models/analysis/hard_transition_table.py +169 -0
- dendra/models/analysis/hard_transition_validation.py +337 -0
- dendra/models/analysis/spike_timing.py +300 -0
- dendra/models/analysis/threshold_event_root.py +348 -0
- dendra/models/analysis/threshold_noise_metrics.py +182 -0
- dendra/models/analysis/threshold_protocol.py +182 -0
- dendra/models/analysis/threshold_trace_probe.py +429 -0
- dendra/models/analysis/threshold_trace_tangent.py +549 -0
- dendra/models/analysis/threshold_transition_jets.py +103 -0
- dendra/models/analysis/threshold_transition_metrics.py +162 -0
- dendra/models/backend.py +78 -0
- dendra/models/callbacks.py +1947 -0
- dendra/models/core.py +10320 -0
- dendra/models/distributions.py +218 -0
- dendra/models/extcell.py +311 -0
- dendra/models/fields/__init__.py +64 -0
- dendra/models/fields/analytic.py +390 -0
- dendra/models/fields/line.py +199 -0
- dendra/models/fields/precomputed.py +1143 -0
- dendra/models/fields/quasipotentials.py +158 -0
- dendra/models/fields/spherical_cartesian.py +41 -0
- dendra/models/graph.py +163 -0
- dendra/models/heterogeneous/__init__.py +5 -0
- dendra/models/heterogeneous/compartments.py +141 -0
- dendra/models/initialization.py +247 -0
- dendra/models/instruments/__init__.py +3 -0
- dendra/models/instruments/thresholder.py +1154 -0
- dendra/models/integrators/__init__.py +86 -0
- dendra/models/integrators/cable.py +108 -0
- dendra/models/integrators/core.py +905 -0
- dendra/models/integrators/explicit.py +811 -0
- dendra/models/integrators/imex.py +369 -0
- dendra/models/integrators/implicit.py +1038 -0
- dendra/models/integrators/tree.py +1841 -0
- dendra/models/integrators/tree_bt.py +600 -0
- dendra/models/integrators/tridiag/__init__.py +3 -0
- dendra/models/integrators/tridiag/block.py +219 -0
- dendra/models/integrators/tridiag/pcr.py +203 -0
- dendra/models/integrators/triton/__init__.py +28 -0
- dendra/models/integrators/triton/_contracts.py +351 -0
- dendra/models/integrators/triton/bt_kernel.py +298 -0
- dendra/models/integrators/triton/bt_spd_kernel.py +733 -0
- dendra/models/integrators/triton/dhs_kernel.py +654 -0
- dendra/models/integrators/triton/dhs_kernel_bt.py +479 -0
- dendra/models/integrators/triton/dhs_kernel_multi.py +889 -0
- dendra/models/integrators/triton/pcr_kernel_thomas.py +226 -0
- dendra/models/integrators/triton/t_kernel_thomas.py +232 -0
- dendra/models/intrinsic.py +139 -0
- dendra/models/io.py +1238 -0
- dendra/models/mechanisms/__init__.py +46 -0
- dendra/models/mechanisms/_bufferimplicit.py +420 -0
- dendra/models/mechanisms/_cnexp.py +143 -0
- dendra/models/mechanisms/_derivimplicit.py +831 -0
- dendra/models/mechanisms/_euler_heun.py +199 -0
- dendra/models/mechanisms/_euler_maruyama.py +152 -0
- dendra/models/mechanisms/_handler.py +2946 -0
- dendra/models/mechanisms/_ions.py +316 -0
- dendra/models/mechanisms/_kinetic.py +365 -0
- dendra/models/mechanisms/_linearimplicit.py +595 -0
- dendra/models/mechanisms/_material_process.py +2545 -0
- dendra/models/mechanisms/_materials.py +407 -0
- dendra/models/mechanisms/_mechanism.py +4340 -0
- dendra/models/mechanisms/_numerical.py +431 -0
- dendra/models/mechanisms/_rosenbrock.py +456 -0
- dendra/models/mechanisms/_solve_utils.py +284 -0
- dendra/models/mechanisms/_solvers.py +129 -0
- dendra/models/mechanisms/_spatial.py +1799 -0
- dendra/models/mechanisms/_state.py +2410 -0
- dendra/models/mechanisms/_support.py +760 -0
- dendra/models/mechanisms/_support_registry.py +466 -0
- dendra/models/mechanisms/_symbolic.py +246 -0
- dendra/models/mechanisms/compilers/__init__.py +0 -0
- dendra/models/mechanisms/compilers/ast.py +363 -0
- dendra/models/mechanisms/compilers/source.py +121 -0
- dendra/models/mechanisms/ode.py +515 -0
- dendra/models/mechanisms/ops.py +133 -0
- dendra/models/mechanisms/validate.py +6 -0
- dendra/models/mod/ALPHASYNAPSE.py +63 -0
- dendra/models/mod/ALPHASYNAPSE_D.py +77 -0
- dendra/models/mod/APCOUNT.py +42 -0
- dendra/models/mod/APCOUNT_D.py +132 -0
- dendra/models/mod/EXP2SYN.py +138 -0
- dendra/models/mod/EXPSYN.py +60 -0
- dendra/models/mod/FIRE.py +23 -0
- dendra/models/mod/FIRE_D.py +84 -0
- dendra/models/mod/FIRE_R.py +51 -0
- dendra/models/mod/FIRE_R_D.py +124 -0
- dendra/models/mod/GRADED_SYNAPSE.py +414 -0
- dendra/models/mod/HH.py +96 -0
- dendra/models/mod/PAS.py +25 -0
- dendra/models/mod/SPIKEDETECT.py +160 -0
- dendra/models/mod/__init__.py +117 -0
- dendra/models/modular.py +232 -0
- dendra/models/morphology.py +3539 -0
- dendra/models/morphology_io.py +606 -0
- dendra/models/morphology_visualization.py +3244 -0
- dendra/models/multi.py +1049 -0
- dendra/models/networks/__init__.py +3 -0
- dendra/models/networks/net.py +5125 -0
- dendra/models/networks/netcon.py +6063 -0
- dendra/models/networks/netcon_bitpack_contracts.py +160 -0
- dendra/models/networks/netcon_bitpack_kernel.cpp +149 -0
- dendra/models/networks/netcon_bitpack_kernel.cu +228 -0
- dendra/models/networks/netcon_bitpack_ops.py +712 -0
- dendra/models/networks/netcon_bitpack_ops_triton.py +285 -0
- dendra/models/networks/netstim.py +1603 -0
- dendra/models/networks/spiking.py +96 -0
- dendra/models/networks/utils.py +36 -0
- dendra/models/parametric.py +4182 -0
- dendra/models/random_parameters.py +423 -0
- dendra/models/rng.py +429 -0
- dendra/models/slice.py +2445 -0
- dendra/models/stim/__init__.py +4 -0
- dendra/models/stim/extra.py +200 -0
- dendra/models/stim/intra.py +278 -0
- dendra/models/stim/waveform/__init__.py +25 -0
- dendra/models/stim/waveform/_gates.py +65 -0
- dendra/models/stim/waveform/core.py +708 -0
- dendra/models/stim/waveform/implementations.py +860 -0
- dendra/models/tree.py +1269 -0
- dendra/models/utils.py +134 -0
- dendra/models/visualization.py +1791 -0
- dendra/opt/__init__.py +5 -0
- dendra/opt/utils.py +103 -0
- dendra/stepping.py +158 -0
- dendra/units.py +151 -0
- dendra/utils/__init__.py +21 -0
- dendra/utils/dynamic_compilation.py +82 -0
- dendra/utils/gpu.py +49 -0
- dendra/utils/interpolation.py +4418 -0
- dendra/utils/neuron.py +151 -0
- dendra/utils/tensor_ops.py +287 -0
- dendra-0.27.2.dist-info/METADATA +161 -0
- dendra-0.27.2.dist-info/RECORD +173 -0
- dendra-0.27.2.dist-info/WHEEL +5 -0
- dendra-0.27.2.dist-info/entry_points.txt +2 -0
- dendra-0.27.2.dist-info/licenses/LICENSE.md +39 -0
- dendra-0.27.2.dist-info/top_level.txt +1 -0
dendra/__init__.py
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"""Dendra: A PyTorch-based framework for simulating and modeling neural dynamics."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
__version__ = "0.27.2"
|
|
6
|
+
|
|
7
|
+
os.environ.setdefault("OMP_DYNAMIC", "FALSE")
|
|
8
|
+
os.environ.setdefault("MKL_DYNAMIC", "FALSE")
|
|
9
|
+
os.environ["OMP_PROC_BIND"] = "true"
|
|
10
|
+
os.environ["OMP_PLACES"] = "cores"
|
|
11
|
+
|
|
12
|
+
from ._bootstrap import (
|
|
13
|
+
_should_cache_cpu_isa_for_dendra,
|
|
14
|
+
_should_configure_torchinductor_cache_on_import,
|
|
15
|
+
configure_torchinductor_cache_for_dendra,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
_torchinductor_cache_opt_in = _should_configure_torchinductor_cache_on_import()
|
|
19
|
+
if _torchinductor_cache_opt_in:
|
|
20
|
+
configure_torchinductor_cache_for_dendra()
|
|
21
|
+
|
|
22
|
+
import pickle
|
|
23
|
+
import time
|
|
24
|
+
import warnings
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
import torch
|
|
28
|
+
|
|
29
|
+
import dendra.func as func
|
|
30
|
+
import dendra.models.callbacks as callbacks
|
|
31
|
+
import dendra.models.mod as mod
|
|
32
|
+
|
|
33
|
+
from .const import FARADAY, PI, TAU, E, R
|
|
34
|
+
from .diagnostics import doctor
|
|
35
|
+
from .helpers import (
|
|
36
|
+
COMPILE_OPTIONS,
|
|
37
|
+
DEVICE,
|
|
38
|
+
DTYPE,
|
|
39
|
+
NATIVE_EXTENSION_POLICY,
|
|
40
|
+
PRESERVE_MECHANISM_POPULATION_AXIS,
|
|
41
|
+
RUNTIME_CONTRACT_VALIDATION,
|
|
42
|
+
TF32,
|
|
43
|
+
allow_tf32,
|
|
44
|
+
ctx,
|
|
45
|
+
current_compile_options,
|
|
46
|
+
current_device,
|
|
47
|
+
current_dtype,
|
|
48
|
+
current_native_extension_policy,
|
|
49
|
+
current_preserve_mechanism_population_axis,
|
|
50
|
+
current_runtime_contract_validation,
|
|
51
|
+
normalize_native_extension_policy,
|
|
52
|
+
normalize_preserve_mechanism_population_axis,
|
|
53
|
+
normalize_runtime_contract_validation,
|
|
54
|
+
set_compile_options,
|
|
55
|
+
set_jit_enabled,
|
|
56
|
+
set_jit_in_network_enabled,
|
|
57
|
+
set_jit_network_ops_enabled,
|
|
58
|
+
set_jit_network_solves_enabled,
|
|
59
|
+
)
|
|
60
|
+
from .models import (
|
|
61
|
+
Axon,
|
|
62
|
+
Cable,
|
|
63
|
+
CompartmentGeometry,
|
|
64
|
+
CompartmentGraph,
|
|
65
|
+
CompartmentMetadata,
|
|
66
|
+
CompartmentTopology,
|
|
67
|
+
DistributionSpec,
|
|
68
|
+
ExtCellAxon,
|
|
69
|
+
ExtCellTree,
|
|
70
|
+
Morphology,
|
|
71
|
+
Myelinated,
|
|
72
|
+
NetStim,
|
|
73
|
+
Network,
|
|
74
|
+
Population,
|
|
75
|
+
RandomParameterSpec,
|
|
76
|
+
RuntimeNoiseSpec,
|
|
77
|
+
Section,
|
|
78
|
+
SectionLocation,
|
|
79
|
+
SingleCompartment,
|
|
80
|
+
SynapseSlots,
|
|
81
|
+
Tree,
|
|
82
|
+
Unmyelinated,
|
|
83
|
+
available_random_distributions,
|
|
84
|
+
concat_models,
|
|
85
|
+
concat_slices,
|
|
86
|
+
connect_morphologies,
|
|
87
|
+
get_random_distribution,
|
|
88
|
+
insert_intrinsic_activity,
|
|
89
|
+
make_random_parameter_spec,
|
|
90
|
+
make_runtime_noise_spec,
|
|
91
|
+
passive_end_nodes_,
|
|
92
|
+
register_random_distribution,
|
|
93
|
+
remove_intrinsic_activity,
|
|
94
|
+
sample_random_parameter,
|
|
95
|
+
sample_runtime_noise,
|
|
96
|
+
)
|
|
97
|
+
from .models.fields import *
|
|
98
|
+
from .models.integrators import (
|
|
99
|
+
bwd_euler_bt,
|
|
100
|
+
bwd_euler_sc,
|
|
101
|
+
bwd_euler_ub,
|
|
102
|
+
df,
|
|
103
|
+
dfh,
|
|
104
|
+
dhs,
|
|
105
|
+
dufort_frankel,
|
|
106
|
+
dufort_frankel_homogeneous,
|
|
107
|
+
euler,
|
|
108
|
+
eulerv1,
|
|
109
|
+
rk1,
|
|
110
|
+
rk2,
|
|
111
|
+
rk4,
|
|
112
|
+
scnv,
|
|
113
|
+
)
|
|
114
|
+
from .models.mod import load_mechanisms
|
|
115
|
+
from .models.stim.waveform import *
|
|
116
|
+
from .stepping import step, step_network, step_population
|
|
117
|
+
|
|
118
|
+
__all__ = [
|
|
119
|
+
"PI",
|
|
120
|
+
"E",
|
|
121
|
+
"TAU",
|
|
122
|
+
"R",
|
|
123
|
+
"FARADAY",
|
|
124
|
+
"ctx",
|
|
125
|
+
"doctor",
|
|
126
|
+
"step",
|
|
127
|
+
"step_population",
|
|
128
|
+
"step_network",
|
|
129
|
+
"DEVICE",
|
|
130
|
+
"DTYPE",
|
|
131
|
+
"NATIVE_EXTENSION_POLICY",
|
|
132
|
+
"PRESERVE_MECHANISM_POPULATION_AXIS",
|
|
133
|
+
"RUNTIME_CONTRACT_VALIDATION",
|
|
134
|
+
"COMPILE_OPTIONS",
|
|
135
|
+
"current_compile_options",
|
|
136
|
+
"current_device",
|
|
137
|
+
"current_dtype",
|
|
138
|
+
"current_native_extension_policy",
|
|
139
|
+
"current_preserve_mechanism_population_axis",
|
|
140
|
+
"current_runtime_contract_validation",
|
|
141
|
+
"normalize_runtime_contract_validation",
|
|
142
|
+
"normalize_native_extension_policy",
|
|
143
|
+
"normalize_preserve_mechanism_population_axis",
|
|
144
|
+
"set_compile_options",
|
|
145
|
+
"set_jit_enabled",
|
|
146
|
+
"set_jit_network_solves_enabled",
|
|
147
|
+
"set_jit_network_ops_enabled",
|
|
148
|
+
"set_jit_in_network_enabled",
|
|
149
|
+
"callbacks",
|
|
150
|
+
"func",
|
|
151
|
+
"mod",
|
|
152
|
+
"load_mechanisms",
|
|
153
|
+
"DistributionSpec",
|
|
154
|
+
"RandomParameterSpec",
|
|
155
|
+
"RuntimeNoiseSpec",
|
|
156
|
+
"available_random_distributions",
|
|
157
|
+
"get_random_distribution",
|
|
158
|
+
"register_random_distribution",
|
|
159
|
+
"make_random_parameter_spec",
|
|
160
|
+
"make_runtime_noise_spec",
|
|
161
|
+
"sample_random_parameter",
|
|
162
|
+
"sample_runtime_noise",
|
|
163
|
+
"insert_intrinsic_activity",
|
|
164
|
+
"remove_intrinsic_activity",
|
|
165
|
+
"passive_end_nodes_",
|
|
166
|
+
"Population",
|
|
167
|
+
"Morphology",
|
|
168
|
+
"Section",
|
|
169
|
+
"SectionLocation",
|
|
170
|
+
"CompartmentTopology",
|
|
171
|
+
"CompartmentGeometry",
|
|
172
|
+
"CompartmentMetadata",
|
|
173
|
+
"CompartmentGraph",
|
|
174
|
+
"SingleCompartment",
|
|
175
|
+
"Cable",
|
|
176
|
+
"Axon",
|
|
177
|
+
"Unmyelinated",
|
|
178
|
+
"Myelinated",
|
|
179
|
+
"Tree",
|
|
180
|
+
"ExtCellAxon",
|
|
181
|
+
"ExtCellTree",
|
|
182
|
+
"NetStim",
|
|
183
|
+
"Network",
|
|
184
|
+
"SynapseSlots",
|
|
185
|
+
"concat_models",
|
|
186
|
+
"concat_slices",
|
|
187
|
+
"connect_morphologies",
|
|
188
|
+
"anisotropic_point",
|
|
189
|
+
"isotropic_point",
|
|
190
|
+
"parametric_efield",
|
|
191
|
+
"PreComputedInterpolate1D",
|
|
192
|
+
"precomputed_interpolate_1d",
|
|
193
|
+
"EfieldInterpolate3DRect",
|
|
194
|
+
"efield_interpolate_3d_rect",
|
|
195
|
+
"PreComputedInterpolate3DRect",
|
|
196
|
+
"precomputed_interpolate_3d_rect",
|
|
197
|
+
"PreComputedInterpolate3DScattered",
|
|
198
|
+
"precomputed_interpolate_3d_scattered",
|
|
199
|
+
"EfieldInterpolate3DScattered",
|
|
200
|
+
"efield_interpolate_3d_scattered",
|
|
201
|
+
"euler",
|
|
202
|
+
"eulerv1",
|
|
203
|
+
"rk1",
|
|
204
|
+
"rk2",
|
|
205
|
+
"rk4",
|
|
206
|
+
"dufort_frankel",
|
|
207
|
+
"dufort_frankel_homogeneous",
|
|
208
|
+
"bwd_euler_sc",
|
|
209
|
+
"bwd_euler_ub",
|
|
210
|
+
"bwd_euler_bt",
|
|
211
|
+
"dhs",
|
|
212
|
+
"df",
|
|
213
|
+
"dfh",
|
|
214
|
+
"scnv",
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _cache_cpu_isa_list():
|
|
219
|
+
"""
|
|
220
|
+
Checks for a cached CPU ISA string. If not found, runs the slow
|
|
221
|
+
detection and caches the result for future runs.
|
|
222
|
+
"""
|
|
223
|
+
# Use a standard cache location.
|
|
224
|
+
cache_dir = Path.home() / ".cache" / "dendra"
|
|
225
|
+
cache_file = cache_dir / f"cpu_isa_list_{torch.__version__}"
|
|
226
|
+
|
|
227
|
+
def get_valid_vec_isa_list():
|
|
228
|
+
with open(cache_file, "rb") as f:
|
|
229
|
+
return pickle.load(f)
|
|
230
|
+
|
|
231
|
+
# --- Cache Hit ---
|
|
232
|
+
if cache_file.exists():
|
|
233
|
+
# Check if the PyTorch version matches the one used to create the cache.
|
|
234
|
+
torch._inductor.cpu_vec_isa.valid_vec_isa_list = get_valid_vec_isa_list
|
|
235
|
+
return
|
|
236
|
+
|
|
237
|
+
# --- Cache Miss or Stale Cache ---
|
|
238
|
+
print("Dendra: Performing one-time CPU capability check. This may take a minute...")
|
|
239
|
+
try:
|
|
240
|
+
os.makedirs(cache_dir, exist_ok=True)
|
|
241
|
+
start = time.time()
|
|
242
|
+
valid_vec_isa_list = torch._inductor.cpu_vec_isa.valid_vec_isa_list()
|
|
243
|
+
print(f"Dendra: CPU capability check took {(time.time() - start):.3f}s.")
|
|
244
|
+
with open(cache_file, "wb") as f:
|
|
245
|
+
pickle.dump(valid_vec_isa_list, f)
|
|
246
|
+
except Exception as e:
|
|
247
|
+
warnings.warn(
|
|
248
|
+
f"Dendra: CPU capability check failed: {e}. Falling back to default behavior."
|
|
249
|
+
)
|
|
250
|
+
return
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
if _torchinductor_cache_opt_in and _should_cache_cpu_isa_for_dendra():
|
|
254
|
+
_cache_cpu_isa_list()
|
|
255
|
+
|
|
256
|
+
# setup environment
|
|
257
|
+
allow_tf32(bool(TF32))
|
dendra/__main__.py
ADDED
dendra/_bootstrap.py
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# dendra/_bootstrap.py
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import atexit
|
|
6
|
+
import getpass
|
|
7
|
+
import os
|
|
8
|
+
import shutil
|
|
9
|
+
import sys
|
|
10
|
+
import tempfile
|
|
11
|
+
import uuid
|
|
12
|
+
import warnings
|
|
13
|
+
from contextlib import contextmanager
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
_DISABLED_INDUCTOR_CACHE_POLICIES = {
|
|
17
|
+
"0",
|
|
18
|
+
"false",
|
|
19
|
+
"none",
|
|
20
|
+
"off",
|
|
21
|
+
"disable",
|
|
22
|
+
"disabled",
|
|
23
|
+
}
|
|
24
|
+
_PROCESS_INDUCTOR_CACHE_POLICIES = {
|
|
25
|
+
"process",
|
|
26
|
+
"isolated",
|
|
27
|
+
"per_process",
|
|
28
|
+
"per-process",
|
|
29
|
+
}
|
|
30
|
+
_SHARED_INDUCTOR_CACHE_POLICIES = {"shared", "global"}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@contextmanager
|
|
34
|
+
def torch_compiler_warning_context():
|
|
35
|
+
"""Filter only known PyTorch compiler deprecations in strict-warning runs."""
|
|
36
|
+
with warnings.catch_warnings():
|
|
37
|
+
warnings.filterwarnings(
|
|
38
|
+
"ignore",
|
|
39
|
+
message=r".*torch\.jit\.script_method.*deprecated.*",
|
|
40
|
+
category=DeprecationWarning,
|
|
41
|
+
module=r"torch\.jit\._script",
|
|
42
|
+
)
|
|
43
|
+
warnings.filterwarnings(
|
|
44
|
+
"ignore",
|
|
45
|
+
message=r".*torch\.jit\.script.*deprecated.*",
|
|
46
|
+
category=DeprecationWarning,
|
|
47
|
+
module=r"torch\.jit\._script",
|
|
48
|
+
)
|
|
49
|
+
warnings.filterwarnings(
|
|
50
|
+
"ignore",
|
|
51
|
+
message=(
|
|
52
|
+
r".*The \.grad attribute of a Tensor that is not a leaf Tensor "
|
|
53
|
+
r"is being accessed.*"
|
|
54
|
+
),
|
|
55
|
+
category=UserWarning,
|
|
56
|
+
)
|
|
57
|
+
warnings.filterwarnings(
|
|
58
|
+
"ignore",
|
|
59
|
+
message=(
|
|
60
|
+
r".*torch\.autograd\.function\.Function.*should not be "
|
|
61
|
+
r"instantiated\..*Methods on autograd functions.*"
|
|
62
|
+
),
|
|
63
|
+
category=DeprecationWarning,
|
|
64
|
+
)
|
|
65
|
+
yield
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def reset_torch_compiler(*, prefer_public: bool = True) -> None:
|
|
69
|
+
"""Reset Torch compiler state without leaking PyTorch-internal warnings.
|
|
70
|
+
|
|
71
|
+
PyTorch 2.13 can emit deprecations for ``torch.jit.script_method`` while
|
|
72
|
+
lazily initializing Inductor and for internal ``autograd.Function``
|
|
73
|
+
handling while tracing custom functions. Dendra still treats every other
|
|
74
|
+
warning as actionable; only those upstream deprecations are filtered around
|
|
75
|
+
compiler operations that trigger them.
|
|
76
|
+
"""
|
|
77
|
+
import torch
|
|
78
|
+
|
|
79
|
+
with torch_compiler_warning_context():
|
|
80
|
+
if not prefer_public and hasattr(torch, "_dynamo"):
|
|
81
|
+
torch._dynamo.reset()
|
|
82
|
+
elif hasattr(torch, "compiler") and hasattr(torch.compiler, "reset"):
|
|
83
|
+
torch.compiler.reset()
|
|
84
|
+
elif hasattr(torch, "_dynamo") and hasattr(torch._dynamo, "reset"):
|
|
85
|
+
torch._dynamo.reset()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _truthy(x: str | None) -> bool:
|
|
89
|
+
return str(x).lower() in {"1", "true", "yes", "on"}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _should_configure_torchinductor_cache_on_import() -> bool:
|
|
93
|
+
"""Return whether importing Dendra should configure TorchInductor's cache."""
|
|
94
|
+
return _truthy(os.environ.get("DENDRA_CONFIGURE_TORCHINDUCTOR_CACHE", "0"))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _should_cache_cpu_isa_for_dendra() -> bool:
|
|
98
|
+
"""Return whether the selected policy enables Dendra's CPU ISA cache."""
|
|
99
|
+
policy = os.environ.get("DENDRA_INDUCTOR_CACHE_POLICY", "process").lower()
|
|
100
|
+
return policy in (
|
|
101
|
+
_PROCESS_INDUCTOR_CACHE_POLICIES | _SHARED_INDUCTOR_CACHE_POLICIES
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _get_notebook_or_process_id() -> str:
|
|
106
|
+
"""
|
|
107
|
+
Stable-enough process identifier for interactive notebooks and scripts.
|
|
108
|
+
|
|
109
|
+
We include PID to avoid cross-process cache sharing.
|
|
110
|
+
UUID avoids stale collisions if a PID is reused.
|
|
111
|
+
"""
|
|
112
|
+
user = "unknown"
|
|
113
|
+
try:
|
|
114
|
+
user = getpass.getuser()
|
|
115
|
+
except Exception:
|
|
116
|
+
pass
|
|
117
|
+
|
|
118
|
+
return f"{user}_{os.getpid()}_{uuid.uuid4().hex[:8]}"
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def configure_torchinductor_cache_for_dendra() -> None:
|
|
122
|
+
"""
|
|
123
|
+
Configure TorchInductor cache behavior before importing torch.
|
|
124
|
+
|
|
125
|
+
Environment variables
|
|
126
|
+
---------------------
|
|
127
|
+
DENDRA_CONFIGURE_TORCHINDUCTOR_CACHE:
|
|
128
|
+
"1" opts ``import dendra`` into Dendra-managed TorchInductor cache
|
|
129
|
+
behavior, including this function and the CPU ISA cache. Default: "0".
|
|
130
|
+
The flag does not affect explicit calls to this function.
|
|
131
|
+
|
|
132
|
+
DENDRA_INDUCTOR_CACHE_POLICY:
|
|
133
|
+
"process" -> per-process cache directory, safest for notebooks
|
|
134
|
+
"shared" -> leave TORCHINDUCTOR_CACHE_DIR alone unless user set it
|
|
135
|
+
"off" -> do nothing
|
|
136
|
+
|
|
137
|
+
DENDRA_INDUCTOR_CACHE_ROOT:
|
|
138
|
+
Parent directory for Dendra-owned process caches.
|
|
139
|
+
Default: tempfile.gettempdir()/dendra_torchinductor
|
|
140
|
+
|
|
141
|
+
DENDRA_INDUCTOR_DISABLE_PCH:
|
|
142
|
+
"1" disables C++ precompiled header caching where supported.
|
|
143
|
+
|
|
144
|
+
DENDRA_INDUCTOR_COMPILE_THREADS:
|
|
145
|
+
Sets TORCHINDUCTOR_COMPILE_THREADS. Default "1" in process mode.
|
|
146
|
+
|
|
147
|
+
DENDRA_INDUCTOR_CLEANUP:
|
|
148
|
+
"1" removes the Dendra-owned per-process cache at interpreter exit.
|
|
149
|
+
"""
|
|
150
|
+
policy = os.environ.get("DENDRA_INDUCTOR_CACHE_POLICY", "process").lower()
|
|
151
|
+
|
|
152
|
+
if policy in _DISABLED_INDUCTOR_CACHE_POLICIES:
|
|
153
|
+
return
|
|
154
|
+
|
|
155
|
+
# This is the important limitation. If torch is already imported, some
|
|
156
|
+
# Inductor config/cache state may already be initialized.
|
|
157
|
+
if "torch" in sys.modules:
|
|
158
|
+
warnings.warn(
|
|
159
|
+
"Dendra: torch was imported before Dendra configured TorchInductor. "
|
|
160
|
+
"Dendra cannot reliably isolate TORCHINDUCTOR_CACHE_DIR after torch import. "
|
|
161
|
+
"For concurrent notebook use, import dendra before torch or set "
|
|
162
|
+
"TORCHINDUCTOR_CACHE_DIR before starting Python.",
|
|
163
|
+
RuntimeWarning,
|
|
164
|
+
stacklevel=2,
|
|
165
|
+
)
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
if policy in _PROCESS_INDUCTOR_CACHE_POLICIES:
|
|
169
|
+
root = Path(
|
|
170
|
+
os.environ.get(
|
|
171
|
+
"DENDRA_INDUCTOR_CACHE_ROOT",
|
|
172
|
+
str(Path(tempfile.gettempdir()) / "dendra_torchinductor"),
|
|
173
|
+
)
|
|
174
|
+
).expanduser()
|
|
175
|
+
|
|
176
|
+
session_id = os.environ.get("DENDRA_INDUCTOR_SESSION_ID")
|
|
177
|
+
if not session_id:
|
|
178
|
+
session_id = _get_notebook_or_process_id()
|
|
179
|
+
|
|
180
|
+
cache_dir = root / session_id
|
|
181
|
+
cache_dir.mkdir(parents=True, exist_ok=True)
|
|
182
|
+
|
|
183
|
+
# Only set if user did not explicitly choose a cache directory.
|
|
184
|
+
os.environ.setdefault("TORCHINDUCTOR_CACHE_DIR", str(cache_dir))
|
|
185
|
+
|
|
186
|
+
# This is the key workaround for the malformed .h/.h.pch failure mode.
|
|
187
|
+
# It is an internal/implementation-dependent knob, so setdefault keeps
|
|
188
|
+
# user choice authoritative.
|
|
189
|
+
if _truthy(os.environ.get("DENDRA_INDUCTOR_DISABLE_PCH", "1")):
|
|
190
|
+
os.environ.setdefault("TORCHINDUCTOR_CPP_CACHE_PRECOMPILE_HEADERS", "0")
|
|
191
|
+
|
|
192
|
+
# Reduces within-process async compile races and makes failures easier
|
|
193
|
+
# to reproduce/debug. Users can override.
|
|
194
|
+
os.environ.setdefault(
|
|
195
|
+
"TORCHINDUCTOR_COMPILE_THREADS",
|
|
196
|
+
os.environ.get("DENDRA_INDUCTOR_COMPILE_THREADS", "1"),
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
if _truthy(os.environ.get("DENDRA_INDUCTOR_CLEANUP", "0")):
|
|
200
|
+
|
|
201
|
+
def _cleanup_cache_dir(path: Path = cache_dir) -> None:
|
|
202
|
+
shutil.rmtree(path, ignore_errors=True)
|
|
203
|
+
|
|
204
|
+
atexit.register(_cleanup_cache_dir)
|
|
205
|
+
|
|
206
|
+
elif policy in _SHARED_INDUCTOR_CACHE_POLICIES:
|
|
207
|
+
# Respect user's chosen shared cache. Do not clean it automatically.
|
|
208
|
+
if _truthy(os.environ.get("DENDRA_INDUCTOR_DISABLE_PCH", "1")):
|
|
209
|
+
os.environ.setdefault("TORCHINDUCTOR_CPP_CACHE_PRECOMPILE_HEADERS", "0")
|
|
210
|
+
|
|
211
|
+
else:
|
|
212
|
+
warnings.warn(
|
|
213
|
+
f"Dendra: unknown DENDRA_INDUCTOR_CACHE_POLICY={policy!r}; "
|
|
214
|
+
"expected 'process', 'shared', or 'off'.",
|
|
215
|
+
RuntimeWarning,
|
|
216
|
+
stacklevel=2,
|
|
217
|
+
)
|
dendra/cli.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Command-line entry points for Dendra deployment diagnostics."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
from typing import Optional, Sequence
|
|
8
|
+
|
|
9
|
+
from .diagnostics import collect_doctor_report
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _parser() -> argparse.ArgumentParser:
|
|
13
|
+
parser = argparse.ArgumentParser(prog="dendra")
|
|
14
|
+
subparsers = parser.add_subparsers(dest="command")
|
|
15
|
+
doctor = subparsers.add_parser(
|
|
16
|
+
"doctor", help="inspect CPU, CUDA, and optional native-extension readiness"
|
|
17
|
+
)
|
|
18
|
+
doctor.add_argument(
|
|
19
|
+
"--require-cuda",
|
|
20
|
+
action="store_true",
|
|
21
|
+
help="treat unavailable CUDA/PyTorch CUDA support as an error",
|
|
22
|
+
)
|
|
23
|
+
doctor.add_argument(
|
|
24
|
+
"--probe-native-bitpack",
|
|
25
|
+
action="store_true",
|
|
26
|
+
help="opt into JIT build/load and tiny native bitpack kernel launches",
|
|
27
|
+
)
|
|
28
|
+
doctor.add_argument(
|
|
29
|
+
"--json",
|
|
30
|
+
action="store_true",
|
|
31
|
+
help="emit the structured report as JSON",
|
|
32
|
+
)
|
|
33
|
+
return parser
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
37
|
+
parser = _parser()
|
|
38
|
+
args = parser.parse_args(argv)
|
|
39
|
+
if args.command != "doctor":
|
|
40
|
+
parser.print_help()
|
|
41
|
+
return 2
|
|
42
|
+
|
|
43
|
+
report = collect_doctor_report(
|
|
44
|
+
require_cuda=args.require_cuda,
|
|
45
|
+
probe_native_bitpack=args.probe_native_bitpack,
|
|
46
|
+
)
|
|
47
|
+
if args.json:
|
|
48
|
+
print(json.dumps(report.as_dict(), indent=2, sort_keys=True))
|
|
49
|
+
else:
|
|
50
|
+
print(report.to_text())
|
|
51
|
+
return 0 if report.ok else 1
|
dendra/const.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""dendra.const
|
|
2
|
+
|
|
3
|
+
Mathematical and physical constants used throughout Dendra.
|
|
4
|
+
|
|
5
|
+
All values are plain Python ``float`` constants (TorchScript-friendly).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import math
|
|
11
|
+
|
|
12
|
+
import torch
|
|
13
|
+
|
|
14
|
+
__all__ = ["PI", "E", "TAU", "R", "FARADAY"]
|
|
15
|
+
|
|
16
|
+
PI: torch.jit.Final[float] = math.pi
|
|
17
|
+
""":math:`\\pi`, ratio of a circle's circumference to its diameter."""
|
|
18
|
+
|
|
19
|
+
E: torch.jit.Final[float] = math.e
|
|
20
|
+
"""Euler's number."""
|
|
21
|
+
|
|
22
|
+
TAU: torch.jit.Final[float] = math.tau
|
|
23
|
+
""":math:`\\tau = 2\\pi`."""
|
|
24
|
+
|
|
25
|
+
R: torch.jit.Final[float] = 8314.46261815324
|
|
26
|
+
"""Molar gas constant in Dendra's millivolt convention.
|
|
27
|
+
|
|
28
|
+
The value has units mV·C/(mol·K), so ``R * temperature / FARADAY`` is in mV
|
|
29
|
+
when :data:`FARADAY` is expressed in C/mol. It is numerically equal to the gas
|
|
30
|
+
constant in J/(kmol·K).
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
FARADAY: torch.jit.Final[float] = 96485.33212331001
|
|
34
|
+
"""Faraday constant in SI units of C/mol."""
|