DeepGPR 0.1.1__tar.gz → 0.1.3__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.
- {deepgpr-0.1.1/src/DeepGPR.egg-info → deepgpr-0.1.3}/PKG-INFO +17 -18
- {deepgpr-0.1.1 → deepgpr-0.1.3}/README.md +15 -16
- {deepgpr-0.1.1 → deepgpr-0.1.3/docs}/CHANGELOG.md +45 -10
- deepgpr-0.1.3/docs/Fig/2dfwiinit.png +0 -0
- deepgpr-0.1.3/docs/Fig/2dfwipred.png +0 -0
- deepgpr-0.1.3/docs/Fig/2dfwitrue.png +0 -0
- deepgpr-0.1.3/docs/Fig/3dfwiinit.png +0 -0
- deepgpr-0.1.3/docs/Fig/3dfwipred.png +0 -0
- deepgpr-0.1.3/docs/Fig/3dfwitrue.png +0 -0
- deepgpr-0.1.3/docs/Fig/example.png +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3/docs}/MANIFEST.in +6 -4
- deepgpr-0.1.3/docs/build_support.py +20 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/pyproject.toml +7 -4
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/__init__.py +2 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/_version.py +1 -1
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/inversion/regularization.py +1 -1
- deepgpr-0.1.3/src/DeepGPR/lib/cuda_resources.h +156 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr.cu +149 -93
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr.dll +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr.h +5 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr.so +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr_cpu.c +64 -26
- deepgpr-0.1.3/src/DeepGPR/lib/deepgpr_cpu.dll +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/deepgpr_cpu.dylib +0 -0
- deepgpr-0.1.3/src/DeepGPR/lib/deepgpr_cpu.so +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/native/__init__.py +2 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/native/abi.py +2 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/native/loader.py +26 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/preprocessing/model_setup.py +16 -8
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/autograd.py +23 -3
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/memory.py +2 -1
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/modeling.py +20 -4
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/pml.py +36 -13
- {deepgpr-0.1.1 → deepgpr-0.1.3/src/DeepGPR.egg-info}/PKG-INFO +17 -18
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR.egg-info/SOURCES.txt +11 -2
- deepgpr-0.1.1/src/DeepGPR/lib/deepgpr_cpu.dll +0 -0
- deepgpr-0.1.1/src/DeepGPR/lib/deepgpr_cpu.so +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/license +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/requirements.txt +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/setup.cfg +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/common.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/compute2.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/config/__init__.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/config/constants.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/config/defaults.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/inversion/__init__.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/lib/libomp.dylib +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/multiscale.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/native/bridge.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/postprocessing/__init__.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/postprocessing/filters.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/postprocessing/io.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/preprocessing/__init__.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/preprocessing/grid.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/preprocessing/stability.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/preprocessing/wavelets.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/py.typed +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/__init__.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/fields.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/sampling.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/solver/storage.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/__init__.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/devices.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/exceptions.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/formatting.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/logger.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/tensor_checks.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/utils/validators.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/visualization/__init__.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/visualization/plotting.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR/wavelet.py +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR.egg-info/dependency_links.txt +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR.egg-info/requires.txt +0 -0
- {deepgpr-0.1.1 → deepgpr-0.1.3}/src/DeepGPR.egg-info/top_level.txt +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DeepGPR
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: PyTorch and CUDA for GPR FWI
|
|
5
5
|
Author-email: Lei Liu <liulei990222@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/songc0a/DeepGPR
|
|
8
8
|
Project-URL: Repository, https://github.com/songc0a/DeepGPR
|
|
9
9
|
Project-URL: Documentation, https://songc0a.github.io/DeepGPR/
|
|
10
|
-
Project-URL: Changelog, https://github.com/songc0a/DeepGPR/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Changelog, https://github.com/songc0a/DeepGPR/blob/main/docs/CHANGELOG.md
|
|
11
11
|
Keywords: ground penetrating radar,GPR,FDTD,full waveform inversion,PyTorch,CUDA
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
13
|
Classifier: Operating System :: Microsoft :: Windows
|
|
@@ -44,10 +44,10 @@ DeepGPR provides a wave propagation module for PyTorch, designed for application
|
|
|
44
44
|
|
|
45
45
|
- 2D and 3D forward modeling of Maxwell's equations with the Finite-Difference Time-Domain (FDTD) method, for single and multiple excitations.
|
|
46
46
|
- Gradients of the receiver data with respect to relative permittivity, conductivity, the initial wavefield and the source amplitudes, computed by an exact discrete adjoint.
|
|
47
|
-
- Automatic extension of the physical model into a CPML with an independent thickness on every face. Supply only air and the target region;
|
|
47
|
+
- Automatic extension of the physical model into a CPML with an independent thickness on every face. Supply only air and the target region; sensitivities from replicated PML materials are summed back to the input model edges. Absorption uses a fixed `pml_max_velocity` reference (vacuum light speed by default).
|
|
48
48
|
- CUDA GPU backend and a C/OpenMP CPU backend (selected automatically with `device='cpu'`).
|
|
49
49
|
- Spatial FDTD order 2, 4 or 8 (`fdtd_order`), and gradient mode 2 (Ez only) or 3 (Ex, Ey, Ez).
|
|
50
|
-
- Large models: checkpointing, DDP, temporal sub-sampling (fixed or `"auto"` from the source spectrum), E-only float32 histories (default; half the memory of E+R),
|
|
50
|
+
- Large models: checkpointing, DDP, temporal sub-sampling (fixed or `"auto"` from the source spectrum), E-only float32 histories (default; half the memory of E+R), FP16/BF16 or GPU-native INT8 wavefield histories and asynchronous offload to host memory. Material gradients with PML require `wavefield_history_region="extended"`; physical-only histories remain available for diagnostics, source/initial-state gradients and models without PML. See [`docs/API.md`](docs/API.md) §4.3-4.6.
|
|
51
51
|
|
|
52
52
|
## System requirements
|
|
53
53
|
|
|
@@ -68,8 +68,7 @@ pip install "DeepGPR[examples]" # + scipy, scikit-image, jupyter for the not
|
|
|
68
68
|
For development from a clone:
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
-
pip install -
|
|
72
|
-
pip install -e .
|
|
71
|
+
pip install -e ".[dev,examples]"
|
|
73
72
|
```
|
|
74
73
|
|
|
75
74
|
The prebuilt native libraries ship in `src/DeepGPR/lib`. To rebuild them see [`docs/BUILDING.md`](docs/BUILDING.md).
|
|
@@ -114,7 +113,7 @@ DeepGPR.visualization.plot_model(eps_r.grad, ax=ax[1], title="Gradient", cmap="s
|
|
|
114
113
|
plt.show()
|
|
115
114
|
```
|
|
116
115
|
|
|
117
|
-

|
|
116
|
+

|
|
118
117
|
|
|
119
118
|
More examples are in [`examples/`](examples) (forward modeling, 2D FWI, 3D FWI).
|
|
120
119
|
|
|
@@ -141,15 +140,15 @@ The figures show the true model, the initial model and the inverted result.
|
|
|
141
140
|
|
|
142
141
|
| True model | Initial model | Inverted result |
|
|
143
142
|
| --- | --- | --- |
|
|
144
|
-
|  |  |  |
|
|
143
|
+
|  |  |  |
|
|
145
144
|
|
|
146
145
|
### 3D FWI (central slice)
|
|
147
146
|
|
|
148
147
|
| Model | Central slice |
|
|
149
148
|
| --- | --- |
|
|
150
|
-
| True model |  |
|
|
151
|
-
| Initial model |  |
|
|
152
|
-
| Inverted result |  |
|
|
149
|
+
| True model |  |
|
|
150
|
+
| Initial model |  |
|
|
151
|
+
| Inverted result |  |
|
|
153
152
|
|
|
154
153
|
## API overview
|
|
155
154
|
|
|
@@ -198,10 +197,10 @@ src/DeepGPR/
|
|
|
198
197
|
├── utils/ logging, exceptions, validators, diagnostics
|
|
199
198
|
├── lib/ deepgpr.cu, deepgpr_cpu.c, deepgpr.h and prebuilt binaries
|
|
200
199
|
├── common.py, compute2.py, multiscale.py, wavelet.py compatibility modules
|
|
201
|
-
docs/ API reference, build guide,
|
|
200
|
+
docs/ API reference, build guide, changelog, manifest and Fig/
|
|
202
201
|
examples/ forward, 2D FWI and 3D FWI notebooks
|
|
203
202
|
tests/ unit tests, verification notebooks, benchmarks
|
|
204
|
-
tools/
|
|
203
|
+
website/ static pages, assets, scripts/, tools/ and promo_pixel/
|
|
205
204
|
```
|
|
206
205
|
|
|
207
206
|
Data flow of one `compute` call:
|
|
@@ -216,8 +215,8 @@ and the saved history.
|
|
|
216
215
|
python -m unittest discover -s tests -p "test_*.py" # unit tests
|
|
217
216
|
python -m unittest tests/test_native_abi.py # ABI check, no PyTorch needed
|
|
218
217
|
python tests/run_notebook.py tests/00_local_backend_and_contracts.ipynb
|
|
219
|
-
python tools/verify_equivalence.py --reference-src /path/to/DeepGPR-0.0.20/src/DeepGPR
|
|
220
|
-
bash tools/run_local_validation.sh /path/to/DeepGPR-0.0.20 # rebuild CPU+CUDA libs, run everything
|
|
218
|
+
python website/tools/verify_equivalence.py --no-pml --reference-src /path/to/DeepGPR-0.0.20/src/DeepGPR
|
|
219
|
+
bash website/tools/run_local_validation.sh /path/to/DeepGPR-0.0.20 # rebuild CPU+CUDA libs, run everything
|
|
221
220
|
```
|
|
222
221
|
|
|
223
222
|
Run the notebooks `00` to `09` in numeric order, followed by
|
|
@@ -232,15 +231,15 @@ bits between runs.
|
|
|
232
231
|
|
|
233
232
|
**Reproducing results from DeepGPR ≤ 0.0.20.** 0.1.0 corrects the FIR design
|
|
234
233
|
for even filter lengths, the envelope for odd trace lengths and the isotropic
|
|
235
|
-
TV (see [`CHANGELOG.md`](CHANGELOG.md)). Use `apply_filter(..., legacy=True)`,
|
|
234
|
+
TV (see [`docs/CHANGELOG.md`](docs/CHANGELOG.md)). Use `apply_filter(..., legacy=True)`,
|
|
236
235
|
`design_fir_filter(..., legacy=True)`, `hilbert_transform(..., legacy=True)`
|
|
237
236
|
and `TVRegularization(method="legacy_isotropic")` to reproduce earlier numbers.
|
|
238
237
|
|
|
239
238
|
## Development
|
|
240
239
|
|
|
241
|
-
- Code style: PEP 8, enforced with `ruff check src/DeepGPR tools` (configuration in `pyproject.toml`).
|
|
240
|
+
- Code style: PEP 8, enforced with `ruff check src/DeepGPR website/tools docs/build_support.py` (configuration in `pyproject.toml`).
|
|
242
241
|
- Type hints throughout; `mypy` configuration in `pyproject.toml`.
|
|
243
|
-
- Changes are recorded in [`CHANGELOG.md`](CHANGELOG.md); known issues and recommended native work in [`docs/AUDIT.md`](docs/AUDIT.md).
|
|
242
|
+
- Changes are recorded in [`docs/CHANGELOG.md`](docs/CHANGELOG.md); known issues and recommended native work in [`docs/AUDIT.md`](docs/AUDIT.md).
|
|
244
243
|
- Changes to `lib/deepgpr.h` must be mirrored in `src/DeepGPR/native/abi.py`; `tests/test_native_abi.py` enforces it.
|
|
245
244
|
|
|
246
245
|
## Citation
|
|
@@ -8,10 +8,10 @@ DeepGPR provides a wave propagation module for PyTorch, designed for application
|
|
|
8
8
|
|
|
9
9
|
- 2D and 3D forward modeling of Maxwell's equations with the Finite-Difference Time-Domain (FDTD) method, for single and multiple excitations.
|
|
10
10
|
- Gradients of the receiver data with respect to relative permittivity, conductivity, the initial wavefield and the source amplitudes, computed by an exact discrete adjoint.
|
|
11
|
-
- Automatic extension of the physical model into a CPML with an independent thickness on every face. Supply only air and the target region;
|
|
11
|
+
- Automatic extension of the physical model into a CPML with an independent thickness on every face. Supply only air and the target region; sensitivities from replicated PML materials are summed back to the input model edges. Absorption uses a fixed `pml_max_velocity` reference (vacuum light speed by default).
|
|
12
12
|
- CUDA GPU backend and a C/OpenMP CPU backend (selected automatically with `device='cpu'`).
|
|
13
13
|
- Spatial FDTD order 2, 4 or 8 (`fdtd_order`), and gradient mode 2 (Ez only) or 3 (Ex, Ey, Ez).
|
|
14
|
-
- Large models: checkpointing, DDP, temporal sub-sampling (fixed or `"auto"` from the source spectrum), E-only float32 histories (default; half the memory of E+R),
|
|
14
|
+
- Large models: checkpointing, DDP, temporal sub-sampling (fixed or `"auto"` from the source spectrum), E-only float32 histories (default; half the memory of E+R), FP16/BF16 or GPU-native INT8 wavefield histories and asynchronous offload to host memory. Material gradients with PML require `wavefield_history_region="extended"`; physical-only histories remain available for diagnostics, source/initial-state gradients and models without PML. See [`docs/API.md`](docs/API.md) §4.3-4.6.
|
|
15
15
|
|
|
16
16
|
## System requirements
|
|
17
17
|
|
|
@@ -32,8 +32,7 @@ pip install "DeepGPR[examples]" # + scipy, scikit-image, jupyter for the not
|
|
|
32
32
|
For development from a clone:
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
pip install -
|
|
36
|
-
pip install -e .
|
|
35
|
+
pip install -e ".[dev,examples]"
|
|
37
36
|
```
|
|
38
37
|
|
|
39
38
|
The prebuilt native libraries ship in `src/DeepGPR/lib`. To rebuild them see [`docs/BUILDING.md`](docs/BUILDING.md).
|
|
@@ -78,7 +77,7 @@ DeepGPR.visualization.plot_model(eps_r.grad, ax=ax[1], title="Gradient", cmap="s
|
|
|
78
77
|
plt.show()
|
|
79
78
|
```
|
|
80
79
|
|
|
81
|
-

|
|
80
|
+

|
|
82
81
|
|
|
83
82
|
More examples are in [`examples/`](examples) (forward modeling, 2D FWI, 3D FWI).
|
|
84
83
|
|
|
@@ -105,15 +104,15 @@ The figures show the true model, the initial model and the inverted result.
|
|
|
105
104
|
|
|
106
105
|
| True model | Initial model | Inverted result |
|
|
107
106
|
| --- | --- | --- |
|
|
108
|
-
|  |  |  |
|
|
107
|
+
|  |  |  |
|
|
109
108
|
|
|
110
109
|
### 3D FWI (central slice)
|
|
111
110
|
|
|
112
111
|
| Model | Central slice |
|
|
113
112
|
| --- | --- |
|
|
114
|
-
| True model |  |
|
|
115
|
-
| Initial model |  |
|
|
116
|
-
| Inverted result |  |
|
|
113
|
+
| True model |  |
|
|
114
|
+
| Initial model |  |
|
|
115
|
+
| Inverted result |  |
|
|
117
116
|
|
|
118
117
|
## API overview
|
|
119
118
|
|
|
@@ -162,10 +161,10 @@ src/DeepGPR/
|
|
|
162
161
|
├── utils/ logging, exceptions, validators, diagnostics
|
|
163
162
|
├── lib/ deepgpr.cu, deepgpr_cpu.c, deepgpr.h and prebuilt binaries
|
|
164
163
|
├── common.py, compute2.py, multiscale.py, wavelet.py compatibility modules
|
|
165
|
-
docs/ API reference, build guide,
|
|
164
|
+
docs/ API reference, build guide, changelog, manifest and Fig/
|
|
166
165
|
examples/ forward, 2D FWI and 3D FWI notebooks
|
|
167
166
|
tests/ unit tests, verification notebooks, benchmarks
|
|
168
|
-
tools/
|
|
167
|
+
website/ static pages, assets, scripts/, tools/ and promo_pixel/
|
|
169
168
|
```
|
|
170
169
|
|
|
171
170
|
Data flow of one `compute` call:
|
|
@@ -180,8 +179,8 @@ and the saved history.
|
|
|
180
179
|
python -m unittest discover -s tests -p "test_*.py" # unit tests
|
|
181
180
|
python -m unittest tests/test_native_abi.py # ABI check, no PyTorch needed
|
|
182
181
|
python tests/run_notebook.py tests/00_local_backend_and_contracts.ipynb
|
|
183
|
-
python tools/verify_equivalence.py --reference-src /path/to/DeepGPR-0.0.20/src/DeepGPR
|
|
184
|
-
bash tools/run_local_validation.sh /path/to/DeepGPR-0.0.20 # rebuild CPU+CUDA libs, run everything
|
|
182
|
+
python website/tools/verify_equivalence.py --no-pml --reference-src /path/to/DeepGPR-0.0.20/src/DeepGPR
|
|
183
|
+
bash website/tools/run_local_validation.sh /path/to/DeepGPR-0.0.20 # rebuild CPU+CUDA libs, run everything
|
|
185
184
|
```
|
|
186
185
|
|
|
187
186
|
Run the notebooks `00` to `09` in numeric order, followed by
|
|
@@ -196,15 +195,15 @@ bits between runs.
|
|
|
196
195
|
|
|
197
196
|
**Reproducing results from DeepGPR ≤ 0.0.20.** 0.1.0 corrects the FIR design
|
|
198
197
|
for even filter lengths, the envelope for odd trace lengths and the isotropic
|
|
199
|
-
TV (see [`CHANGELOG.md`](CHANGELOG.md)). Use `apply_filter(..., legacy=True)`,
|
|
198
|
+
TV (see [`docs/CHANGELOG.md`](docs/CHANGELOG.md)). Use `apply_filter(..., legacy=True)`,
|
|
200
199
|
`design_fir_filter(..., legacy=True)`, `hilbert_transform(..., legacy=True)`
|
|
201
200
|
and `TVRegularization(method="legacy_isotropic")` to reproduce earlier numbers.
|
|
202
201
|
|
|
203
202
|
## Development
|
|
204
203
|
|
|
205
|
-
- Code style: PEP 8, enforced with `ruff check src/DeepGPR tools` (configuration in `pyproject.toml`).
|
|
204
|
+
- Code style: PEP 8, enforced with `ruff check src/DeepGPR website/tools docs/build_support.py` (configuration in `pyproject.toml`).
|
|
206
205
|
- Type hints throughout; `mypy` configuration in `pyproject.toml`.
|
|
207
|
-
- Changes are recorded in [`CHANGELOG.md`](CHANGELOG.md); known issues and recommended native work in [`docs/AUDIT.md`](docs/AUDIT.md).
|
|
206
|
+
- Changes are recorded in [`docs/CHANGELOG.md`](docs/CHANGELOG.md); known issues and recommended native work in [`docs/AUDIT.md`](docs/AUDIT.md).
|
|
208
207
|
- Changes to `lib/deepgpr.h` must be mirrored in `src/DeepGPR/native/abi.py`; `tests/test_native_abi.py` enforces it.
|
|
209
208
|
|
|
210
209
|
## Citation
|
|
@@ -6,8 +6,21 @@ All notable changes to this project are documented here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased] — History memory and CUDA adjoint performance
|
|
8
8
|
|
|
9
|
+
### Repository layout
|
|
10
|
+
|
|
11
|
+
- Website tools, statistics scripts and pixel film sources now live under
|
|
12
|
+
`website/tools`, `website/scripts` and `website/promo_pixel`. Their input/output
|
|
13
|
+
paths and CI commands follow the new locations; Pages publishes public assets
|
|
14
|
+
without the source tool directories.
|
|
15
|
+
- Figures, changelog and the source-distribution template now live in `docs`.
|
|
16
|
+
The setuptools build hook reads `docs/MANIFEST.in`, including when building a
|
|
17
|
+
wheel from a source archive. Documentation and package metadata links updated.
|
|
18
|
+
- Development dependencies are installed with `pip install -e ".[dev,examples]"`.
|
|
19
|
+
Removed the duplicate development requirements file and local assistant
|
|
20
|
+
configuration, and cleaned embedded tool attribution from media metadata.
|
|
21
|
+
|
|
9
22
|
Measurements, protocol and per-item decisions:
|
|
10
|
-
[`tests/profiling_results/history_adjoint_gpu_report.md`](tests/profiling_results/history_adjoint_gpu_report.md).
|
|
23
|
+
[`tests/profiling_results/history_adjoint_gpu_report.md`](../tests/profiling_results/history_adjoint_gpu_report.md).
|
|
11
24
|
|
|
12
25
|
### Added
|
|
13
26
|
|
|
@@ -29,14 +42,21 @@ Measurements, protocol and per-item decisions:
|
|
|
29
42
|
capability probe `deepgpr_supports_rhs_reconstruction` (ABI 6 unchanged);
|
|
30
43
|
older libraries fall back to E+R.
|
|
31
44
|
- `wavefield_history_region` (`"extended"` default, `"physical"`). `"physical"`
|
|
32
|
-
stores E/R histories only on
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
stores E/R histories only on physical cells for forward diagnostics,
|
|
46
|
+
source/initial-state gradients, or models without PML. Material inversion
|
|
47
|
+
with PML requires `"extended"`. INT8 histories widen the box to whole tiles of the
|
|
35
48
|
full-grid tiling so tiles and scales are identical to `"extended"`. New probe
|
|
36
49
|
`deepgpr_supports_physical_history`; saved files record the region.
|
|
37
50
|
|
|
38
51
|
### Performance
|
|
39
52
|
|
|
53
|
+
- CUDA async-offload calls reuse streams, synchronization events and staging
|
|
54
|
+
buffers (audit N-8). Workspaces are exclusive to each call, partitioned by
|
|
55
|
+
device, and cached only after successful synchronization. At most one idle
|
|
56
|
+
workspace with up to 64 MiB of staging is retained per device;
|
|
57
|
+
`DeepGPR.clear_cuda_resource_cache(device=None)` releases idle resources.
|
|
58
|
+
Native forward/backward signatures and ABI 6 are unchanged. Measurements:
|
|
59
|
+
[CUDA resource cache report](../tests/profiling_results/cuda_resource_cache_report.md).
|
|
40
60
|
- CUDA full-grid kernels (E/H update and adjoint) take the shot from
|
|
41
61
|
`blockIdx.y` and decode `(i, j, k)` from a 32-bit per-shot index with a
|
|
42
62
|
multiply-high divider instead of four 64-bit `/` and `%` per thread. Grids
|
|
@@ -75,6 +95,21 @@ Measurements, protocol and per-item decisions:
|
|
|
75
95
|
|
|
76
96
|
### Changed
|
|
77
97
|
|
|
98
|
+
- PML materials remain derived from the physical model, with CPU/CUDA material
|
|
99
|
+
sensitivities retained throughout PML and summed back to model edges,
|
|
100
|
+
intersections and corners. Absorbing profiles use `pml_max_velocity`, a fixed
|
|
101
|
+
reference speed (default vacuum), instead of changing boundary material
|
|
102
|
+
averages. Keep it fixed during optimization, FD checks and checkpointing.
|
|
103
|
+
Old native libraries are rejected for PML material gradients via the new
|
|
104
|
+
`deepgpr_supports_pml_material_gradients` probe; ABI 6 is unchanged.
|
|
105
|
+
- Exactly zero local material sensitivities remain zero even when an
|
|
106
|
+
unobservable outer-CPML state cotangent overflows in long lossless runs.
|
|
107
|
+
CPU, CUDA and INT8 avoid `0 * Inf` without clipping nonzero sensitivities
|
|
108
|
+
or changing the forward equations. Arbitrary long-time initial-state
|
|
109
|
+
cotangents can still overflow on these outer cells.
|
|
110
|
+
- Corrected material gradients at Yee components that do not execute the base
|
|
111
|
+
electric update; source and CPML corrections still contribute through `cb`.
|
|
112
|
+
- Total variation losses preserve the input dtype, including float64.
|
|
78
113
|
- An explicit `model_gradient_sampling_interval > 1` no longer always raises a
|
|
79
114
|
`RuntimeWarning`; it warns (and states the bound) only above
|
|
80
115
|
`floor(1 / (4 f_max dt))`. Intervals inside the bound are logged at INFO.
|
|
@@ -93,7 +128,7 @@ Measurements, protocol and per-item decisions:
|
|
|
93
128
|
|
|
94
129
|
This release reorganises the Python package into a layered, typed and
|
|
95
130
|
documented code base and fixes the defects found in the review
|
|
96
|
-
([`docs/AUDIT.md`](
|
|
131
|
+
([`docs/AUDIT.md`](AUDIT.md)).
|
|
97
132
|
|
|
98
133
|
**What changes numerically** (all deliberate, see [Numerical fixes](#numerical-fixes)):
|
|
99
134
|
|
|
@@ -202,7 +237,7 @@ from the 0.1.0 sources. The CUDA (`deepgpr.so`, `deepgpr.dll`) and the Windows /
|
|
|
202
237
|
macOS CPU binaries are still the 0.0.20 builds until the *Build Native
|
|
203
238
|
Libraries* workflow runs; they load and compute as before but without error
|
|
204
239
|
reporting (and, for the CPU ones, without the deterministic adjoint).
|
|
205
|
-
`tools/run_local_validation.sh` rebuilds the CPU and CUDA libraries locally
|
|
240
|
+
`website/tools/run_local_validation.sh` rebuilds the CPU and CUDA libraries locally
|
|
206
241
|
and runs the full validation.
|
|
207
242
|
|
|
208
243
|
### Fixed
|
|
@@ -234,7 +269,7 @@ and runs the full validation.
|
|
|
234
269
|
(same `forward_wavefield_HH-MM[_NN].pt` scheme). Partially written files are
|
|
235
270
|
removed on failure.
|
|
236
271
|
- **Invalid requirement shipped in the wheel.** `src/DeepGPR/requirements.txt`
|
|
237
|
-
contained `torch+cu` and was packaged via `MANIFEST.in`; removed.
|
|
272
|
+
contained `torch+cu` and was packaged via `docs/MANIFEST.in`; removed.
|
|
238
273
|
- Error message of `apply_filter` used full-width punctuation (`。`).
|
|
239
274
|
|
|
240
275
|
### Changed
|
|
@@ -300,7 +335,7 @@ measurable:
|
|
|
300
335
|
- `tests/test_signal_and_regularization.py` (FIR, envelope and TV against
|
|
301
336
|
independent NumPy implementations; legacy switches).
|
|
302
337
|
- `tests/test_cpu_determinism.py` (bitwise equality for 1, 2 and 5 threads).
|
|
303
|
-
- `tools/verify_equivalence.py` (comparison with a reference release: forward
|
|
338
|
+
- `website/tools/verify_equivalence.py` (comparison with a reference release: forward
|
|
304
339
|
and gradient tolerances, legacy reproduction, determinism, error reporting).
|
|
305
340
|
- `legacy=` keyword for `design_fir_filter`, `apply_filter`,
|
|
306
341
|
`hilbert_transform`; `remove_dc=` for `hilbert_transform`; `epsilon=` and
|
|
@@ -308,7 +343,7 @@ measurable:
|
|
|
308
343
|
- Native functions `deepgpr_supports_error_reporting`, `deepgpr_last_error`,
|
|
309
344
|
`deepgpr_clear_last_error`, `deepgpr_deterministic_adjoint` (ABI 6, additive).
|
|
310
345
|
- `.github/workflows/quality.yml` (ruff, ABI test, CPU unit tests, equivalence).
|
|
311
|
-
- `requirements.txt`, `
|
|
346
|
+
- `requirements.txt`, development extras in `pyproject.toml`, ruff/mypy/pytest configuration.
|
|
312
347
|
|
|
313
348
|
### Removed / internal changes
|
|
314
349
|
|
|
@@ -353,7 +388,7 @@ which is byte-identical to the 0.0.21 PyPI release):
|
|
|
353
388
|
|
|
354
389
|
| Check | Scope | Result |
|
|
355
390
|
|---|---|---|
|
|
356
|
-
| `tools/verify_equivalence.py` | CPU and CUDA: 2D/3D × order 2/4/8 × fp32/fp16/bf16 × sampling 1/3, no/asymmetric PML, forward-only, mode 3, checkpoint segments; CUDA INT8 (2D/3D), async offload, fp16 conversion backends; legacy switches; error reporting; CPU determinism for 1/2/4/8 threads | all passed; forward outputs **bitwise identical**, gradients within 1.9·10⁻⁶ (CPU) / 4.7·10⁻⁷ (CUDA) relative |
|
|
391
|
+
| `website/tools/verify_equivalence.py` | CPU and CUDA: 2D/3D × order 2/4/8 × fp32/fp16/bf16 × sampling 1/3, no/asymmetric PML, forward-only, mode 3, checkpoint segments; CUDA INT8 (2D/3D), async offload, fp16 conversion backends; legacy switches; error reporting; CPU determinism for 1/2/4/8 threads | all passed; forward outputs **bitwise identical**, gradients within 1.9·10⁻⁶ (CPU) / 4.7·10⁻⁷ (CUDA) relative |
|
|
357
392
|
| Unit tests | 105 tests, `OMP_NUM_THREADS` = 1, 2, 4, 8 | all passed (1 skip: needs two GPUs) |
|
|
358
393
|
| Verification notebooks `tests/00`–`09`, `99` | `DEEPGPR_REQUIRE_CUDA=1` | 108 checks passed, CUDA parity evidence present |
|
|
359
394
|
| CI simulation | Python 3.12, PyTorch 2.x CPU: unit tests and `verify_equivalence.py --device cpu --quick`; `ruff check src/DeepGPR tools` | all passed |
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
include README.md
|
|
2
|
-
include CHANGELOG.md
|
|
3
2
|
include license
|
|
4
3
|
include pyproject.toml
|
|
5
4
|
include requirements.txt
|
|
@@ -9,14 +8,17 @@ recursive-include src/DeepGPR *.py *.typed *.cu *.h *.c *.dll *.so *.dylib
|
|
|
9
8
|
# Exclude local state and repository-only resources.
|
|
10
9
|
prune .*
|
|
11
10
|
prune validation
|
|
12
|
-
prune Fig
|
|
13
11
|
prune docs
|
|
14
12
|
prune examples
|
|
15
|
-
prune scripts
|
|
16
13
|
prune tests
|
|
17
|
-
prune tools
|
|
18
14
|
prune website
|
|
19
15
|
|
|
16
|
+
# Keep the relocated manifest and its build hook available in the sdist.
|
|
17
|
+
include docs/MANIFEST.in
|
|
18
|
+
include docs/build_support.py
|
|
19
|
+
include docs/CHANGELOG.md
|
|
20
|
+
recursive-include docs/Fig *.png
|
|
21
|
+
|
|
20
22
|
global-exclude .DS_Store
|
|
21
23
|
global-exclude *.py[cod]
|
|
22
24
|
global-exclude __pycache__
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Keep the source-distribution manifest alongside the project documentation."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from setuptools.command.egg_info import egg_info, manifest_maker
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class EggInfo(egg_info):
|
|
9
|
+
"""Use docs/MANIFEST.in when setuptools generates the source file list."""
|
|
10
|
+
|
|
11
|
+
def find_sources(self):
|
|
12
|
+
template = Path("docs/MANIFEST.in")
|
|
13
|
+
if not template.is_file():
|
|
14
|
+
raise FileNotFoundError("Source distribution template missing: docs/MANIFEST.in")
|
|
15
|
+
maker = manifest_maker(self.distribution)
|
|
16
|
+
maker.ignore_egg_info_dir = self.ignore_egg_info_in_manifest
|
|
17
|
+
maker.template = str(template)
|
|
18
|
+
maker.manifest = str(Path(self.egg_info) / "SOURCES.txt")
|
|
19
|
+
maker.run()
|
|
20
|
+
self.filelist = maker.filelist
|
|
@@ -39,12 +39,15 @@ dev = ["ruff>=0.5", "mypy>=1.8", "pytest>=7", "nbformat", "nbclient"]
|
|
|
39
39
|
Homepage = "https://github.com/songc0a/DeepGPR"
|
|
40
40
|
Repository = "https://github.com/songc0a/DeepGPR"
|
|
41
41
|
Documentation = "https://songc0a.github.io/DeepGPR/"
|
|
42
|
-
Changelog = "https://github.com/songc0a/DeepGPR/blob/main/CHANGELOG.md"
|
|
42
|
+
Changelog = "https://github.com/songc0a/DeepGPR/blob/main/docs/CHANGELOG.md"
|
|
43
43
|
|
|
44
44
|
[tool.setuptools]
|
|
45
|
-
package-dir = { "" = "src" }
|
|
45
|
+
package-dir = { "" = "src", docs = "docs" }
|
|
46
46
|
include-package-data = true
|
|
47
47
|
|
|
48
|
+
[tool.setuptools.cmdclass]
|
|
49
|
+
egg_info = "docs.build_support.EggInfo"
|
|
50
|
+
|
|
48
51
|
[tool.setuptools.dynamic]
|
|
49
52
|
version = { attr = "DeepGPR._version.__version__" }
|
|
50
53
|
|
|
@@ -77,8 +80,8 @@ DeepGPR = [
|
|
|
77
80
|
[tool.ruff]
|
|
78
81
|
line-length = 100
|
|
79
82
|
target-version = "py38"
|
|
80
|
-
src = ["src", "tests", "tools"]
|
|
81
|
-
extend-exclude = ["tests/*.ipynb", "examples", "website", "scripts"]
|
|
83
|
+
src = ["src", "tests", "website/tools"]
|
|
84
|
+
extend-exclude = ["tests/*.ipynb", "examples", "website/assets", "website/scripts", "website/promo_pixel"]
|
|
82
85
|
|
|
83
86
|
[tool.ruff.lint]
|
|
84
87
|
select = ["E", "F", "W", "B", "UP", "SIM", "C4"]
|
|
@@ -34,6 +34,7 @@ from __future__ import annotations
|
|
|
34
34
|
from . import config, utils
|
|
35
35
|
from ._version import __version__
|
|
36
36
|
from .native.loader import (
|
|
37
|
+
clear_cuda_resource_cache,
|
|
37
38
|
get_deepgpr_lib,
|
|
38
39
|
get_deepgpr_library_path,
|
|
39
40
|
set_library_fdtd_order,
|
|
@@ -97,6 +98,7 @@ __all__ = [
|
|
|
97
98
|
"check_cfl",
|
|
98
99
|
"check_tensors_for_nan_inf",
|
|
99
100
|
"checkpoint_initial_field",
|
|
101
|
+
"clear_cuda_resource_cache",
|
|
100
102
|
"common",
|
|
101
103
|
"compute",
|
|
102
104
|
"compute2",
|
|
@@ -137,7 +137,7 @@ class TVRegularization(nn.Module):
|
|
|
137
137
|
raise ValueError("TVRegularization needs at least one of ep or sigma.")
|
|
138
138
|
reference = ep if ep is not None else sigma
|
|
139
139
|
assert reference is not None
|
|
140
|
-
loss =
|
|
140
|
+
loss = reference.new_zeros(())
|
|
141
141
|
if ep is not None and self.weight_ep > 0:
|
|
142
142
|
loss += self.weight_ep * self._compute_tv(ep)
|
|
143
143
|
if sigma is not None and self.weight_sigma > 0:
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#ifndef DEEPGPR_CUDA_RESOURCES_H
|
|
2
|
+
#define DEEPGPR_CUDA_RESOURCES_H
|
|
3
|
+
|
|
4
|
+
#include <cuda_runtime.h>
|
|
5
|
+
#include <list>
|
|
6
|
+
#include <mutex>
|
|
7
|
+
#include <new>
|
|
8
|
+
#include <utility>
|
|
9
|
+
|
|
10
|
+
/* A workspace is leased exclusively to one native call. Only drained,
|
|
11
|
+
* successful calls return it to the cache; histories remain caller-owned. */
|
|
12
|
+
struct CudaAsyncWorkspace {
|
|
13
|
+
int device = -1;
|
|
14
|
+
unsigned char* e = nullptr;
|
|
15
|
+
unsigned char* r = nullptr;
|
|
16
|
+
size_t e_capacity = 0;
|
|
17
|
+
size_t r_capacity = 0;
|
|
18
|
+
cudaStream_t streams[2] = {nullptr, nullptr};
|
|
19
|
+
cudaEvent_t events[4] = {nullptr, nullptr, nullptr, nullptr};
|
|
20
|
+
|
|
21
|
+
CudaAsyncWorkspace() = default;
|
|
22
|
+
CudaAsyncWorkspace(const CudaAsyncWorkspace&) = delete;
|
|
23
|
+
CudaAsyncWorkspace& operator=(const CudaAsyncWorkspace&) = delete;
|
|
24
|
+
|
|
25
|
+
void swap(CudaAsyncWorkspace& other) noexcept
|
|
26
|
+
{
|
|
27
|
+
std::swap(device, other.device);
|
|
28
|
+
std::swap(e, other.e);
|
|
29
|
+
std::swap(r, other.r);
|
|
30
|
+
std::swap(e_capacity, other.e_capacity);
|
|
31
|
+
std::swap(r_capacity, other.r_capacity);
|
|
32
|
+
for (int i = 0; i < 2; ++i) std::swap(streams[i], other.streams[i]);
|
|
33
|
+
for (int i = 0; i < 4; ++i) std::swap(events[i], other.events[i]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
~CudaAsyncWorkspace()
|
|
37
|
+
{
|
|
38
|
+
if (device < 0) return;
|
|
39
|
+
int previous;
|
|
40
|
+
// During runtime shutdown CUDA may already be unavailable.
|
|
41
|
+
if (cudaGetDevice(&previous) != cudaSuccess) return;
|
|
42
|
+
if (previous != device && cudaSetDevice(device) != cudaSuccess) return;
|
|
43
|
+
for (auto stream : streams) {
|
|
44
|
+
if (stream) cudaStreamSynchronize(stream);
|
|
45
|
+
}
|
|
46
|
+
if (e) cudaFree(e);
|
|
47
|
+
if (r) cudaFree(r);
|
|
48
|
+
for (auto event : events) {
|
|
49
|
+
if (event) cudaEventDestroy(event);
|
|
50
|
+
}
|
|
51
|
+
for (auto stream : streams) {
|
|
52
|
+
if (stream) cudaStreamDestroy(stream);
|
|
53
|
+
}
|
|
54
|
+
if (previous != device) cudaSetDevice(previous);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static cudaError_t reserve(unsigned char*& pointer, size_t& capacity, size_t bytes)
|
|
58
|
+
{
|
|
59
|
+
if (bytes <= capacity) return cudaSuccess;
|
|
60
|
+
// The old workspace is idle. Release before growing to avoid holding
|
|
61
|
+
// both old and new allocations at peak memory usage.
|
|
62
|
+
if (pointer) {
|
|
63
|
+
cudaError_t error = cudaFree(pointer);
|
|
64
|
+
if (error != cudaSuccess) return error;
|
|
65
|
+
pointer = nullptr;
|
|
66
|
+
capacity = 0;
|
|
67
|
+
}
|
|
68
|
+
cudaError_t error = cudaMalloc(&pointer, bytes);
|
|
69
|
+
if (error == cudaSuccess) capacity = bytes;
|
|
70
|
+
return error;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
cudaError_t prepare(size_t e_bytes, size_t r_bytes)
|
|
74
|
+
{
|
|
75
|
+
for (auto& stream : streams) {
|
|
76
|
+
if (!stream) {
|
|
77
|
+
cudaError_t error = cudaStreamCreate(&stream);
|
|
78
|
+
if (error != cudaSuccess) return error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
for (auto& event : events) {
|
|
82
|
+
if (!event) {
|
|
83
|
+
cudaError_t error = cudaEventCreateWithFlags(&event, cudaEventDisableTiming);
|
|
84
|
+
if (error != cudaSuccess) return error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
cudaError_t error = reserve(e, e_capacity, e_bytes);
|
|
88
|
+
if (error != cudaSuccess) return error;
|
|
89
|
+
return reserve(r, r_capacity, r_bytes);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
class CudaAsyncCache {
|
|
94
|
+
std::mutex mutex_;
|
|
95
|
+
std::list<CudaAsyncWorkspace> idle_;
|
|
96
|
+
|
|
97
|
+
public:
|
|
98
|
+
// Retain at most one idle workspace and 64 MiB of staging per device.
|
|
99
|
+
// Oversized calls still run, but their workspace is released on return.
|
|
100
|
+
static constexpr size_t max_bytes = 64 * size_t(1024) * 1024;
|
|
101
|
+
|
|
102
|
+
void take(int device, CudaAsyncWorkspace& workspace)
|
|
103
|
+
{
|
|
104
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
105
|
+
for (auto it = idle_.begin(); it != idle_.end(); ++it) {
|
|
106
|
+
if (it->device == device) {
|
|
107
|
+
workspace.swap(*it);
|
|
108
|
+
idle_.erase(it);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
workspace.device = device;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
void put(CudaAsyncWorkspace& workspace)
|
|
116
|
+
{
|
|
117
|
+
if (workspace.e_capacity > max_bytes
|
|
118
|
+
|| workspace.r_capacity > max_bytes - workspace.e_capacity) return;
|
|
119
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
120
|
+
for (const auto& entry : idle_) {
|
|
121
|
+
if (entry.device == workspace.device) return;
|
|
122
|
+
}
|
|
123
|
+
// A cache miss must not turn a successful solver call into an error.
|
|
124
|
+
try {
|
|
125
|
+
idle_.emplace_back();
|
|
126
|
+
} catch (const std::bad_alloc&) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
idle_.back().swap(workspace);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
void clear(int device)
|
|
133
|
+
{
|
|
134
|
+
CudaAsyncWorkspace discarded;
|
|
135
|
+
{
|
|
136
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
137
|
+
for (auto it = idle_.begin(); it != idle_.end(); ++it) {
|
|
138
|
+
if (it->device == device) {
|
|
139
|
+
discarded.swap(*it);
|
|
140
|
+
idle_.erase(it);
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// CUDA calls happen outside the lock. Active calls own separate
|
|
146
|
+
// workspaces and may repopulate the cache after clear() returns.
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
inline CudaAsyncCache& cuda_async_cache()
|
|
151
|
+
{
|
|
152
|
+
static CudaAsyncCache cache;
|
|
153
|
+
return cache;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
#endif
|