Skip to content

Commit 5735be8

Browse files
authored
Merge pull request #156 from oesteban/fix/auto-lowmem-mode
ENH: Add a memory check to dynamically limit interpolation blocksize
2 parents 92350a2 + c13fde3 commit 5735be8

File tree

5 files changed

+46
-1
lines changed

5 files changed

+46
-1
lines changed

.github/workflows/travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ jobs:
5050
- name: Install minimal dependencies
5151
run: |
5252
$CONDA/bin/pip install -r min-requirements.txt
53-
$CONDA/bin/pip install .
5453
$CONDA/bin/pip install .[tests]
5554
5655
- uses: actions/cache@v2

sdcflows/interfaces/bspline.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ class Coefficients2Warp(SimpleInterface):
227227
output_spec = _Coefficients2WarpOutputSpec
228228

229229
def _run_interface(self, runtime):
230+
from ..utils.misc import get_free_mem
231+
230232
# Calculate the physical coordinates of target grid
231233
targetnii = nb.load(self.inputs.in_target)
232234
targetaff = targetnii.affine
@@ -237,11 +239,21 @@ def _run_interface(self, runtime):
237239
weights = []
238240
coeffs = []
239241
blocksize = LOW_MEM_BLOCK_SIZE if self.inputs.low_mem else len(points)
242+
240243
for cname in self.inputs.in_coeff:
241244
cnii = nb.load(cname)
242245
cdata = cnii.get_fdata(dtype="float32")
243246
coeffs.append(cdata.reshape(-1))
244247

248+
# Try to probe the free memory
249+
_free_mem = get_free_mem()
250+
suggested_blocksize = (
251+
int(np.round((_free_mem * 0.80) / (3 * 32 * cdata.size)))
252+
if _free_mem
253+
else blocksize
254+
)
255+
blocksize = min(blocksize, suggested_blocksize)
256+
245257
idx = 0
246258
block_w = []
247259
while True:

sdcflows/utils/misc.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,13 @@ def last(inlist):
3535
if isinstance(inlist, (list, tuple)):
3636
return inlist[-1]
3737
return inlist
38+
39+
40+
def get_free_mem():
41+
"""Probe the free memory right now."""
42+
try:
43+
from psutil import virtual_memory
44+
45+
return round(virtual_memory().free, 1)
46+
except Exception:
47+
return None

sdcflows/utils/tests/test_misc.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""Test miscellaneous utilities."""
2+
import sys
3+
from collections import namedtuple
4+
import types
5+
import pytest
6+
from ..misc import get_free_mem
7+
8+
9+
@pytest.mark.parametrize("retval", [None, 10])
10+
def test_get_free_mem(monkeypatch, retval):
11+
"""Test the get_free_mem utility."""
12+
13+
def mock_func():
14+
if retval is None:
15+
raise ImportError
16+
return namedtuple("Mem", ("free",))(free=retval)
17+
18+
psutil = types.ModuleType("psutil")
19+
psutil.virtual_memory = mock_func
20+
monkeypatch.setitem(sys.modules, "psutil", psutil)
21+
assert get_free_mem() == retval

setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ doc =
5656
sphinxcontrib-versioning
5757
docs =
5858
%(doc)s
59+
mem =
60+
psutil
5961
tests =
6062
pytest
6163
pytest-xdist >= 2.0
@@ -64,6 +66,7 @@ tests =
6466
coverage
6567
all =
6668
%(doc)s
69+
%(mem)s
6770
%(tests)s
6871

6972
[options.package_data]

0 commit comments

Comments
 (0)