Skip to content
This repository was archived by the owner on Jul 2, 2026. It is now read-only.

Commit abd8277

Browse files
juaristi22claudeMaxGhenis
authored
Parallelize chunked matrix building approach (#818) (#821)
* Extract ChunkedMatrixAssembler and stream CSR assembly (#818) Phase 1 of issue #818: refactor `UnifiedMatrixBuilder.build_matrix_chunked` behind a coordinator class so a later commit can parallelize per-chunk work across Modal workers. Changes: - New `policyengine_us_data/calibration/chunked_matrix_assembler.py` with `SharedBuildState`, `ChunkPlan`, `ChunkResult` dataclasses and a `ChunkedMatrixAssembler` class exposing `run_chunks`, `run_single_chunk`, and `assemble_final`. The per-chunk body (H5 materialization, per-chunk `Microsimulation`, variable calculation, COO shard write) moves into `run_single_chunk`. - Replace the list-then-concat final-assembly block with a two-pass streaming CSR build: pass 1 counts per-row nnz across shards to compute `indptr`; pass 2 scatters entries into preallocated `data`/`indices` arrays, avoiding the scipy COO->CSR memory peak. Measured peak RSS on a 5M-nnz synthetic fixture is 1.22x the final CSR, vs. the 2-3x peak the old path reintroduced. - `build_matrix_chunked` becomes a ~80-line facade; target querying, uprating, constraint extraction, and manifest handling stay on `UnifiedMatrixBuilder`. Public signature unchanged; all 6 existing chunked-matrix integration tests pass without edits. - Lift `_build_entity_relationship` to module scope as `build_entity_relationship(sim)` so `SharedBuildState` stays pickle-clean for cross-process dispatch in phase 2. The memoizing wrapper on `UnifiedMatrixBuilder` remains for non-chunked callers. - 10 new unit tests in `tests/unit/calibration/test_chunked_matrix_assembler.py` cover partition correctness, streaming CSR (including a memory bound), resume-skip, range-mismatch rejection, and dispatcher routing via `run_chunks`. The Modal parallel-dispatch function, `build_matrix_chunk_worker` Modal function, and `--parallel` / `--num-matrix-workers` CLI flags will land in the next commit (phase 2). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Parallelize chunked matrix build across Modal workers (#818) Phase 2 of issue #818. Builds on the phase-1 coordinator extraction to fan chunked matrix building out across Modal workers, cutting the full-CPS build's wall time from the ~14 h serial ceiling into a wall-time window proportional to one chunk. Changes: - `policyengine_us_data/calibration/chunked_matrix_modal.py`: new `dispatch_chunks_modal` coordinator. Pickles `SharedBuildState` to `{chunk_root}/chunk_build_state.pkl` on the pipeline volume, partitions `range(n_chunks)` into contiguous batches, spawns one `build_matrix_chunk_worker` per batch via `modal.Function.from_name`, collects results, aggregates per-chunk errors, and streams the final CSR from shards on the volume. Contiguous batching (not round-robin) keeps resume-friendly prefixes on disk. - `modal_app/matrix_chunk_worker.py`: new `build_matrix_chunk_worker` `@app.function` registered on the existing `policyengine-us-data-fit-weights` app (same app as `build_package_remote`). Mirrors `build_areas_worker` resources (memory=16384, cpu=1.0, timeout=28800, max_containers=50, nonpreemptible). Worker reads the pickled shared state, constructs a `ChunkedMatrixAssembler` with `resume=True`, calls `run_chunks` on its batch, commits the volume, returns nnz + errors. - `SharedBuildState` grows a `chunk_size` field so a worker can reconstruct the assembler from the pickle alone (no extra args). - `build_matrix_chunked` accepts `parallel`, `num_matrix_workers`, `run_id`; routes to `dispatch_chunks_modal` when `parallel=True`, preserves the in-process serial path otherwise. - `unified_calibration` CLI gains `--parallel` (default off) and `--num-matrix-workers` (default 50). `--parallel` without `--chunked-matrix` logs an info message and runs the non-chunked path unchanged. `run_id` flows from env `POLICYENGINE_US_DATA_RUN_ID`, set by `build_package_remote`. - `build_package_remote` / `_build_package_impl` take `chunked_matrix`, `chunk_size`, `parallel_matrix`, `num_matrix_workers` kwargs and forward them to the `unified_calibration` subprocess. Tests: - 9 unit tests in `tests/unit/calibration/test_chunked_matrix_modal.py` cover `partition_chunk_ids_contiguous` (exact division, remainder, more workers than chunks, zero chunks, invalid num_workers) and `dispatch_chunks_modal` with injected `worker_function` + `volume` fakes (spawn/assemble happy path, zero-chunks short-circuit, error aggregation, shared-state pickle side effect). - New `test_shared_build_state_roundtrips_pickle` in the assembler unit tests guards the phase-2 boundary: if `SharedBuildState` stops pickling cleanly, we catch it here rather than in a Modal worker. 11 assembler unit tests total. - `tests/integration/test_matrix_chunk_worker_modal.py` is an env-gated smoke test (MODAL_TOKEN_ID + MODAL_TOKEN_SECRET + POLICYENGINE_US_DATA_MODAL_SMOKE=1) that validates the deployed worker is lookupable via `modal.Function.from_name` and that production-scale batching is sane. Full end-to-end validation (write shared state, spawn, verify shards on the volume) is a pre-merge manual step documented in the PR. Verified: - 392 calibration unit tests pass (up from 382; 10 new phase-2 tests; 0 regressions), plus the 6 existing chunked-matrix integration tests still green against the phase-1 facade. - `ruff check` and `ruff format --check` clean on all changed files. Validation still pending on real Modal (deploy + one-chunk benchmark + full-CPS `workflow_dispatch` run); gated on the Modal venv-activation PR landing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Thread parallel-matrix flags through pipeline.py + workflow_dispatch Closes the wiring gap between issue #818's CLI flags and the pipeline orchestrator. `run_pipeline` now accepts `chunked_matrix`, `chunk_size`, `parallel_matrix`, and `num_matrix_workers` kwargs and forwards them to `build_package_remote.remote()`. All four default off/50, so the auto-triggered pipeline run on the next `Update package version` commit after this PR merges will continue to use the existing non-chunked path. `pipeline.yaml`'s `workflow_dispatch` exposes the same four knobs (defaults also off/50). To trigger the one-off chunked-parallel validation run after this PR merges: gh workflow run pipeline.yaml \ -f chunked_matrix=true \ -f parallel_matrix=true \ -f num_matrix_workers=50 Subsequent automatic pipeline runs (on version-bump commits) pick up the defaults and stay non-chunked until someone dispatches manually with the flags on again. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Register build_matrix_chunk_worker via pipeline.py import Without this import, ``modal deploy modal_app/pipeline.py`` (run by ``pipeline.yaml`` on dispatch) would skip ``build_matrix_chunk_worker`` because it lives in its own module — ``_calibration_app`` only knows about functions that have been loaded. Importing the worker here runs its ``@app.function`` decorator at module load, so ``app.include(_calibration_app)`` picks it up and the worker is deployed alongside ``build_package_remote``. Without it, ``modal.Function.from_name`` in ``dispatch_chunks_modal`` would fail at runtime on the first parallel-matrix attempt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Fix Modal app name used by dispatch_chunks_modal lookup (#818) ``dispatch_chunks_modal._lookup_worker_function`` was looking the worker up under ``policyengine-us-data-fit-weights`` — the name declared on ``_calibration_app`` in ``modal_app/remote_calibration_runner.py`` where the worker's ``@app.function`` decorator attaches at the Python level. That is not the name the function is registered under in Modal's registry. ``modal_app/pipeline.py`` merges the fit-weights sub-app into the pipeline app via ``app.include(_calibration_app)`` before deploy. After ``modal deploy modal_app/pipeline.py`` (what both the ``pipeline.yaml`` dispatch step and the ``pr.yaml`` preview step run), Modal's registry only knows about ``policyengine-us-data-pipeline`` — there is no independent ``policyengine-us-data-fit-weights`` entry. A ``Function.from_name`` call with the sub-app's name would raise at runtime on the first parallel-matrix invocation. Caught by inspecting ``modal app list`` on a deploy: the fit-weights app is absent; only ``policyengine-us-data-pipeline`` (and the dataset-only ``policyengine-us-data`` ephemeral from ``push.yaml``'s ``modal run modal_app/data_build.py``) appear. Changes: - ``MODAL_APP_NAME`` now ``policyengine-us-data-pipeline``, with a comment pointing at the ``app.include`` hop that makes this necessary. - ``matrix_chunk_worker.py`` docstring rewritten to explain the two-level naming (Python-object name vs registry name after ``app.include``). - ``test_matrix_chunk_worker_modal.py`` looks up under the pipeline app name and updates the "Deploy first with" instruction to ``modal deploy modal_app/pipeline.py`` (the correct deploy path — the previous instruction would have created an orphan fit-weights registration that production code never looks up). Unit tests (which inject a fake ``worker_function``) are unaffected and still pass. The env-gated integration smoke was previously guaranteed to fail on first real deploy; it can now pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Fix diagnostics upload script indentation * Force Modal worker smoke lookup * Allow Modal smoke test to use profile auth * Set volume chunk dir for Modal matrix builds * Release volume handles before Modal matrix reload * Document Modal matrix runtime fixes * Harden parallel matrix Modal dispatch --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Max Ghenis <mghenis@gmail.com>
1 parent ceef4ae commit abd8277

17 files changed

Lines changed: 2131 additions & 329 deletions

.github/scripts/spawn_modal_pipeline.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ def _as_bool(value: str) -> bool:
1515
return value.lower() == "true"
1616

1717

18+
def _env(name: str, default: str) -> str:
19+
return os.environ.get(name, default)
20+
21+
1822
def _append_summary(function_call_id: str, context: RunContext) -> None:
1923
summary_path = os.environ.get("GITHUB_STEP_SUMMARY")
2024
if not summary_path:
@@ -36,6 +40,13 @@ def _append_summary(function_call_id: str, context: RunContext) -> None:
3640
handle.write(f"| HF staging | `{context.hf_staging_prefix}` |\n")
3741
if os.environ.get("SOURCE_SHA"):
3842
handle.write(f"| Source SHA | `{os.environ['SOURCE_SHA']}` |\n")
43+
handle.write(
44+
"| Matrix | "
45+
f"`chunked={_env('CHUNKED_MATRIX', 'false')}, "
46+
f"parallel={_env('PARALLEL_MATRIX', 'false')}, "
47+
f"chunk_size={_env('CHUNK_SIZE', '25000')}, "
48+
f"workers={_env('NUM_MATRIX_WORKERS', '50')}` |\n"
49+
)
3950
handle.write(f"| Function call ID | `{function_call_id}` |\n\n")
4051
handle.write("**[Monitor on Modal Dashboard](https://modal.com/apps)**\n")
4152

@@ -58,6 +69,10 @@ def main() -> None:
5869
"run_context": context.to_dict(),
5970
"modal_app_name": context.modal_app_name,
6071
"modal_environment": context.modal_environment,
72+
"chunked_matrix": _as_bool(_env("CHUNKED_MATRIX", "false")),
73+
"chunk_size": int(_env("CHUNK_SIZE", "25000")),
74+
"parallel_matrix": _as_bool(_env("PARALLEL_MATRIX", "false")),
75+
"num_matrix_workers": int(_env("NUM_MATRIX_WORKERS", "50")),
6176
}
6277
if environment_name:
6378
run_pipeline = modal.Function.from_name(

.github/workflows/pipeline.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ on:
3939
description: "Exact policyengine-us-data commit SHA to deploy"
4040
default: ""
4141
type: string
42+
chunked_matrix:
43+
description: "Build the calibration matrix in chunks (opt-in)"
44+
default: false
45+
type: boolean
46+
chunk_size:
47+
description: "Clone-household columns per chunk"
48+
default: "25000"
49+
type: string
50+
parallel_matrix:
51+
description: "Fan chunked matrix building across Modal workers"
52+
default: false
53+
type: boolean
54+
num_matrix_workers:
55+
description: "Number of Modal workers for parallel matrix build"
56+
default: "50"
57+
type: string
4258

4359
concurrency:
4460
group: pipeline-${{ github.run_id }}-${{ github.run_attempt }}
@@ -80,6 +96,10 @@ jobs:
8096
RESUME_RUN_ID: ${{ inputs.resume_run_id || '' }}
8197
VERSION_OVERRIDE: ${{ inputs.version_override || '' }}
8298
SOURCE_SHA: ${{ inputs.source_sha || github.sha }}
99+
CHUNKED_MATRIX: ${{ inputs.chunked_matrix || 'false' }}
100+
CHUNK_SIZE: ${{ inputs.chunk_size || '25000' }}
101+
PARALLEL_MATRIX: ${{ inputs.parallel_matrix || 'false' }}
102+
NUM_MATRIX_WORKERS: ${{ inputs.num_matrix_workers || '50' }}
83103
run: |
84104
modal deploy --env="${MODAL_ENVIRONMENT}" --name="${US_DATA_MODAL_APP_NAME}" --tag="${US_DATA_RUN_ID}" modal_app/pipeline.py
85105
python .github/scripts/spawn_modal_pipeline.py

changelog.d/818.changed.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Extract `ChunkedMatrixAssembler` from `UnifiedMatrixBuilder.build_matrix_chunked` and replace the list-then-concat final assembly with a two-pass streaming CSR build. The facade signature and all existing chunked-matrix behaviour are unchanged.
2+
3+
Parallelize chunked matrix building across Modal workers. Adds `dispatch_chunks_modal` (`policyengine_us_data/calibration/chunked_matrix_modal.py`) that pickles `SharedBuildState` to the pipeline volume, fans contiguous chunk-id batches to `build_matrix_chunk_worker` (`modal_app/matrix_chunk_worker.py`, registered on the `policyengine-us-data-fit-weights` app), and streams the final CSR from shards on the volume. New CLI flags on `unified_calibration`: `--parallel` (default off) and `--num-matrix-workers` (default 50). `build_package_remote` threads `run_id` to the subprocess via the `POLICYENGINE_US_DATA_RUN_ID` env var and forwards `--parallel` / `--num-matrix-workers` when `parallel_matrix=True`. `--parallel` without `--chunked-matrix` logs an info message and runs the non-chunked path unchanged.
4+
5+
Ensure Modal parallel matrix builds write coordinator shared state to the same volume-backed `matrix_build` directory used by workers, and release coordinator-side volume file handles before the final volume reload and CSR assembly.

modal_app/data_build.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
pipeline_volume = modal.Volume.from_name(
4646
os.environ.get("US_DATA_PIPELINE_VOLUME_NAME", "pipeline-artifacts"),
4747
create_if_missing=True,
48+
version=2,
4849
)
4950
PIPELINE_MOUNT = "/pipeline"
5051

modal_app/local_area.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
pipeline_volume = modal.Volume.from_name(
5656
os.environ.get("US_DATA_PIPELINE_VOLUME_NAME", "pipeline-artifacts"),
5757
create_if_missing=True,
58+
version=2,
5859
)
5960

6061
VOLUME_MOUNT = "/staging"

modal_app/matrix_chunk_worker.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
"""Modal worker that materializes a batch of matrix chunks.
2+
3+
The ``@app.function`` decorator here attaches to ``_calibration_app``
4+
(declared as ``policyengine-us-data-fit-weights`` in
5+
``remote_calibration_runner.py``), alongside ``build_package_remote``.
6+
At deploy time, ``modal_app/pipeline.py`` merges that app into the
7+
pipeline app via ``app.include(_calibration_app)``, so after
8+
``modal deploy modal_app/pipeline.py`` the function is registered
9+
under ``policyengine-us-data-pipeline`` in Modal's registry — that's
10+
the name ``dispatch_chunks_modal`` uses in its
11+
``modal.Function.from_name`` lookup.
12+
13+
Each worker reads the shared ``ChunkedMatrixAssembler`` state from
14+
``pipeline_volume``, materializes its assigned chunks to COO shard
15+
files on the volume, and commits. The coordinator reads the shards
16+
back after all workers finish and streams them into the final CSR
17+
matrix.
18+
"""
19+
20+
from __future__ import annotations
21+
22+
import pickle
23+
import sys
24+
import traceback
25+
from pathlib import Path
26+
from typing import Dict, List
27+
28+
_baked = "/root/policyengine-us-data"
29+
_local = str(Path(__file__).resolve().parent.parent)
30+
for _p in (_baked, _local):
31+
if _p not in sys.path:
32+
sys.path.insert(0, _p)
33+
34+
from modal_app.images import cpu_image # noqa: E402
35+
from modal_app.remote_calibration_runner import ( # noqa: E402
36+
PIPELINE_MOUNT,
37+
app,
38+
hf_secret,
39+
pipeline_vol,
40+
)
41+
42+
43+
def _chunk_root(run_id: str) -> str:
44+
return f"{PIPELINE_MOUNT}/artifacts/{run_id}/matrix_build"
45+
46+
47+
@app.function(
48+
image=cpu_image,
49+
secrets=[hf_secret],
50+
volumes={PIPELINE_MOUNT: pipeline_vol},
51+
memory=16384,
52+
cpu=1.0,
53+
timeout=28800,
54+
max_containers=50,
55+
nonpreemptible=True,
56+
)
57+
def build_matrix_chunk_worker(
58+
run_id: str,
59+
chunk_ids: List[int],
60+
resume_chunks: bool = False,
61+
) -> Dict:
62+
"""Materialize ``chunk_ids`` from the pickled ``SharedBuildState``.
63+
64+
Args:
65+
run_id: Pipeline run identifier; selects the volume path for
66+
this worker's shared state and shard output directory.
67+
chunk_ids: Chunk indices this worker is responsible for.
68+
resume_chunks: Whether to trust matching pre-existing COO shards.
69+
Fresh builds pass ``False`` so workers overwrite stale chunks.
70+
71+
Returns:
72+
Dict with ``chunk_ids``, ``nnz_per_chunk``, and ``errors``
73+
lists suitable for the coordinator to aggregate.
74+
"""
75+
from policyengine_us_data.calibration.chunked_matrix_assembler import (
76+
ChunkedMatrixAssembler,
77+
)
78+
79+
pipeline_vol.reload()
80+
chunk_root = Path(_chunk_root(run_id))
81+
state_path = chunk_root / "chunk_build_state.pkl"
82+
if not state_path.exists():
83+
return {
84+
"chunk_ids": list(chunk_ids),
85+
"nnz_per_chunk": [],
86+
"errors": [
87+
{
88+
"chunk_ids": list(chunk_ids),
89+
"error": f"Missing shared state at {state_path}",
90+
}
91+
],
92+
}
93+
94+
with open(state_path, "rb") as f:
95+
shared_state = pickle.load(f)
96+
97+
assembler = ChunkedMatrixAssembler(
98+
shared_state=shared_state,
99+
chunk_root=chunk_root,
100+
chunk_size=shared_state.chunk_size,
101+
resume=resume_chunks,
102+
keep_chunks=False,
103+
)
104+
105+
errors: List[Dict] = []
106+
nnz_per_chunk: List[int] = []
107+
for chunk_id in chunk_ids:
108+
try:
109+
result = assembler.run_single_chunk(chunk_id)
110+
nnz_per_chunk.append(result.nnz)
111+
except Exception as exc:
112+
errors.append(
113+
{
114+
"chunk_id": chunk_id,
115+
"error": str(exc),
116+
"traceback": traceback.format_exc(),
117+
}
118+
)
119+
120+
pipeline_vol.commit()
121+
return {
122+
"chunk_ids": list(chunk_ids),
123+
"nnz_per_chunk": nnz_per_chunk,
124+
"errors": errors,
125+
}

modal_app/pipeline.py

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
pipeline_volume = modal.Volume.from_name(
116116
os.environ.get("US_DATA_PIPELINE_VOLUME_NAME", "pipeline-artifacts"),
117117
create_if_missing=True,
118+
version=2,
118119
)
119120
staging_volume = modal.Volume.from_name(
120121
os.environ.get("US_DATA_STAGING_VOLUME_NAME", "local-area-staging"),
@@ -129,6 +130,31 @@ def _python_cmd(*args: str) -> list[str]:
129130
return [sys.executable, *args]
130131

131132

133+
def _calibration_package_parameters(
134+
*,
135+
workers: int,
136+
n_clones: int,
137+
target_config: str | None,
138+
skip_county: bool,
139+
chunked_matrix: bool,
140+
chunk_size: int,
141+
parallel_matrix: bool,
142+
num_matrix_workers: int,
143+
) -> dict:
144+
"""Return manifest parameters that affect package construction."""
145+
effective_parallel = bool(chunked_matrix and parallel_matrix)
146+
return {
147+
"workers": workers if not chunked_matrix else None,
148+
"n_clones": n_clones,
149+
"target_config": target_config,
150+
"skip_county": skip_county,
151+
"chunked_matrix": bool(chunked_matrix),
152+
"chunk_size": chunk_size if chunked_matrix else None,
153+
"parallel_matrix": effective_parallel,
154+
"num_matrix_workers": num_matrix_workers if effective_parallel else None,
155+
}
156+
157+
132158
def get_pinned_sha(branch: str) -> str:
133159
"""Get the current tip SHA for a branch from GitHub."""
134160
result = subprocess.run(
@@ -207,6 +233,13 @@ def archive_diagnostics(
207233
PACKAGE_GPU_FUNCTIONS,
208234
)
209235

236+
# Import registers ``build_matrix_chunk_worker`` on ``_calibration_app``
237+
# so a single ``modal deploy modal_app/pipeline.py`` also deploys the
238+
# worker via ``app.include(_calibration_app)`` below. Without this the
239+
# dispatch layer's ``modal.Function.from_name`` lookup would fail at
240+
# runtime.
241+
from modal_app.matrix_chunk_worker import build_matrix_chunk_worker # noqa: E402, F401
242+
210243
app.include(_calibration_app)
211244

212245
from modal_app.local_area import app as _local_area_app # noqa: E402
@@ -767,6 +800,10 @@ def run_pipeline(
767800
run_context: dict | None = None,
768801
modal_app_name: str = "",
769802
modal_environment: str = "",
803+
chunked_matrix: bool = False,
804+
chunk_size: int = 25_000,
805+
parallel_matrix: bool = False,
806+
num_matrix_workers: int = 50,
770807
) -> str:
771808
"""Run the full pipeline end-to-end.
772809
@@ -792,6 +829,15 @@ def run_pipeline(
792829
run_context: Serialized run context from the launcher workflow.
793830
modal_app_name: Deployed Modal app name for this run.
794831
modal_environment: Modal environment used for this run.
832+
chunked_matrix: Build the calibration matrix in clone-household
833+
chunks instead of the non-chunked path. Opt-in; default off.
834+
chunk_size: Clone-household columns per chunk when
835+
``chunked_matrix`` is True.
836+
parallel_matrix: Fan chunked matrix building across Modal
837+
workers via ``build_matrix_chunk_worker``. Only meaningful
838+
when ``chunked_matrix`` is True; ignored otherwise.
839+
num_matrix_workers: Number of Modal workers when
840+
``parallel_matrix`` is True.
795841
796842
Returns:
797843
The run ID for use with promote.
@@ -1030,12 +1076,16 @@ def run_pipeline(
10301076
"database": _artifacts_dir(run_id) / "policy_data.db",
10311077
}
10321078
)
1033-
package_parameters = {
1034-
"workers": num_workers,
1035-
"n_clones": n_clones,
1036-
"target_config": None,
1037-
"skip_county": True,
1038-
}
1079+
package_parameters = _calibration_package_parameters(
1080+
workers=num_workers,
1081+
n_clones=n_clones,
1082+
target_config=None,
1083+
skip_county=True,
1084+
chunked_matrix=chunked_matrix,
1085+
chunk_size=chunk_size,
1086+
parallel_matrix=parallel_matrix,
1087+
num_matrix_workers=num_matrix_workers,
1088+
)
10391089
package_reuse = _step_reusable(
10401090
meta,
10411091
BUILD_CALIBRATION_PACKAGE,
@@ -1068,6 +1118,13 @@ def run_pipeline(
10681118
workers=num_workers,
10691119
n_clones=n_clones,
10701120
run_id=run_id,
1121+
modal_app_name=current_run_context.modal_app_name,
1122+
modal_environment=current_run_context.modal_environment,
1123+
pipeline_volume_name=current_run_context.pipeline_volume_name,
1124+
chunked_matrix=chunked_matrix,
1125+
chunk_size=chunk_size,
1126+
parallel_matrix=parallel_matrix,
1127+
num_matrix_workers=num_matrix_workers,
10711128
)
10721129
print(f" Package at: {pkg_path}")
10731130

0 commit comments

Comments
 (0)