Skip to content

Memory aware scheduling - #357

Merged
sjoelund merged 2 commits into
masterfrom
memory-aware-scheduling
Sep 8, 2026
Merged

Memory aware scheduling#357
sjoelund merged 2 commits into
masterfrom
memory-aware-scheduling

Conversation

@sjoelund

@sjoelund sjoelund commented Sep 8, 2026

Copy link
Copy Markdown
Member

No description provided.

The 2026-09-08 wasm-jit run took the machine out of memory: peak
104.9 GiB, 19176 OOM kills, 5856 models at finalphase 0 where every
earlier run had ~894, and 202 killed at their timeout where no earlier
run had any. Two causes, neither visible in `maxrss`.

A job that runs into the outer timeout is killed by its process group,
and OMPython starts omc with `preexec_fn=os.setsid`, so omc is in a
session of its own and never gets the signal. testmodel.py, which does
find omc through psutil, is dead by then. Each timeout therefore leaks a
running omc for the rest of the run. test.py now takes the descendants
before it kills the parent and kills them after, and testmodel.py
handles SIGTERM: it writes the result file and takes its children with
it, inside the ten seconds before the SIGKILL.

The 16 jobs also ran with no regard for what they need. Summing the
largest measurement each model has, over the newest runs of master,
wasm-jit, cpp and newInst-newBackend:

  | scheduling            | peak concurrent | wall  |
  |-----------------------|-----------------|-------|
  | as before             |         121 GiB | 3.18h |
  | >=4 GiB capped at 4   |        62.7 GiB | 3.18h |

The cap is free because the heavy models are 148 of 19800: `runCapped`
keeps two queues, and a worker that may not start a heavy job takes a
light one instead of waiting for a slot. Only when heavy jobs are all
that is left does anyone wait.

`configs/heavy-models.json` is that list, meant to be read and edited
rather than regenerated: a model that dies early on one branch reports
what it reached, not what it wants, and the 33 entries that stopped at
exactly 7.01 GiB are sitting on the 8 GB `ulimit -v`. heavy-models.py
proposes it and says which entries those are.

Children also get oom_score_adj 1000, so that the kernel takes omc and
leaves python to report the phase it had reached. Raising a child is
allowed unprivileged; lowering ourselves is not.

Assisted-by: Claude Opus 5 (1M context)
A run of `--wasmjitrunner` or `--fmisimulator` is one job filling
several tables under one date: wasm-jit, wasm-jit-me and wasm-jit-cs.
Removing a bad run a table at a time leaves the siblings describing a
run that no longer exists, and the rows in omcversion and libversion
behind either way.

`remove-run.py` takes the branch, finds the newest run of it (or the one
`--date`/`--omcversion` names), and deletes from every table of that
date at once. It prints what it would delete and does nothing until it
is given `--write`, then reads the counts back to check.

  ./remove-run.py --db postgresql://om@localhost/omdb wasm-jit
  ./remove-run.py --db postgresql://om@localhost/omdb wasm-jit --write

Siblings are found by name and skipped when they have no rows of that
date; `--also` names a table the prefix does not reach, which is how the
`--solver` runners are stored.

job_claim is left alone. Its rows say who tested a library last, the
next run overwrites them, and a claim that is not running blocks
nothing.

Assisted-by: Claude Opus 5 (1M context)
@sjoelund
sjoelund enabled auto-merge (rebase) September 8, 2026 18:41
@sjoelund
sjoelund merged commit 6753c3a into master Sep 8, 2026
7 checks passed
@sjoelund
sjoelund deleted the memory-aware-scheduling branch September 8, 2026 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant