Source code for spacr.sweep_child
"""Run one regression trial in a fresh worker process.
python -m spacr.sweep_child <settings.json> <result.json>
The parent may place this process in a kernel-enforced resource scope. Thread
limits are set before NumPy imports so BLAS libraries initialize with one
thread per trial. Results and failures are returned through a JSON file,
including when no in-memory return value is available.
"""
import os
for _variable in ("OMP_NUM_THREADS", "MKL_NUM_THREADS", "OPENBLAS_NUM_THREADS",
"NUMEXPR_NUM_THREADS", "VECLIB_MAXIMUM_THREADS"):
os.environ.setdefault(_variable, "1")
try:
with open(f"/proc/{os.getpid()}/oom_score_adj", "w") as _handle:
_handle.write("800")
except OSError:
pass
import json # noqa: E402
import sys # noqa: E402
import time # noqa: E402
import traceback # noqa: E402
[docs]
def main(argv=None) -> int:
"""Run one sweep trial in this process and write its result as JSON.
Parameters
----------
argv : sequence of str, optional
Settings and output JSON paths. Defaults to ``sys.argv[1:]``.
Returns
-------
int
``0`` once a result document was written, including when that document
reports a failed trial, or ``2`` when the argument count is invalid.
Raises
------
OSError
If the settings document cannot be read or the result document cannot
be written.
json.JSONDecodeError
If the settings document is not valid JSON.
"""
argv = list(sys.argv[1:] if argv is None else argv)
if len(argv) != 2:
print("usage: python -m spacr.sweep_child <settings.json> <out.json>",
file=sys.stderr)
return 2
settings_path, out_path = argv
with open(settings_path) as handle:
payload = json.load(handle)
settings = payload.get("settings", payload)
trial_id = payload.get("trial_id")
from .fit_resources import _worker_stamp
result = {
"status": "failed",
"trial_id": trial_id,
"_resource_worker": _worker_stamp(
"parameter_sweep_trial", trial_id),
}
began = time.time()
try:
import matplotlib
matplotlib.use("Agg")
from .parameter_sweep import _pin_threads
_pin_threads()
from .figure_font import _open_sans_if_a_run_started_this
from .ml import perform_regression
with _open_sans_if_a_run_started_this():
output = perform_regression(dict(settings))
result["status"] = "ok"
from .trial_metrics import summarise_trial
result.update(summarise_trial(output, settings))
controls = payload.get("controls") or {}
if controls:
try:
import pandas as pd
from .parameter_sweep import _named_control_rows
results = output.get("results") \
if hasattr(output, "get") else None
if isinstance(results, pd.DataFrame):
result.update(_named_control_rows(results, controls))
except Exception: # noqa: BLE001 - an alias must not sink a trial
pass
except BaseException as error: # noqa: BLE001 - a failed trial is a result
from .runctx import _is_overload_failure
result["status"] = "failed"
result["_overload"] = _is_overload_failure(error)
result["error_type"] = type(error).__name__
result["error"] = (str(error).splitlines() or [""])[0][:400]
folder = settings.get("src")
if folder:
try:
with open(os.path.join(folder, "error.txt"), "w",
encoding="utf-8") as handle:
handle.write(traceback.format_exc())
except OSError:
pass
result["seconds"] = round(time.time() - began, 2)
with open(out_path, "w") as handle:
json.dump(result, handle, indent=2, default=str)
return 0
if __name__ == "__main__":
raise SystemExit(main())