Repository navigation
Benchmark sharding basic functionality #1813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
cmdupuis3
wants to merge
58
commits into
UXARRAY:main
Choose a base branch
from
cmdupuis3:cmd/bench_shards
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
58 commits
Select commit
Hold shift + click to select a range
1c7665d
Cached benchmark IO sketch
cmdupuis3 787e2d4
benchmark debugging
cmdupuis3 96ce618
Sample large benchmarks fewer times
cmdupuis3 4060897
Temp fork/thread speedup for connectivity. REEVALUATE OR REMOVE WHEN …
cmdupuis3 7ab239d
Cache benchmark sampling across forks too
cmdupuis3 c63676c
Per-resolution async benchmarks
cmdupuis3 85f7c0c
Benchmark IO caching fixes
cmdupuis3 9cd8fa8
cached IO benchmarks deslopping
cmdupuis3 b1a6be6
cached IO deslop global variables
cmdupuis3 41f68b2
bench cached IO: more global variable deslopping
cmdupuis3 4dad004
Prime the fixture cache before asv run, not during it
cmdupuis3 60cf1db
Merge branch 'main' into cmd/bench_io
cmdupuis3 ec83767
Lazy neighborhood filter kernel compilation
cmdupuis3 8564410
Lazy nb kernels with functools cache instead
cmdupuis3 7127726
Move kernels inside
cmdupuis3 d1ab4e0
merge cmd/lazy_nb_kernels to cmd/bench_io
cmdupuis3 c00fd1d
Cached IO: try to impose more CI thread safety
cmdupuis3 526e320
Cached IO: lazy interpreter warming; NetCDF warming
cmdupuis3 a064b30
Cached IO: configuration tweaks
cmdupuis3 b17b7a5
Merge branch 'main' into cmd/bench_io
cmdupuis3 a0f4a80
Partially revert a064b30, add cpu info dump
cmdupuis3 f54d634
Cache the asv environment and fixtures, and report durations
cmdupuis3 8f66e30
Fix 'run benchmark' action for manual runs
cmdupuis3 3b46b08
Cache the asv environment and fixtures on main too
cmdupuis3 04f96f2
Split the suite into shards of roughly equal cost
cmdupuis3 f9e5546
ASV workflow branch for pre-caching IO
cmdupuis3 966e5a8
ASV benchmarks skip existing commits
cmdupuis3 6ad7a7f
ASV diff against merge base rather than main
cmdupuis3 d472982
ASV multithreading
cmdupuis3 dbbd6ca
Merge branch 'UXARRAY:main' into cmd/bench_io
cmdupuis3 aaf1dd8
Merge branch 'cmd/bench_io' into cmd/bench_shards
cmdupuis3 5114500
Generalize caching across machine names
cmdupuis3 4f044ff
Fully async sharding (?)
cmdupuis3 8da3f54
Benchmark sharding fix
cmdupuis3 f7d8118
Sharding fix 2
cmdupuis3 99c49b5
Rework shard partitioning
cmdupuis3 8428e1d
Load balancing and removing thread sweeps
cmdupuis3 6bcf1e7
HPC benchmark scipts
cmdupuis3 63dfedb
HPC bugs
cmdupuis3 4803894
Benchmark machine names
cmdupuis3 6a4882d
Thread/core numbers for benchmarks
cmdupuis3 cd8d5ed
ASV machine bug
cmdupuis3 98e9c9d
benchmark shard bug
cmdupuis3 8066798
Merge main into cmd/bench_io
cmdupuis3 f417df8
Cached benchmarks IO deslop p1
cmdupuis3 7bb949a
Cached benchmark IO deslop p2
cmdupuis3 353805c
Cached benchmark IO deslop p3
cmdupuis3 937fb06
Merge branch 'main' into cmd/bench_io
cmdupuis3 152e418
Merge branch 'main' into cmd/bench_io
cmdupuis3 5cfac6d
Merge origin/main into cmd/bench_shards
cmdupuis3 7c1a1cc
Merge cmd/bench_io into cmd/bench_shards
cmdupuis3 2739e6f
Benchmark shards: asv run instead of asv continuous
cmdupuis3 cc1d850
Drop merge leftovers in gcagca and mpas_ocean benchmarks
cmdupuis3 aa5a267
Condense comments and docstrings added on the benchmark sharding branch
cmdupuis3 189e78f
Trim neighborhood benchmark radii
cmdupuis3 dc3df00
Simplify the benchmark sharding helpers, workflow and HPC scripts
cmdupuis3 d136d95
Remove hpc scripts (maybe re-add on a new branch)
cmdupuis3 c88d68d
Build neighborhood benchmark setups once per process; seed PR duratio…
cmdupuis3 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,67 +12,241 @@ on: | |
| pull_request: | ||
| types: [opened, reopened, synchronize, labeled] | ||
| workflow_dispatch: | ||
| inputs: | ||
| base_ref: | ||
| description: >- | ||
| Branch, tag or commit to compare against, via its merge-base with the | ||
| dispatched ref (so name the branch a topic branch will merge into). | ||
| required: false | ||
| default: main | ||
| shards: | ||
| description: >- | ||
| Runners to split the suite over. Each pays a fixed ~1 min (env | ||
| restore, install, numba warmup), so past about four gains little. | ||
| required: false | ||
| default: "4" | ||
|
|
||
| env: | ||
| PR_HEAD_LABEL: ${{ github.event.pull_request.head.label }} | ||
| ASV_DIR: "./benchmarks" | ||
| CONDA_ENV_FILE: ci/environment.yml | ||
| # Shared by every shard so their results merge under one machine. | ||
| ASV_MACHINE: gh-linux-x64 | ||
| SHARDS: ${{ github.event.inputs.shards || '4' }} | ||
|
|
||
| jobs: | ||
| benchmark: | ||
| setup: | ||
| name: Setup | ||
| if: ${{ contains(github.event.pull_request.labels.*.name, 'run-benchmark') && github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} | ||
| name: Linux | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| ASV_DIR: "./benchmarks" | ||
| CONDA_ENV_FILE: ci/environment.yml | ||
|
|
||
| outputs: | ||
| base: ${{ steps.base.outputs.sha }} | ||
| shards: ${{ steps.plan.outputs.shards }} | ||
| steps: | ||
| - uses: actions/checkout@v7 | ||
| - &checkout | ||
| uses: actions/checkout@v7 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
|
|
||
| - name: Record CPU topology | ||
| # A diagnostic; never fail the job over it. | ||
| run: | | ||
| # A diagnostic; never fail the job over it. | ||
| lscpu | grep -E 'Model name|^CPU\(s\):|Thread\(s\) per core|Core\(s\) per socket|Socket\(s\)|CPU max MHz' || lscpu || true | ||
|
|
||
| - name: Set up Conda environment | ||
| - &conda | ||
| name: Set up Conda environment | ||
| uses: mamba-org/setup-micromamba@v3 | ||
| with: | ||
| environment-file: ${{env.CONDA_ENV_FILE}} | ||
| cache-environment: true | ||
| environment-name: uxarray_build | ||
| cache-environment-key: "${{runner.os}}-${{runner.arch}}-py${{env.PYTHON_VERSION}}-${{env.TODAY}}-${{hashFiles(env.CONDA_ENV_FILE)}}-benchmark" | ||
| cache-environment-key: "${{runner.os}}-${{runner.arch}}-${{hashFiles(env.CONDA_ENV_FILE)}}-benchmark" | ||
| create-args: >- | ||
| asv | ||
| python-build | ||
| mamba | ||
|
|
||
| - name: Resolve the baseline commit | ||
| id: base | ||
| # pull_request.* expressions are empty on workflow_dispatch. | ||
| env: | ||
| BASE: ${{ github.event.pull_request.base.sha }} | ||
| BASE_REF: ${{ github.event.inputs.base_ref }} | ||
| run: | | ||
| set -ex | ||
| if [ -z "$BASE" ]; then | ||
| BASE=$(git merge-base HEAD "origin/$BASE_REF" 2>/dev/null || git merge-base HEAD "$BASE_REF") | ||
| fi | ||
| # Dispatched from the base itself: compare against the commit before. | ||
| [ "$BASE" != "$GITHUB_SHA" ] || BASE=$(git rev-parse HEAD^) | ||
| echo "sha=$BASE" >> "$GITHUB_OUTPUT" | ||
|
|
||
| # asv rebuilds its own env under benchmarks/env/ each run; caching skips the | ||
| # solve. No restore-keys: asv reuses a restored env without checking it. | ||
| - name: Cache asv environment | ||
| - &asv-env | ||
| name: Cache asv's benchmark environment | ||
| uses: actions/cache@v6 | ||
| with: | ||
| path: ${{ env.ASV_DIR }}/env | ||
| key: "asv-env-${{runner.os}}-${{runner.arch}}-${{hashFiles(env.CONDA_ENV_FILE, 'benchmarks/asv.conf.json')}}" | ||
|
|
||
| - name: Run Benchmarks | ||
| - &fixtures | ||
| name: Cache the benchmark fixtures | ||
| uses: actions/cache@v6 | ||
| with: | ||
| path: | | ||
| ${{ env.ASV_DIR }}/oQU*.nc | ||
| ${{ env.ASV_DIR }}/_io_cache | ||
| key: asv-fixtures-${{ runner.os }}-${{ hashFiles('benchmarks/helpers/_fixtures.py') }} | ||
| restore-keys: | | ||
| asv-fixtures-${{ runner.os }}- | ||
|
|
||
| # The env cache key has no commit in it, so on a hit nothing is saved and the | ||
| # wheels setup builds would be lost; cache them (a few MB) for the shards. | ||
| - &wheels | ||
| name: Cache the built wheels | ||
| uses: actions/cache@v6 | ||
| with: | ||
| path: ${{ env.ASV_DIR }}/env/*/asv-build-cache | ||
| key: asv-wheels-${{ runner.os }}-${{ github.run_id }} | ||
|
|
||
| # _partition balances shards by asv's recorded durations; with none it | ||
| # splits by count. Restore-only: the merge job saves the updated tree. A | ||
| # PR's first run falls back to main's, saved by asv-benchmarking.yml. | ||
| - name: Restore recorded durations | ||
| uses: actions/cache/restore@v6 | ||
| with: | ||
| path: ${{ env.ASV_DIR }}/results | ||
| key: asv-results-${{ runner.os }}-${{ github.run_id }} | ||
| restore-keys: | | ||
| asv-results-${{ runner.os }}- | ||
|
|
||
| - name: Pre-build, discover and plan | ||
| id: plan | ||
| shell: bash -l {0} | ||
| id: benchmark | ||
| working-directory: ${{ env.ASV_DIR }} | ||
| env: | ||
| BASE: ${{ steps.base.outputs.sha }} | ||
| # --bench just-discover builds the env and the commit's wheel and writes | ||
| # results/benchmarks.json without running anything. Done once here so a | ||
| # cold cache costs one conda solve, not one per shard. | ||
| run: | | ||
| set -x | ||
| set -ex | ||
| # Fill the fixture cache before asv preimports the suite, which would otherwise build it serially in the forkserver parent | ||
| (cd .. && python -m benchmarks.helpers._fixtures) | ||
| # ID this runner | ||
| asv machine --yes | ||
| echo "Baseline: ${{ github.event.pull_request.base.sha }} (${{ github.event.pull_request.base.label }})" | ||
| echo "Contender: ${GITHUB_SHA} ($PR_HEAD_LABEL)" | ||
| # Run benchmarks for current commit against base | ||
| ASV_OPTIONS="--split --show-stderr" | ||
| asv continuous $ASV_OPTIONS ${{ github.event.pull_request.base.sha }} ${GITHUB_SHA} | ||
| # Save compare results | ||
| asv compare --split ${{ github.event.pull_request.base.sha }} ${GITHUB_SHA} > asv_compare_results.txt | ||
| (cd .. && python -m benchmarks.helpers._machine) | ||
| asv run --bench just-discover "${BASE}^!" | ||
| asv run --bench just-discover "${GITHUB_SHA}^!" | ||
| # Logs the split so a lopsided one is visible without opening each shard. | ||
| PYTHONPATH=.. python -m benchmarks.helpers._partition --shards "$SHARDS" | ||
| echo "shards=[$(seq -s, 0 $((SHARDS - 1)))]" >> "$GITHUB_OUTPUT" | ||
|
|
||
| # The whole tree, not just benchmarks.json, so shards weigh the same durations. | ||
| - name: Upload the discovered suite | ||
| uses: actions/upload-artifact@v7 | ||
| with: | ||
| name: asv-plan | ||
| path: ${{ env.ASV_DIR }}/results | ||
|
|
||
| benchmark: | ||
| name: Shard ${{ matrix.shard }} | ||
| needs: setup | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| # A failed shard still leaves the rest worth merging. | ||
| fail-fast: false | ||
| matrix: | ||
| shard: ${{ fromJSON(needs.setup.outputs.shards) }} | ||
| steps: | ||
| - *checkout | ||
| - *conda | ||
| - *asv-env | ||
| - *fixtures | ||
| - *wheels | ||
|
|
||
| - name: Download the discovered suite | ||
| uses: actions/download-artifact@v8 | ||
| with: | ||
| name: asv-plan | ||
| path: plan | ||
|
|
||
| - name: Run shard | ||
| shell: bash -l {0} | ||
| working-directory: ${{ env.ASV_DIR }} | ||
| env: | ||
| BASE: ${{ needs.setup.outputs.base }} | ||
| SHARD: ${{ matrix.shard }} | ||
| # Partition from setup's plan, not this runner's cache, so all shards split the | ||
| # same suite. Nothing checks they tile it; a mismatch silently skips benchmarks. | ||
| run: | | ||
| set -ex | ||
| (cd .. && python -m benchmarks.helpers._fixtures) | ||
| (cd .. && python -m benchmarks.helpers._machine) | ||
| ASV_ARGS=$(PYTHONPATH=.. python -m benchmarks.helpers._partition \ | ||
| --shards "$SHARDS" --shard "$SHARD" --results ../plan --config asv.conf.json) | ||
| echo "Baseline: $BASE" | ||
| echo "Contender: ${GITHUB_SHA} (${PR_HEAD_LABEL:-$GITHUB_REF_NAME})" | ||
| # asv run, not continuous: continuous exits 1 on a regression, same as a | ||
| # broken run. The merge job does the comparison. | ||
| printf '%s\n' "${GITHUB_SHA}" "$BASE" > "$RUNNER_TEMP/commits.txt" | ||
| # Exit 2 means a benchmark failed, not the run; keep the shard's other | ||
| # results and warn rather than fail. | ||
| status=0 | ||
| asv run --show-stderr -m "$ASV_MACHINE" $ASV_ARGS \ | ||
| "HASHFILE:$RUNNER_TEMP/commits.txt" || status=$? | ||
| if [ "$status" -eq 2 ]; then | ||
| echo "::warning title=Benchmark failures in shard ${SHARD}::asv exited 2; see the failed entries above" | ||
| elif [ "$status" -ne 0 ]; then | ||
| exit "$status" | ||
| fi | ||
|
|
||
| - name: Upload shard results | ||
| if: always() | ||
| uses: actions/upload-artifact@v7 | ||
| with: | ||
| name: asv-shard-${{ matrix.shard }} | ||
| path: ${{ env.ASV_DIR }}/results.shard${{ matrix.shard }} | ||
| if-no-files-found: warn | ||
|
|
||
| merge: | ||
| name: Merge and compare | ||
| needs: [setup, benchmark] | ||
| # Run even if a shard failed: the surviving shards' results are still worth merging. | ||
| if: ${{ always() && needs.setup.result == 'success' }} | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - *checkout | ||
| - *conda | ||
|
|
||
| # No merge-multiple: the shards' results files share names. | ||
| - name: Download the shards | ||
| uses: actions/download-artifact@v8 | ||
| with: | ||
| pattern: asv-shard-* | ||
| path: shards | ||
|
|
||
| - name: Merge and compare | ||
| shell: bash -l {0} | ||
| working-directory: ${{ env.ASV_DIR }} | ||
| env: | ||
| BASE: ${{ needs.setup.outputs.base }} | ||
| run: | | ||
| set -ex | ||
| (cd .. && python -m benchmarks.helpers._machine) | ||
| (cd .. && python -m benchmarks.helpers._merge --out benchmarks/results shards/asv-shard-*) | ||
| asv compare --split --machine "$ASV_MACHINE" "$BASE" "${GITHUB_SHA}" \ | ||
| > asv_compare_results.txt | ||
| cat asv_compare_results.txt | ||
| # Where the time went, and how the next run will split it. | ||
| PYTHONPATH=.. python -m benchmarks.helpers._partition --shards "$SHARDS" || true | ||
|
|
||
| # Keyed per run so setup's prefix restore picks up the newest. | ||
| - name: Save recorded durations for the next run | ||
| if: always() | ||
| uses: actions/cache/save@v6 | ||
| with: | ||
| path: ${{ env.ASV_DIR }}/results | ||
| key: asv-results-${{ runner.os }}-${{ github.run_id }} | ||
|
|
||
| - name: Save PR number | ||
| if: always() | ||
|
|
@@ -81,7 +255,7 @@ jobs: | |
| - uses: actions/upload-artifact@v7 | ||
| if: always() | ||
| with: | ||
| name: asv-benchmark-results-${{ runner.os }} | ||
| name: asv-benchmark-results-Linux | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was this an intentional change? |
||
| path: | | ||
| ${{ env.ASV_DIR }}/results | ||
| ${{ env.ASV_DIR }}/asv_compare_results.txt | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to use pre-built actions here (actions/upload-artifact/merge@v4)?