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.
Files changed (152) hide show
  1. ensemble_launcher-0.1.0/.github/workflows/pages.yml +42 -0
  2. ensemble_launcher-0.1.0/.github/workflows/tests.yml +39 -0
  3. ensemble_launcher-0.1.0/.gitignore +12 -0
  4. ensemble_launcher-0.1.0/CLAUDE.md +104 -0
  5. ensemble_launcher-0.1.0/LICENSE +29 -0
  6. ensemble_launcher-0.1.0/PKG-INFO +94 -0
  7. ensemble_launcher-0.1.0/README.md +43 -0
  8. ensemble_launcher-0.1.0/assets/el.png +0 -0
  9. ensemble_launcher-0.1.0/benchmarks/benchmark_comm.py +398 -0
  10. ensemble_launcher-0.1.0/benchmarks/benchmark_latency.py +193 -0
  11. ensemble_launcher-0.1.0/benchmarks/benchmark_pool.py +76 -0
  12. ensemble_launcher-0.1.0/benchmarks/benchmark_uv.py +47 -0
  13. ensemble_launcher-0.1.0/benchmarks/benchmark_zero_copy.py +127 -0
  14. ensemble_launcher-0.1.0/benchmarks/latency_results.csv +3 -0
  15. ensemble_launcher-0.1.0/benchmarks/utils.py +9 -0
  16. ensemble_launcher-0.1.0/docs/docs/api-reference.md +155 -0
  17. ensemble_launcher-0.1.0/docs/docs/architecture.md +93 -0
  18. ensemble_launcher-0.1.0/docs/docs/cli.md +69 -0
  19. ensemble_launcher-0.1.0/docs/docs/cluster-mode.md +101 -0
  20. ensemble_launcher-0.1.0/docs/docs/configuration.md +186 -0
  21. ensemble_launcher-0.1.0/docs/docs/contributing.md +56 -0
  22. ensemble_launcher-0.1.0/docs/docs/custom-scheduling.md +148 -0
  23. ensemble_launcher-0.1.0/docs/docs/examples.md +175 -0
  24. ensemble_launcher-0.1.0/docs/docs/experimental/actors.md +122 -0
  25. ensemble_launcher-0.1.0/docs/docs/experimental/inference.md +153 -0
  26. ensemble_launcher-0.1.0/docs/docs/experimental/mcp.md +103 -0
  27. ensemble_launcher-0.1.0/docs/docs/index.md +43 -0
  28. ensemble_launcher-0.1.0/docs/docs/installation.md +69 -0
  29. ensemble_launcher-0.1.0/docs/docs/quickstart.md +80 -0
  30. ensemble_launcher-0.1.0/docs/mkdocs.yml +65 -0
  31. ensemble_launcher-0.1.0/ensemble_launcher/__init__.py +4 -0
  32. ensemble_launcher-0.1.0/ensemble_launcher/checkpointing/__init__.py +15 -0
  33. ensemble_launcher-0.1.0/ensemble_launcher/checkpointing/checkpointer.py +482 -0
  34. ensemble_launcher-0.1.0/ensemble_launcher/cli.py +95 -0
  35. ensemble_launcher-0.1.0/ensemble_launcher/comm/__init__.py +72 -0
  36. ensemble_launcher-0.1.0/ensemble_launcher/comm/async_base.py +971 -0
  37. ensemble_launcher-0.1.0/ensemble_launcher/comm/async_zmq.py +908 -0
  38. ensemble_launcher-0.1.0/ensemble_launcher/comm/base.py +294 -0
  39. ensemble_launcher-0.1.0/ensemble_launcher/comm/dragon.py +388 -0
  40. ensemble_launcher-0.1.0/ensemble_launcher/comm/hb.py +311 -0
  41. ensemble_launcher-0.1.0/ensemble_launcher/comm/messages.py +629 -0
  42. ensemble_launcher-0.1.0/ensemble_launcher/comm/mp.py +124 -0
  43. ensemble_launcher-0.1.0/ensemble_launcher/comm/nodeinfo.py +20 -0
  44. ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/__init__.py +47 -0
  45. ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/async_connection.py +630 -0
  46. ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/async_transport.py +273 -0
  47. ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/mp_connection.py +106 -0
  48. ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/mp_transport.py +99 -0
  49. ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/registry.py +45 -0
  50. ensemble_launcher-0.1.0/ensemble_launcher/comm/pipe/utils.py +24 -0
  51. ensemble_launcher-0.1.0/ensemble_launcher/comm/queue/__init__.py +2 -0
  52. ensemble_launcher-0.1.0/ensemble_launcher/comm/queue/protocol.py +16 -0
  53. ensemble_launcher-0.1.0/ensemble_launcher/comm/queue/registry.py +36 -0
  54. ensemble_launcher-0.1.0/ensemble_launcher/comm/zmq.py +254 -0
  55. ensemble_launcher-0.1.0/ensemble_launcher/config/__init__.py +19 -0
  56. ensemble_launcher-0.1.0/ensemble_launcher/config/config.py +138 -0
  57. ensemble_launcher-0.1.0/ensemble_launcher/config/mpi_config.py +193 -0
  58. ensemble_launcher-0.1.0/ensemble_launcher/ensemble/__init__.py +3 -0
  59. ensemble_launcher-0.1.0/ensemble_launcher/ensemble/actor.py +851 -0
  60. ensemble_launcher-0.1.0/ensemble_launcher/ensemble/actor_pool.py +213 -0
  61. ensemble_launcher-0.1.0/ensemble_launcher/ensemble/ensemble.py +394 -0
  62. ensemble_launcher-0.1.0/ensemble_launcher/ensemble_launcher.py +208 -0
  63. ensemble_launcher-0.1.0/ensemble_launcher/executors/__init__.py +5 -0
  64. ensemble_launcher-0.1.0/ensemble_launcher/executors/async_mp_executor.py +277 -0
  65. ensemble_launcher-0.1.0/ensemble_launcher/executors/async_mpi_executor.py +602 -0
  66. ensemble_launcher-0.1.0/ensemble_launcher/executors/async_mpi_pool_executor.py +357 -0
  67. ensemble_launcher-0.1.0/ensemble_launcher/executors/base.py +46 -0
  68. ensemble_launcher-0.1.0/ensemble_launcher/executors/dragon_executor.py +230 -0
  69. ensemble_launcher-0.1.0/ensemble_launcher/executors/mp_executor.py +101 -0
  70. ensemble_launcher-0.1.0/ensemble_launcher/executors/mpi_executor.py +215 -0
  71. ensemble_launcher-0.1.0/ensemble_launcher/executors/mpi_pool.py +309 -0
  72. ensemble_launcher-0.1.0/ensemble_launcher/executors/utils.py +238 -0
  73. ensemble_launcher-0.1.0/ensemble_launcher/helper_functions.py +100 -0
  74. ensemble_launcher-0.1.0/ensemble_launcher/inference/__init__.py +13 -0
  75. ensemble_launcher-0.1.0/ensemble_launcher/inference/configs.py +28 -0
  76. ensemble_launcher-0.1.0/ensemble_launcher/inference/copy_model.py +302 -0
  77. ensemble_launcher-0.1.0/ensemble_launcher/inference/openai_inference.py +68 -0
  78. ensemble_launcher-0.1.0/ensemble_launcher/inference/start_vllm_server.sh +104 -0
  79. ensemble_launcher-0.1.0/ensemble_launcher/inference/utils.py +255 -0
  80. ensemble_launcher-0.1.0/ensemble_launcher/inference/vllm_inference.py +1516 -0
  81. ensemble_launcher-0.1.0/ensemble_launcher/logging/__init__.py +63 -0
  82. ensemble_launcher-0.1.0/ensemble_launcher/loop.py +4 -0
  83. ensemble_launcher-0.1.0/ensemble_launcher/mcp/__init__.py +2 -0
  84. ensemble_launcher-0.1.0/ensemble_launcher/mcp/interface.py +414 -0
  85. ensemble_launcher-0.1.0/ensemble_launcher/mcp/utils.py +200 -0
  86. ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/__init__.py +67 -0
  87. ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/async_master.py +2089 -0
  88. ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/async_worker.py +1216 -0
  89. ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/async_workstealing_master.py +269 -0
  90. ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/async_workstealing_worker.py +162 -0
  91. ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/cluster_client.py +572 -0
  92. ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/master.py +589 -0
  93. ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/node.py +55 -0
  94. ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/utils.py +97 -0
  95. ensemble_launcher-0.1.0/ensemble_launcher/orchestrator/worker.py +383 -0
  96. ensemble_launcher-0.1.0/ensemble_launcher/profiling/__init__.py +5 -0
  97. ensemble_launcher-0.1.0/ensemble_launcher/profiling/event_registry.py +886 -0
  98. ensemble_launcher-0.1.0/ensemble_launcher/profiling/merge_traces.py +156 -0
  99. ensemble_launcher-0.1.0/ensemble_launcher/scheduler/__init__.py +22 -0
  100. ensemble_launcher-0.1.0/ensemble_launcher/scheduler/async_scheduler.py +1217 -0
  101. ensemble_launcher-0.1.0/ensemble_launcher/scheduler/child_state.py +10 -0
  102. ensemble_launcher-0.1.0/ensemble_launcher/scheduler/policy.py +625 -0
  103. ensemble_launcher-0.1.0/ensemble_launcher/scheduler/resource/__init__.py +9 -0
  104. ensemble_launcher-0.1.0/ensemble_launcher/scheduler/resource/cluster.py +305 -0
  105. ensemble_launcher-0.1.0/ensemble_launcher/scheduler/resource/node.py +417 -0
  106. ensemble_launcher-0.1.0/ensemble_launcher/scheduler/scheduler.py +255 -0
  107. ensemble_launcher-0.1.0/ensemble_launcher/scheduler/state.py +107 -0
  108. ensemble_launcher-0.1.0/ensemble_launcher/tests/conftest.py +7 -0
  109. ensemble_launcher-0.1.0/ensemble_launcher/tests/ensembles.json +10 -0
  110. ensemble_launcher-0.1.0/ensemble_launcher/tests/py_echo.py +12 -0
  111. ensemble_launcher-0.1.0/ensemble_launcher/tests/start_mcp.py +83 -0
  112. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_actor.py +383 -0
  113. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_actor_pool.py +355 -0
  114. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_async_comm.py +382 -0
  115. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_async_executor.py +47 -0
  116. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_async_master.py +130 -0
  117. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_async_worker.py +338 -0
  118. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_async_workstealing_master.py +124 -0
  119. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_cluster.py +245 -0
  120. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_connections.py +504 -0
  121. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_el.py +37 -0
  122. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_ensemble_launcher.py +98 -0
  123. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_fault_tolerance.py +108 -0
  124. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_mcp.py +169 -0
  125. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_resource_manager.py +63 -0
  126. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_scheduler.py +64 -0
  127. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_ser_deser.py +775 -0
  128. ensemble_launcher-0.1.0/ensemble_launcher/tests/test_vllm.py +720 -0
  129. ensemble_launcher-0.1.0/ensemble_launcher/tests/time_execution.py +53 -0
  130. ensemble_launcher-0.1.0/ensemble_launcher/tests/utils.py +40 -0
  131. ensemble_launcher-0.1.0/ensemble_launcher.egg-info/PKG-INFO +94 -0
  132. ensemble_launcher-0.1.0/ensemble_launcher.egg-info/SOURCES.txt +150 -0
  133. ensemble_launcher-0.1.0/ensemble_launcher.egg-info/dependency_links.txt +1 -0
  134. ensemble_launcher-0.1.0/ensemble_launcher.egg-info/entry_points.txt +2 -0
  135. ensemble_launcher-0.1.0/ensemble_launcher.egg-info/requires.txt +34 -0
  136. ensemble_launcher-0.1.0/ensemble_launcher.egg-info/top_level.txt +1 -0
  137. ensemble_launcher-0.1.0/examples/agents/pydantic/README.md +78 -0
  138. ensemble_launcher-0.1.0/examples/agents/pydantic/agents.py +123 -0
  139. ensemble_launcher-0.1.0/examples/agents/pydantic/joke_generator.py +81 -0
  140. ensemble_launcher-0.1.0/examples/agents/pydantic/utils.py +27 -0
  141. ensemble_launcher-0.1.0/examples/batch/mixed_workload.py +47 -0
  142. ensemble_launcher-0.1.0/examples/batch/python_tasks.py +26 -0
  143. ensemble_launcher-0.1.0/examples/batch/shell_tasks.py +21 -0
  144. ensemble_launcher-0.1.0/examples/cluster/cluster_mode.py +72 -0
  145. ensemble_launcher-0.1.0/examples/cluster/cluster_shell_tasks.py +45 -0
  146. ensemble_launcher-0.1.0/examples/mcp/combustion/README.md +38 -0
  147. ensemble_launcher-0.1.0/examples/mcp/combustion/flamespeed.py +33 -0
  148. ensemble_launcher-0.1.0/examples/mcp/combustion/start_mcp_http.py +41 -0
  149. ensemble_launcher-0.1.0/examples/python/mpi_example.py +58 -0
  150. ensemble_launcher-0.1.0/examples/python/serial_example.py +41 -0
  151. ensemble_launcher-0.1.0/pyproject.toml +59 -0
  152. 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,12 @@
1
+ **/__pycache__/
2
+ ckpt_*/
3
+ mcp_*/
4
+ logs/
5
+ *_status.json
6
+ *.mpiexec_tmp/
7
+ profiles/
8
+ build/
9
+ dist/
10
+ *.egg-info/
11
+ docs/site/
12
+
@@ -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