I changed prep_utils.py (line 266) so every ANTs subprocess now sets:
Browse filesITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS
OMP_NUM_THREADS
OMP_THREAD_LIMIT
- README.md +5 -0
- src/data_prep/prep_utils.py +41 -0
README.md
CHANGED
|
@@ -38,6 +38,11 @@ These defaults can be overridden with:
|
|
| 38 |
- `HF_RUNTIME_REPO_ID`
|
| 39 |
- `HF_RUNTIME_REVISION`
|
| 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
## Experimental Mask Editor
|
| 42 |
|
| 43 |
An isolated post-segmentation mask editor scaffold is available behind the
|
|
|
|
| 38 |
- `HF_RUNTIME_REPO_ID`
|
| 39 |
- `HF_RUNTIME_REVISION`
|
| 40 |
|
| 41 |
+
Registration threading can be controlled with:
|
| 42 |
+
|
| 43 |
+
- `PREP_ANTS_THREADS` to set the exact ANTs/ITK thread count
|
| 44 |
+
- `PREP_ANTS_THREAD_CAP` to cap the automatic count (default: `8`)
|
| 45 |
+
|
| 46 |
## Experimental Mask Editor
|
| 47 |
|
| 48 |
An isolated post-segmentation mask editor scaffold is available behind the
|
src/data_prep/prep_utils.py
CHANGED
|
@@ -263,12 +263,52 @@ def _command_timeout_seconds() -> int | None:
|
|
| 263 |
return None if seconds <= 0 else seconds
|
| 264 |
|
| 265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 266 |
def _run(cmd: list[str]):
|
| 267 |
cmd_str = " ".join(map(str, cmd))
|
| 268 |
timeout_sec = _command_timeout_seconds()
|
| 269 |
timeout_label = f"{timeout_sec}s" if timeout_sec is not None else "disabled"
|
|
|
|
|
|
|
| 270 |
print(">>", cmd_str)
|
| 271 |
print(f"[cmd] timeout={timeout_label}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 272 |
t0 = time.monotonic()
|
| 273 |
try:
|
| 274 |
res = subprocess.run(
|
|
@@ -277,6 +317,7 @@ def _run(cmd: list[str]):
|
|
| 277 |
stderr=subprocess.STDOUT,
|
| 278 |
text=True,
|
| 279 |
timeout=timeout_sec,
|
|
|
|
| 280 |
)
|
| 281 |
except subprocess.TimeoutExpired as exc:
|
| 282 |
elapsed = time.monotonic() - t0
|
|
|
|
| 263 |
return None if seconds <= 0 else seconds
|
| 264 |
|
| 265 |
|
| 266 |
+
def _available_cpu_count() -> int:
|
| 267 |
+
try:
|
| 268 |
+
return max(1, len(os.sched_getaffinity(0)))
|
| 269 |
+
except Exception:
|
| 270 |
+
return max(1, os.cpu_count() or 1)
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
def _ants_thread_count() -> int:
|
| 274 |
+
raw = os.environ.get("PREP_ANTS_THREADS", "").strip()
|
| 275 |
+
if raw:
|
| 276 |
+
try:
|
| 277 |
+
return max(1, int(float(raw)))
|
| 278 |
+
except ValueError:
|
| 279 |
+
print(f"[setup] invalid PREP_ANTS_THREADS={raw!r}; using automatic thread count")
|
| 280 |
+
|
| 281 |
+
cap_raw = os.environ.get("PREP_ANTS_THREAD_CAP", "8").strip()
|
| 282 |
+
try:
|
| 283 |
+
cap = max(1, int(float(cap_raw)))
|
| 284 |
+
except ValueError:
|
| 285 |
+
print(f"[setup] invalid PREP_ANTS_THREAD_CAP={cap_raw!r}; using 8")
|
| 286 |
+
cap = 8
|
| 287 |
+
return max(1, min(_available_cpu_count(), cap))
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
def _subprocess_env() -> dict[str, str]:
|
| 291 |
+
env = os.environ.copy()
|
| 292 |
+
threads = str(_ants_thread_count())
|
| 293 |
+
env["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"] = threads
|
| 294 |
+
env["OMP_NUM_THREADS"] = threads
|
| 295 |
+
env["OMP_THREAD_LIMIT"] = threads
|
| 296 |
+
return env
|
| 297 |
+
|
| 298 |
+
|
| 299 |
def _run(cmd: list[str]):
|
| 300 |
cmd_str = " ".join(map(str, cmd))
|
| 301 |
timeout_sec = _command_timeout_seconds()
|
| 302 |
timeout_label = f"{timeout_sec}s" if timeout_sec is not None else "disabled"
|
| 303 |
+
env = _subprocess_env()
|
| 304 |
+
threads = env["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"]
|
| 305 |
print(">>", cmd_str)
|
| 306 |
print(f"[cmd] timeout={timeout_label}")
|
| 307 |
+
print(
|
| 308 |
+
f"[cmd] ants_threads={threads} "
|
| 309 |
+
f"available_cpus={_available_cpu_count()} "
|
| 310 |
+
f"thread_cap={os.environ.get('PREP_ANTS_THREAD_CAP', '8')}"
|
| 311 |
+
)
|
| 312 |
t0 = time.monotonic()
|
| 313 |
try:
|
| 314 |
res = subprocess.run(
|
|
|
|
| 317 |
stderr=subprocess.STDOUT,
|
| 318 |
text=True,
|
| 319 |
timeout=timeout_sec,
|
| 320 |
+
env=env,
|
| 321 |
)
|
| 322 |
except subprocess.TimeoutExpired as exc:
|
| 323 |
elapsed = time.monotonic() - t0
|