ensemble-launcher 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ensemble_launcher-0.1.0/.github/workflows/pages.yml +42 -0
- ensemble_launcher-0.1.0/.github/workflows/tests.yml +39 -0
- ensemble_launcher-0.1.0/.gitignore +12 -0
- ensemble_launcher-0.1.0/CLAUDE.md +104 -0
- ensemble_launcher-0.1.0/LICENSE +29 -0
- ensemble_launcher-0.1.0/PKG-INFO +94 -0
- ensemble_launcher-0.1.0/README.md +43 -0
- ensemble_launcher-0.1.0/assets/el.png +0 -0
- ensemble_launcher-0.1.0/benchmarks/benchmark_comm.py +398 -0
- ensemble_launcher-0.1.0/benchmarks/benchmark_latency.py +193 -0
- ensemble_launcher-0.1.0/benchmarks/benchmark_pool.py +76 -0
- ensemble_launcher-0.1.0/benchmarks/benchmark_uv.py +47 -0
- ensemble_launcher-0.1.0/benchmarks/benchmark_zero_copy.py +127 -0
- ensemble_launcher-0.1.0/benchmarks/latency_results.csv +3 -0
- ensemble_launcher-0.1.0/benchmarks/utils.py +9 -0
- ensemble_launcher-0.1.0/docs/docs/api-reference.md +155 -0
- ensemble_launcher-0.1.0/docs/docs/architecture.md +93 -0
- ensemble_launcher-0.1.0/docs/docs/cli.md +69 -0
- ensemble_launcher-0.1.0/docs/docs/cluster-mode.md +101 -0
- ensemble_launcher-0.1.0/docs/docs/configuration.md +186 -0
- ensemble_launcher-0.1.0/docs/docs/contributing.md +56 -0
- ensemble_launcher-0.1.0/docs/docs/custom-scheduling.md +148 -0
- ensemble_launcher-0.1.0/docs/docs/examples.md +175 -0
- ensemble_launcher-0.1.0/docs/docs/experimental/actors.md +122 -0
- ensemble_launcher-0.1.0/docs/docs/experimental/inference.md +153 -0
- ensemble_launcher-0.1.0/docs/docs/experimental/mcp.md +103 -0
- ensemble_launcher-0.1.0/docs/docs/index.md +43 -0
- ensemble_launcher-0.1.0/docs/docs/installation.md +69 -0
- ensemble_launcher-0.1.0/docs/docs/quickstart.md +80 -0
- ensemble_launcher-0.1.0/docs/mkdocs.yml +65 -0
- ensemble_launcher-0.1.0/ensemble_launcher/__init__.py +4 -0
- ensemble_launcher-0.1.0/ensemble_launcher/checkpointing/__init__.py +15 -0
- ensemble_launcher-0.1.0/ensemble_launcher/checkpointing/checkpointer.py +482 -0
- ensemble_launcher-0.1.0/ensemble_launcher/cli.py +95 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/__init__.py +72 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/async_base.py +971 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/async_zmq.py +908 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/base.py +294 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/dragon.py +388 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/hb.py +311 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/messages.py +629 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/mp.py +124 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/nodeinfo.py +20 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/__init__.py +47 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/async_connection.py +630 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/async_transport.py +273 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/mp_connection.py +106 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/mp_transport.py +99 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/registry.py +45 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/utils.py +24 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/queue/__init__.py +2 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/queue/protocol.py +16 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/queue/registry.py +36 -0
- ensemble_launcher-0.1.0/ensemble_launcher/comm/zmq.py +254 -0
- ensemble_launcher-0.1.0/ensemble_launcher/config/__init__.py +19 -0
- ensemble_launcher-0.1.0/ensemble_launcher/config/config.py +138 -0
- ensemble_launcher-0.1.0/ensemble_launcher/config/mpi_config.py +193 -0
- ensemble_launcher-0.1.0/ensemble_launcher/ensemble/__init__.py +3 -0
- ensemble_launcher-0.1.0/ensemble_launcher/ensemble/actor.py +851 -0
- ensemble_launcher-0.1.0/ensemble_launcher/ensemble/actor_pool.py +213 -0
- ensemble_launcher-0.1.0/ensemble_launcher/ensemble/ensemble.py +394 -0
- ensemble_launcher-0.1.0/ensemble_launcher/ensemble_launcher.py +208 -0
- ensemble_launcher-0.1.0/ensemble_launcher/executors/__init__.py +5 -0
- ensemble_launcher-0.1.0/ensemble_launcher/executors/async_mp_executor.py +277 -0
- ensemble_launcher-0.1.0/ensemble_launcher/executors/async_mpi_executor.py +602 -0
- ensemble_launcher-0.1.0/ensemble_launcher/executors/async_mpi_pool_executor.py +357 -0
- ensemble_launcher-0.1.0/ensemble_launcher/executors/base.py +46 -0
- ensemble_launcher-0.1.0/ensemble_launcher/executors/dragon_executor.py +230 -0
- ensemble_launcher-0.1.0/ensemble_launcher/executors/mp_executor.py +101 -0
- ensemble_launcher-0.1.0/ensemble_launcher/executors/mpi_executor.py +215 -0
- ensemble_launcher-0.1.0/ensemble_launcher/executors/mpi_pool.py +309 -0
- ensemble_launcher-0.1.0/ensemble_launcher/executors/utils.py +238 -0
- ensemble_launcher-0.1.0/ensemble_launcher/helper_functions.py +100 -0
- ensemble_launcher-0.1.0/ensemble_launcher/inference/__init__.py +13 -0
- ensemble_launcher-0.1.0/ensemble_launcher/inference/configs.py +28 -0
- ensemble_launcher-0.1.0/ensemble_launcher/inference/copy_model.py +302 -0
- ensemble_launcher-0.1.0/ensemble_launcher/inference/openai_inference.py +68 -0
- ensemble_launcher-0.1.0/ensemble_launcher/inference/start_vllm_server.sh +104 -0
- ensemble_launcher-0.1.0/ensemble_launcher/inference/utils.py +255 -0
- ensemble_launcher-0.1.0/ensemble_launcher/inference/vllm_inference.py +1516 -0
- ensemble_launcher-0.1.0/ensemble_launcher/logging/__init__.py +63 -0
- ensemble_launcher-0.1.0/ensemble_launcher/loop.py +4 -0
- ensemble_launcher-0.1.0/ensemble_launcher/mcp/__init__.py +2 -0
- ensemble_launcher-0.1.0/ensemble_launcher/mcp/interface.py +414 -0
- ensemble_launcher-0.1.0/ensemble_launcher/mcp/utils.py +200 -0
- ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/__init__.py +67 -0
- ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/async_master.py +2089 -0
- ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/async_worker.py +1216 -0
- ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/async_workstealing_master.py +269 -0
- ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/async_workstealing_worker.py +162 -0
- ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/cluster_client.py +572 -0
- ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/master.py +589 -0
- ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/node.py +55 -0
- ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/utils.py +97 -0
- ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/worker.py +383 -0
- ensemble_launcher-0.1.0/ensemble_launcher/profiling/__init__.py +5 -0
- ensemble_launcher-0.1.0/ensemble_launcher/profiling/event_registry.py +886 -0
- ensemble_launcher-0.1.0/ensemble_launcher/profiling/merge_traces.py +156 -0
- ensemble_launcher-0.1.0/ensemble_launcher/scheduler/__init__.py +22 -0
- ensemble_launcher-0.1.0/ensemble_launcher/scheduler/async_scheduler.py +1217 -0
- ensemble_launcher-0.1.0/ensemble_launcher/scheduler/child_state.py +10 -0
- ensemble_launcher-0.1.0/ensemble_launcher/scheduler/policy.py +625 -0
- ensemble_launcher-0.1.0/ensemble_launcher/scheduler/resource/__init__.py +9 -0
- ensemble_launcher-0.1.0/ensemble_launcher/scheduler/resource/cluster.py +305 -0
- ensemble_launcher-0.1.0/ensemble_launcher/scheduler/resource/node.py +417 -0
- ensemble_launcher-0.1.0/ensemble_launcher/scheduler/scheduler.py +255 -0
- ensemble_launcher-0.1.0/ensemble_launcher/scheduler/state.py +107 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/conftest.py +7 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/ensembles.json +10 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/py_echo.py +12 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/start_mcp.py +83 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_actor.py +383 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_actor_pool.py +355 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_async_comm.py +382 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_async_executor.py +47 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_async_master.py +130 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_async_worker.py +338 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_async_workstealing_master.py +124 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_cluster.py +245 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_connections.py +504 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_el.py +37 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_ensemble_launcher.py +98 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_fault_tolerance.py +108 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_mcp.py +169 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_resource_manager.py +63 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_scheduler.py +64 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_ser_deser.py +775 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/test_vllm.py +720 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/time_execution.py +53 -0
- ensemble_launcher-0.1.0/ensemble_launcher/tests/utils.py +40 -0
- ensemble_launcher-0.1.0/ensemble_launcher.egg-info/PKG-INFO +94 -0
- ensemble_launcher-0.1.0/ensemble_launcher.egg-info/SOURCES.txt +150 -0
- ensemble_launcher-0.1.0/ensemble_launcher.egg-info/dependency_links.txt +1 -0
- ensemble_launcher-0.1.0/ensemble_launcher.egg-info/entry_points.txt +2 -0
- ensemble_launcher-0.1.0/ensemble_launcher.egg-info/requires.txt +34 -0
- ensemble_launcher-0.1.0/ensemble_launcher.egg-info/top_level.txt +1 -0
- ensemble_launcher-0.1.0/examples/agents/pydantic/README.md +78 -0
- ensemble_launcher-0.1.0/examples/agents/pydantic/agents.py +123 -0
- ensemble_launcher-0.1.0/examples/agents/pydantic/joke_generator.py +81 -0
- ensemble_launcher-0.1.0/examples/agents/pydantic/utils.py +27 -0
- ensemble_launcher-0.1.0/examples/batch/mixed_workload.py +47 -0
- ensemble_launcher-0.1.0/examples/batch/python_tasks.py +26 -0
- ensemble_launcher-0.1.0/examples/batch/shell_tasks.py +21 -0
- ensemble_launcher-0.1.0/examples/cluster/cluster_mode.py +72 -0
- ensemble_launcher-0.1.0/examples/cluster/cluster_shell_tasks.py +45 -0
- ensemble_launcher-0.1.0/examples/mcp/combustion/README.md +38 -0
- ensemble_launcher-0.1.0/examples/mcp/combustion/flamespeed.py +33 -0
- ensemble_launcher-0.1.0/examples/mcp/combustion/start_mcp_http.py +41 -0
- ensemble_launcher-0.1.0/examples/python/mpi_example.py +58 -0
- ensemble_launcher-0.1.0/examples/python/serial_example.py +41 -0
- ensemble_launcher-0.1.0/pyproject.toml +59 -0
- ensemble_launcher-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Deploy docs to GitHub Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, stage_release]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: "pages"
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
- name: Install MkDocs
|
|
26
|
+
run: pip install mkdocs-material
|
|
27
|
+
- name: Build site
|
|
28
|
+
run: mkdocs build --config-file mkdocs.yml
|
|
29
|
+
working-directory: docs
|
|
30
|
+
- uses: actions/upload-pages-artifact@v3
|
|
31
|
+
with:
|
|
32
|
+
path: docs/site
|
|
33
|
+
|
|
34
|
+
deploy:
|
|
35
|
+
environment:
|
|
36
|
+
name: github-pages
|
|
37
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
needs: build
|
|
40
|
+
steps:
|
|
41
|
+
- id: deployment
|
|
42
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, stage_release]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
core-tests:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
|
|
28
|
+
- name: Install OpenMPI
|
|
29
|
+
run: |
|
|
30
|
+
sudo apt-get update
|
|
31
|
+
sudo apt-get install -y openmpi-bin libopenmpi-dev
|
|
32
|
+
|
|
33
|
+
- name: Install package
|
|
34
|
+
run: pip install -e ".[dev-core]"
|
|
35
|
+
|
|
36
|
+
- name: Run core tests
|
|
37
|
+
working-directory: ensemble_launcher/tests
|
|
38
|
+
timeout-minutes: 15
|
|
39
|
+
run: pytest -m core --timeout=300 -v --tb=short -W ignore::pytest.PytestUnraisableExceptionWarning --ignore=test_mcp.py --ignore=test_vllm.py
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Install & Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Editable install with dev dependencies
|
|
9
|
+
python3 -m pip install -e ".[dev]"
|
|
10
|
+
|
|
11
|
+
# Optional extras
|
|
12
|
+
python3 -m pip install -e ".[mcp]" # mcp + paramiko
|
|
13
|
+
python3 -m pip install -e ".[dragonhpc]" # DragonHPC backend
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The CLI entry point is `el` (`ensemble_launcher/cli.py`).
|
|
17
|
+
|
|
18
|
+
## Running Tests
|
|
19
|
+
|
|
20
|
+
Tests live in `ensemble_launcher/tests/`. They must be run from that directory because several tests import from `utils.py` via a relative import:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
cd ensemble_launcher/tests
|
|
24
|
+
pytest # all tests
|
|
25
|
+
pytest test_ensemble_launcher.py # end-to-end launcher tests
|
|
26
|
+
pytest test_async_master.py # async master/worker tests
|
|
27
|
+
pytest test_cluster.py # cluster-mode tests
|
|
28
|
+
pytest test_mcp.py # MCP interface tests
|
|
29
|
+
pytest test_ensemble_launcher.py::test_el_run # single test
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Tests require `pytest-asyncio` (already in `install_requires`). Async tests are decorated with `@pytest.mark.asyncio`.
|
|
33
|
+
|
|
34
|
+
## Architecture Overview
|
|
35
|
+
|
|
36
|
+
### Core abstraction layers (bottom-up)
|
|
37
|
+
|
|
38
|
+
1. **Executors** (`ensemble_launcher/executors/`) — launch subprocesses or coroutines. Registry pattern: `executor_registry.create_executor(name)`. Key executors:
|
|
39
|
+
- `async_processpool` — `AsyncProcessPoolExecutor` (default for serial tasks)
|
|
40
|
+
- `async_mpi` — `AsyncMPIExecutor` (MPI tasks)
|
|
41
|
+
- `multiprocessing`, `mpi`, `dragon` — legacy sync executors
|
|
42
|
+
|
|
43
|
+
2. **Communication** (`ensemble_launcher/comm/`) — message passing between nodes. Two async backends:
|
|
44
|
+
- `async_zmq` — `AsyncZMQComm` (preferred for multi-node)
|
|
45
|
+
- `multiprocessing` — `MPComm` (single-node only)
|
|
46
|
+
Messages are typed dataclasses in `comm/messages.py` (`Task`, `Result`, `ResultBatch`, `Status`, `Action`, `NodeUpdate`, `TaskUpdate`, `HeartBeat`, `Stop`).
|
|
47
|
+
|
|
48
|
+
3. **Scheduler** (`ensemble_launcher/scheduler/`) — assigns tasks to worker nodes. `WorkerScheduler` wraps a `LocalClusterResource` and a pluggable `ChildrenPolicy`. The default policy is `greedy_children_policy`. Custom policies can be loaded at runtime via env vars `EL_EXTERNAL_POLICY_MODULE` / `EL_EXTERNAL_POLICY_PATH`.
|
|
49
|
+
|
|
50
|
+
4. **Orchestrator** (`ensemble_launcher/orchestrator/`) — the master/worker tree:
|
|
51
|
+
- `AsyncMaster` — manages a layer of children (sub-masters or workers); the root is always named `"main"`.
|
|
52
|
+
- `AsyncWorker` — leaf node that executes tasks using a task executor.
|
|
53
|
+
- `AsyncWorkStealingMaster` / `AsyncWorkStealingWorker` — work-stealing variant (enabled via `LauncherConfig.enable_workstealing`).
|
|
54
|
+
- `ClusterClient` — connects to a running cluster via checkpoint directory to submit tasks and retrieve `concurrent.futures.Future`s.
|
|
55
|
+
|
|
56
|
+
5. **EnsembleLauncher** (`ensemble_launcher/ensemble_launcher.py`) — top-level entry point. Reads JSON config or a dict of `Task` objects, auto-configures `LauncherConfig` if not provided, builds the orchestrator tree, and exposes `run()` (blocking) / `start()` + `stop()` (non-blocking cluster mode).
|
|
57
|
+
|
|
58
|
+
### Node naming convention
|
|
59
|
+
|
|
60
|
+
Orchestrator nodes follow a hierarchical naming scheme:
|
|
61
|
+
- `main` — root master
|
|
62
|
+
- `main.w0`, `main.w1` — workers directly under root (nlevels=1)
|
|
63
|
+
- `main.m0`, `main.m1` — sub-masters (nlevels=2)
|
|
64
|
+
- `main.m0.w0` — worker under sub-master 0
|
|
65
|
+
|
|
66
|
+
`ClusterClient(node_id="global")` auto-resolves to the root master by reading checkpoints.
|
|
67
|
+
|
|
68
|
+
### Key configuration types (`ensemble_launcher/config.py`)
|
|
69
|
+
|
|
70
|
+
`SystemConfig` — describes one node: `ncpus`, `ngpus`, `cpus` (list of IDs), `gpus` (list of IDs or strings for overloading).
|
|
71
|
+
|
|
72
|
+
`LauncherConfig` — controls the entire orchestration:
|
|
73
|
+
- `comm_name`: `"async_zmq"` only (sync backends removed)
|
|
74
|
+
- `task_executor_name`: `"async_processpool"` | `"async_mpi"` | list for mixed workloads
|
|
75
|
+
- `child_executor_name`: executor used to launch sub-master/worker processes
|
|
76
|
+
- `nlevels`: hierarchy depth (0=worker only, 1=master+workers, 2=master+sub-masters+workers)
|
|
77
|
+
- `cluster`: enables long-lived cluster mode + `ClusterClient` API
|
|
78
|
+
- `checkpoint_dir`: where the cluster writes its ZMQ address for clients to discover
|
|
79
|
+
- `enable_workstealing`: switches to `AsyncWorkStealingMaster`
|
|
80
|
+
- `req_res`: enables ACK-based guaranteed delivery at the comm layer (default `True`)
|
|
81
|
+
- `send_retries`: number of retry attempts on ACK timeout, only when `req_res=True` (default `10`)
|
|
82
|
+
- `send_timeout`: per-attempt ACK timeout in seconds, only when `req_res=True` (default `1.0`)
|
|
83
|
+
|
|
84
|
+
### Cluster / MCP mode
|
|
85
|
+
|
|
86
|
+
When `cluster=True`, the orchestrator runs as a background service. `ClusterClient` reads the checkpoint directory to find the ZMQ address and submit tasks dynamically.
|
|
87
|
+
|
|
88
|
+
`ensemble_launcher/mcp/Interface` wraps FastMCP and connects to a running cluster:
|
|
89
|
+
- `@interface.tool` — single-task MCP tool
|
|
90
|
+
- `@interface.ensemble_tool` — batch ensemble MCP tool
|
|
91
|
+
SSH tunnel helpers for HPC login→compute node are in `ensemble_launcher/mcp/utils.py`.
|
|
92
|
+
|
|
93
|
+
### Checkpointing & Profiling
|
|
94
|
+
|
|
95
|
+
- Checkpoints written to `checkpoint_dir/` (ZMQ addresses for cluster discovery)
|
|
96
|
+
- Logs written to `logs/master-*.log` and `logs/worker-*.log`
|
|
97
|
+
- Profiling: set `LauncherConfig(profile="perfetto")` → outputs `profiles/*_perfetto.json` and `profiles/*_stats.json`
|
|
98
|
+
|
|
99
|
+
### Auto-configuration logic
|
|
100
|
+
|
|
101
|
+
When `launcher_config=None`, `EnsembleLauncher.__init__` auto-selects:
|
|
102
|
+
- If all tasks have `nnodes*ppn == 1` → `async_processpool`; otherwise `async_mpi`
|
|
103
|
+
- 1 node → `nlevels=0`, `async_zmq`
|
|
104
|
+
- 2–64 nodes → `nlevels=1`; 65–2048 → `nlevels=2`; 2048+ → `nlevels=3`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, UChicago Argonne, LLC
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ensemble_launcher
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A lightweight, scalable tool for launching and orchestrating task ensembles across HPC clusters.
|
|
5
|
+
Author: Hari Tummalapalli
|
|
6
|
+
License: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/argonne-lcf/ensemble_launcher
|
|
8
|
+
Project-URL: Documentation, https://argonne-lcf.github.io/ensemble_launcher
|
|
9
|
+
Project-URL: Repository, https://github.com/argonne-lcf/ensemble_launcher
|
|
10
|
+
Project-URL: Issues, https://github.com/argonne-lcf/ensemble_launcher/issues
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering
|
|
19
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: numpy
|
|
24
|
+
Requires-Dist: cloudpickle
|
|
25
|
+
Requires-Dist: pydantic
|
|
26
|
+
Requires-Dist: pyzmq
|
|
27
|
+
Requires-Dist: loky
|
|
28
|
+
Requires-Dist: typer
|
|
29
|
+
Provides-Extra: hpc
|
|
30
|
+
Requires-Dist: mpi4py; extra == "hpc"
|
|
31
|
+
Provides-Extra: mcp
|
|
32
|
+
Requires-Dist: mcp; extra == "mcp"
|
|
33
|
+
Requires-Dist: paramiko; extra == "mcp"
|
|
34
|
+
Provides-Extra: inference
|
|
35
|
+
Requires-Dist: vllm; extra == "inference"
|
|
36
|
+
Requires-Dist: uvloop; extra == "inference"
|
|
37
|
+
Requires-Dist: uvicorn; extra == "inference"
|
|
38
|
+
Requires-Dist: fastapi; extra == "inference"
|
|
39
|
+
Provides-Extra: docs
|
|
40
|
+
Requires-Dist: mkdocs-material; extra == "docs"
|
|
41
|
+
Provides-Extra: dev-core
|
|
42
|
+
Requires-Dist: pytest; extra == "dev-core"
|
|
43
|
+
Requires-Dist: pytest-timeout; extra == "dev-core"
|
|
44
|
+
Requires-Dist: pytest-asyncio; extra == "dev-core"
|
|
45
|
+
Requires-Dist: ensemble_launcher[hpc]; extra == "dev-core"
|
|
46
|
+
Provides-Extra: dev-extensions
|
|
47
|
+
Requires-Dist: ensemble_launcher[dev-core,inference,mcp]; extra == "dev-extensions"
|
|
48
|
+
Provides-Extra: all
|
|
49
|
+
Requires-Dist: ensemble_launcher[hpc,inference,mcp]; extra == "all"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
# Ensemble Launcher
|
|
53
|
+
|
|
54
|
+
A lightweight, scalable tool for launching and orchestrating task ensembles across HPC clusters with intelligent resource management and hierarchical execution.
|
|
55
|
+
|
|
56
|
+
[Documentation](https://argonne-lcf.github.io/ensemble_launcher/) | [GitHub](https://github.com/argonne-lcf/ensemble_launcher)
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
- **Scalability** -- Hierarchical master-worker architecture tested from 1 to 2048+ nodes
|
|
61
|
+
- **Flexible Execution** -- Support for serial, MPI, and mixed workloads with Python callables or shell commands
|
|
62
|
+
- **Co-Scheduling** -- Run heterogeneous tasks (different node counts, GPU requirements) in a single ensemble
|
|
63
|
+
- **Custom Scheduling Policies** -- Pluggable policy system with built-in bin-packing, split, and FIFO strategies, or write your own
|
|
64
|
+
- **Actors** -- Distributed actor model with async/await communication over ZMQ for long-lived stateful services
|
|
65
|
+
- **Inference** -- Actor-based vLLM wrappers for offline, online, and multi-node LLM serving on HPC clusters
|
|
66
|
+
|
|
67
|
+
## Quick Example
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from ensemble_launcher import EnsembleLauncher
|
|
71
|
+
|
|
72
|
+
el = EnsembleLauncher("config.json")
|
|
73
|
+
results = el.run()
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Or use the CLI
|
|
78
|
+
el start my_ensemble.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Acknowledgments
|
|
82
|
+
|
|
83
|
+
This work was supported by the U.S. Department of Energy, Office of Science, under contract DE-AC02-06CH11357.
|
|
84
|
+
|
|
85
|
+
## Citation
|
|
86
|
+
|
|
87
|
+
```bibtex
|
|
88
|
+
@article{tummalapalli2026overcoming,
|
|
89
|
+
title={Overcoming Orchestration Bottlenecks at Exascale: A Decentralized, Policy-Driven Approach for Sim-AI Ensembles},
|
|
90
|
+
author={Tummalapalli, Harikrishna and Simpson, Christine M and Balin, Riccardo and Morozov, Vitali A and Pham, Thang D and Keceli, Murat and Uram, Thomas D},
|
|
91
|
+
journal={arXiv preprint arXiv:2607.12211},
|
|
92
|
+
year={2026}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Ensemble Launcher
|
|
2
|
+
|
|
3
|
+
A lightweight, scalable tool for launching and orchestrating task ensembles across HPC clusters with intelligent resource management and hierarchical execution.
|
|
4
|
+
|
|
5
|
+
[Documentation](https://argonne-lcf.github.io/ensemble_launcher/) | [GitHub](https://github.com/argonne-lcf/ensemble_launcher)
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Scalability** -- Hierarchical master-worker architecture tested from 1 to 2048+ nodes
|
|
10
|
+
- **Flexible Execution** -- Support for serial, MPI, and mixed workloads with Python callables or shell commands
|
|
11
|
+
- **Co-Scheduling** -- Run heterogeneous tasks (different node counts, GPU requirements) in a single ensemble
|
|
12
|
+
- **Custom Scheduling Policies** -- Pluggable policy system with built-in bin-packing, split, and FIFO strategies, or write your own
|
|
13
|
+
- **Actors** -- Distributed actor model with async/await communication over ZMQ for long-lived stateful services
|
|
14
|
+
- **Inference** -- Actor-based vLLM wrappers for offline, online, and multi-node LLM serving on HPC clusters
|
|
15
|
+
|
|
16
|
+
## Quick Example
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from ensemble_launcher import EnsembleLauncher
|
|
20
|
+
|
|
21
|
+
el = EnsembleLauncher("config.json")
|
|
22
|
+
results = el.run()
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Or use the CLI
|
|
27
|
+
el start my_ensemble.json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Acknowledgments
|
|
31
|
+
|
|
32
|
+
This work was supported by the U.S. Department of Energy, Office of Science, under contract DE-AC02-06CH11357.
|
|
33
|
+
|
|
34
|
+
## Citation
|
|
35
|
+
|
|
36
|
+
```bibtex
|
|
37
|
+
@article{tummalapalli2026overcoming,
|
|
38
|
+
title={Overcoming Orchestration Bottlenecks at Exascale: A Decentralized, Policy-Driven Approach for Sim-AI Ensembles},
|
|
39
|
+
author={Tummalapalli, Harikrishna and Simpson, Christine M and Balin, Riccardo and Morozov, Vitali A and Pham, Thang D and Keceli, Murat and Uram, Thomas D},
|
|
40
|
+
journal={arXiv preprint arXiv:2607.12211},
|
|
41
|
+
year={2026}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
Binary file
|