Skip to content

feat(cli): preflight host resource limits before workers (#234) - #320

Closed
Inoriac wants to merge 7 commits into
inclusionAI:mainfrom
Inoriac:feat/host-resource-preflight-234
Closed

feat(cli): preflight host resource limits before workers (#234)#320
Inoriac wants to merge 7 commits into
inclusionAI:mainfrom
Inoriac:feat/host-resource-preflight-234

Conversation

@Inoriac

@Inoriac Inoriac commented Jul 28, 2026

Copy link
Copy Markdown

What

Adds a preflight that reads host file-descriptor, process-count, and
shared-memory limits before areno train / areno serve spawn worker
ranks, compares them against a documented demand estimate for
world_size/tp_size, and reports normal / warning / blocking severities
without changing the host.

Closes #234. Follows my initial sketch in the issue: reuse AReno's existing
preflight paradigm, probe limits via the stdlib, estimate demand from
concurrency scale, and report severities with the specific delta and
remediation guidance.

How

Reuses the existing diagnostics CheckResult(status, name, detail, next_step)
severity model (OK/WARN/FAIL) rather than introducing a parallel subsystem.

Probes (areno/cli/diagnostics.py:collect_host_limits):

  • file descriptors — resource.getrlimit(RLIMIT_NOFILE)
  • process count — resource.getrlimit(RLIMIT_NPROC)
  • shared memory — /proc/sys/kernel/shmmax (Linux)

Demand estimate (estimate_resource_demand, conservative upper bound):

  • fds: 64 * world_size + world_size * (world_size - 1)
  • processes: world_size + 1
  • shm: 1 GiB * tp_size

New CLI option --resource-check {skip,warn,block} on both train and
serve, default warn:

  • warn (default) — emit a stderr diagnostic only when a probed limit is
    below demand, then continue. Never aborts. Existing stdout / runs are
    unchanged.
  • block — raise UsageError and abort before any worker starts on a
    below-demand probe.
  • skip — disable.

Severities:

  • OK — observed meets demand. RLIM_INFINITY counts as meeting demand.
  • WARN — probe unavailable on this platform (e.g. macOS/Windows have no
    /proc/sys/kernel/shmmax). Never blocks, even under block.
  • FAIL — observed below demand; detail carries exact
    observed/required/delta and a remediation hint
    (ulimit -n 65536, sudo sysctl -w kernel.shmmax=...).

Backward compatibility: preflight output goes to stderr and is only
printed on a FAIL, so stdout (including the machine-parsed config summary) is
byte-for-byte unchanged on the success path; existing CLI behavior is
preserved under the default.

No new dependencies, no config-dataclass changes (the option lives at the CLI
layer with explicit inputs), no external database/sandbox.

Testing

New tests/test_resource_preflight_cpu.py (16 cases, all in -k cpu) covers

  • demand formula + non-positive-scale rejection
  • success path with injected ample limits (asserts exact observed/required/delta)
  • boundary (observed == required → OK)
  • failure: low fd → FAIL + delta + ulimit -n; low shm → FAIL + kernel.shmmax
  • RLIM_INFINITY → OK (not unavailable)
  • unavailable probe → WARN, non-blocking even under block
  • should_block_on_resources counts only FAIL
  • policy validation + format rendering
  • train/serve CLI integration: default warn does not abort on FAIL; block
    aborts before run()/create_app(); skip does not invoke the probe

Full CPU suite green: pytest tests/ -k cpu370 passed, no regression
in test_cli_diagnostics_cpu.py / test_train_cli_config_cpu.py /
test_serve_cli_cpu.py.

GPU train/serve launch not exercised here (requires CUDA); orchestration logic
is covered via CPU tests + mocks.

Issue #234 acceptance

  • Test with injected limit values, include exact observed/required values
    and adjustment guidance; degrade cleanly on platforms without a probe.
  • Uses existing AReno contracts (CheckResult); no external DB or sandbox.
  • Default behavior backward compatible (stderr-only, FAIL-only, never
    aborts; stdout unchanged).
  • Focused automated tests cover success, invalid input, and a
    boundary/failure path.
  • User docs include a minimal runnable example and explain observable
    output (docs/cli/diagnostics.rst, training.rst, inference.rst).

Commit history

  • feat(cli): preflight host resource limits before workers
  • docs(cli): document host resource preflight option

Huang and others added 2 commits July 28, 2026 14:52
Probe file-descriptor (RLIMIT_NOFILE), process-count (RLIMIT_NPROC), and
shared-memory (kernel.shmmax) limits via the stdlib and compare them against
a documented demand estimate for world_size/tp_size before train/serve spawn
workers. Reuse the diagnostics CheckResult severity model.

Add --resource-check {skip,warn,block} to train and serve with a safe warn
default: emit a stderr diagnostic only on a FAIL and never abort, so existing
runs and stdout stay backward compatible; block aborts before worker init on
a below-demand probe. Probes unavailable on a platform (e.g. macOS shmmax)
degrade to a non-blocking WARN; RLIM_INFINITY counts as meeting demand.

Co-Authored-By: Claude <noreply@anthropic.com>
Describe the --resource-check option on train and serve, the fd/process/shm
probe contract, the demand estimate, OK/WARN/FAIL severities, output fields,
platform degradation, and a minimal runnable example covering success and a
boundary failure path.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 28, 2026 09:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a host “resource preflight” to areno train / areno serve that probes fd / process / shared-memory limits before spawning worker ranks, compares them to an estimated demand for world_size / tp_size, and reports via the existing CheckResult OK/WARN/FAIL model (with optional blocking via a new CLI flag).

Changes:

  • Introduces host limit probing + demand estimation + rendering utilities in areno/cli/diagnostics.py.
  • Wires a new --resource-check {skip,warn,block} option into both areno train and areno serve pre-init flows.
  • Adds CPU tests and user documentation describing the new checks, policies, and output.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
areno/cli/diagnostics.py Adds limit probes, demand estimation, CheckResult generation, and formatting helpers for the resource preflight.
areno/cli/train.py Adds --resource-check option and runs the preflight before model/backend init in the training CLI.
areno/cli/serve.py Adds --resource-check option and runs the preflight before model resolution / app creation in the serving CLI.
tests/test_resource_preflight_cpu.py Adds deterministic CPU tests for demand math, severity mapping, formatting, and train/serve wiring via mocks.
docs/cli/diagnostics.rst Documents probes, policies, severities, and example output for the resource preflight.
docs/cli/training.rst Documents the new --resource-check option for areno train.
docs/cli/inference.rst Documents the new --resource-check option for areno serve.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread areno/cli/diagnostics.py
Comment on lines +598 to +616
- file descriptors: per-worker base plus one socket per cross-rank peer for
the NCCL/tensor-parallel mesh; sum across all `world_size` workers.
- processes: `world_size` worker ranks plus the driver process.
- shared memory: baseline per tensor-parallel group, scaled by `tp_size`.

The estimate is intentionally conservative -- it triggers a warning rather
than undershooting a real NCCL/CUDA IPC requirement mid-run.
"""

if world_size < 1:
raise ValueError("world_size must be >= 1")
if tp_size < 1:
raise ValueError("tp_size must be >= 1")
cross_rank_peers = world_size * (world_size - 1)
return {
"file_descriptors": _BASE_FDS_PER_WORKER * world_size + cross_rank_peers,
"processes": world_size + 1,
"shared_memory": _SHM_BASELINE_BYTES * tp_size,
}
Comment thread areno/cli/diagnostics.py
Comment on lines +638 to +642
if policy not in {"skip", "warn", "block"}:
raise ValueError(f"resource-check policy must be skip/warn/block, got {policy!r}")
if limits is None:
limits = collect_host_limits()
demand = estimate_resource_demand(world_size, tp_size)
Comment thread areno/cli/diagnostics.py
Comment on lines +670 to +677
def _shmmax_result(observed: dict[str, Any], required: int) -> CheckResult:
return _resource_result(
observed,
required,
name="shared memory (kernel.shmmax)",
unit=" bytes",
adjust="raise the system limit, e.g. `sudo sysctl -w kernel.shmmax=<required>`",
)
Huang and others added 5 commits July 28, 2026 17:42
Address review feedback on the host-resource preflight:

- estimate_resource_demand: fd demand was summed across the whole fleet
  (_BASE_FDS_PER_WORKER * world + world*(world-1)) but compared against
  RLIMIT_NOFILE, which is a per-process limit. Use the per-process demand
  (base + (world_size - 1) peers) instead. The processes estimate stays as
  the fleet total since RLIMIT_NPROC is per-user. This removes false FAILs
  / spurious ulimit guidance at larger world_size.
- preflight_host_resources: short-circuit on policy="skip" without probing
  the host, so the function's skip semantics match its callers.
- _shmmax_result: interpolate the concrete required value into the sysctl
  remediation hint instead of leaving a <required> placeholder.

Tests updated for the new fd formula and the shm hint; added a case
asserting skip never touches collect_host_limits.

Co-Authored-By: Claude <noreply@anthropic.com>
- serve.py: reorder diagnostics import ahead of model_refs (I001)
- test_resource_preflight_cpu.py: drop unused `result` binding (F841),
  add trailing newline (W292)

No behavior change; ruff check passes clean on the changed files.

Co-Authored-By: Claude <noreply@anthropic.com>
Wrap the over-long _limits(...) call across multiple lines to satisfy
ruff-format. Auto-applied by pre-commit run --all-files.

Co-Authored-By: Claude <noreply@anthropic.com>
…preflight-234

# Conflicts:
#	areno/cli/serve.py
@xsuler xsuler closed this Sep 4, 2026
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.

Preflight host resource limits for multi-process runs

3 participants