Distributed Multi-Device Tuning¶
Status: coordinator, device agent, remote environment, SSH bootstrap, and CLI wiring implemented (Phases 0–5). Runs against a real fleet require identical devices reachable over a trusted network with SSH-key access.
Why this mode exists — fairness¶
In the default local mode every population worker runs as a co-tenant
PostgreSQL instance on one machine. The B1–B17 lockstep barriers
exist specifically to make noisy-neighbour contention identical across
workers — fairness by cancellation.
distributed mode assigns one worker per dedicated, identical device.
With no co-tenancy there is no contention to cancel, so fairness becomes
structural:
- No co-tenancy — one worker per device.
- Identical hardware — a config's score reflects the config, not the host.
- Byte-identical start state — each device holds its own base snapshot and resets to it before every evaluation.
- Local benchmark client — the benchmark runs on the device next to its DB, so no network latency ever enters the measurement window.
The existing local code paths are never modified; distributed mode is entirely
additive and selected with --distributed.
Topology¶
┌─────────────────────────────────────────────┐
│ COORDINATOR (control plane, 1 process) │
│ Population loop · evolution (exploit/explore) │
│ central CompositeScorer · generation barrier │
│ RemoteEnvironment ── HTTP/JSON RPC ──┐ │
└───────────────────────────────────────┼───────┘
┌───────────────┬───────────────┼───────────────┐
▼ ▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Device 0│ │ Device 1│ │ Device 2│ … │ Device N│
│ agent │ │ agent │ │ agent │ │ agent │
│ +1 PG │ │ +1 PG │ │ +1 PG │ │ +1 PG │
│ +bench │ │ +bench │ │ +bench │ │ +bench │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
- Coordinator runs the unchanged PBT algorithm. It only swaps two
components:
env→RemoteEnvironmentandorchestrator→RemoteWorkloadOrchestrator.Population,evolution, and the scorer are untouched. - Device agent (
src/tuners/distributed/device_agent.py) is a long-running HTTP/JSON server that owns one local PostgreSQL instance and runs today's realWorkloadOrchestratorpipeline locally, returning raw metrics. - Scoring is central. Devices return
PerformanceMetrics; the coordinator scores withengine.compute_breakdown, so adaptive normalisation spans the whole population exactly as in local mode.
Because there is no co-tenancy, distributed runs set
synchronize_workers=False: the B1–B17 substep barriers run locally on each
device, and the coordinator's only synchronisation point is the generation
boundary (the ThreadPoolExecutor join in Population.evaluate_generation).
Wire protocol¶
JSON over HTTP (stdlib only — no web framework), defined in
src/tuners/distributed/agent_api.py:
| Route | Purpose |
|---|---|
GET /health |
Liveness + protocol/version + hardware handshake |
POST /setup |
Stand up the device's single local PG instance |
POST /snapshot |
Create the device's local base snapshot |
POST /reset |
Restore data to the local base snapshot (exploit target) |
POST /run_eval |
Run one apply→run→measure locally; return raw metrics |
POST /cleanup |
Tear down the instance |
POST /shutdown |
Stop the agent |
Config-only exploit clone¶
PBT exploit copies an elite worker onto poor workers. Across devices this is
config-only: the elite's knobs are copied in coordinator RAM by the
evolution step (tiny), and RemoteEnvironment.clone_instances merely tells each
target device to /reset its data to the byte-identical local baseline. No
gigabyte-scale PGDATA is transferred over the network.
Fleet inventory¶
Devices are described by a devices.yaml (see
configs/distributed/devices.example.yaml). Devices are bound to workers by
list order (device 0 → worker 0). The fleet must have at least --population
devices.
fleet:
agent_port: 8770
ssh_user: pbt
ssh_key: ~/.ssh/id_rsa
data_dir: /var/lib/pbt
python: python3
devices:
- host: 10.0.0.11
- host: 10.0.0.12
- host: 10.0.0.13
- host: 10.0.0.14
Bootstrap (SSH)¶
src/tuners/distributed/bootstrap.py provisions each device: rsync the repo,
optionally pip install -r requirements.txt, then launch the agent detached
(nohup, recording a pidfile + logfile). Teardown stops each agent via its
pidfile. Command construction is pure/unit-tested; execution is a thin
subprocess wrapper.
Usage¶
# Distributed run (tool bootstraps the fleet, then tunes)
python -m src.tuners.pbt --distributed \
--inventory configs/distributed/devices.example.yaml \
--benchmark sysbench --tier core --config standard --population 4
# Agents already running (skip SSH bootstrap)
python -m src.tuners.pbt --distributed --inventory devices.yaml --no-bootstrap ...
# Run a device agent by hand (for debugging on one box)
python -m src.tuners.distributed.device_agent --worker-id 0 --port 8770 \
--knob-tier core --base-dir ./.instances
Relevant flags: --distributed, --inventory, --no-bootstrap,
--no-remote-deps, --eval-timeout, --agent-timeout.
Fault handling¶
A run_eval RPC timeout or transport error is treated as a dead worker: the
worker gets a failure metric and is handed to the standard population rescue
path (resample / config-clone). Recovery re-runs /setup on the device.
Assumptions & current limitations¶
- Identical hardware fleet. Heterogeneous fleets are out of scope. Note the
coordinator itself can be any light machine: agents report their detected
WorkerResourcesfrom/setupand the coordinator resolves hardware-aware knob ranges against device hardware (see_resolve_device_hardware_rangesinsrc/tuners/pbt/tuner.py), not its own.--worker-ram/--worker-cpusremain a manual override if no device reports resources. - Version-based knob pruning is skipped in distributed mode (the coordinator has no direct TCP path to remote instances); it relies on the identical-fleet assumption that every device runs the same PostgreSQL.
- Synchronized measurement windows are approximated by an agent-side "don't start before epoch" gate; a full two-phase prepare→go protocol (to align the measurement sub-window rather than the eval start) is future work.
LocalDeviceBackendwiressysbenchandtpch; custom-workload wiring is a markedNotImplementedError.- Trusted network + SSH-key access; secrets pass via SSH, never the repo.
Code map¶
| File | Role |
|---|---|
src/tuners/distributed/inventory.py |
Parse/validate devices.yaml |
src/tuners/distributed/config.py |
ExecutionMode, DistributedConfig |
src/tuners/distributed/agent_api.py |
Wire schemas |
src/tuners/distributed/transport.py |
Stdlib HTTP client + server helpers |
src/tuners/distributed/device_agent.py |
Device HTTP server + LocalDeviceBackend |
src/tuners/distributed/remote_environment.py |
DatabaseEnvironment RPC proxy |
src/tuners/distributed/remote_orchestrator.py |
RPC eval + central scoring |
src/tuners/distributed/coordinator.py |
Client mgmt, health handshake, factories |
src/tuners/distributed/bootstrap.py |
SSH provisioning + agent launch/teardown |