Add BGL vecS/vecS eps=1e-6 curve to runtime benchmark & plots #10
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
| name: Louvain Benchmark | |
| on: | |
| push: | |
| branches: [main, master] | |
| pull_request: | |
| branches: [main, master] | |
| workflow_dispatch: | |
| concurrency: | |
| group: benchmark-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: write | |
| # ───────────────────────────────────────────────────────────────────────── | |
| # Job graph: | |
| # build ──► correctness ─┐ | |
| # ├► runtime (×4) ─┤ (small, medium, 100k-lfr, 100k-scalefree) | |
| # ├► incremental ─┤ | |
| # └► epsilon ─┴──► visualize (merge + plot + commit) | |
| # ───────────────────────────────────────────────────────────────────────── | |
| jobs: | |
| # ══════════════════════════════════════════════════════════════════════ | |
| # 1. Build all C++ binaries and upload as artifact | |
| # ══════════════════════════════════════════════════════════════════════ | |
| build: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Clone Boost.Graph fork | |
| run: | | |
| git clone --depth 1 --branch feature/louvain-algorithm \ | |
| https://github.com/Becheler/graph.git \ | |
| ${{ github.workspace }}/bgl-fork | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| cmake build-essential libboost-all-dev curl | |
| - name: Prepare gen-louvain source | |
| working-directory: louvain/vendor/gen-louvain | |
| run: bash build.sh | |
| continue-on-error: true | |
| - name: Build all C++ binaries | |
| working-directory: louvain | |
| run: | | |
| mkdir -p build | |
| cd build | |
| cmake ../src \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DBGL_GRAPH_INCLUDE=${{ github.workspace }}/bgl-fork/include \ | |
| -Wno-dev | |
| cmake --build . -j$(nproc) | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: louvain-build | |
| path: louvain/build/ | |
| retention-days: 1 | |
| # ══════════════════════════════════════════════════════════════════════ | |
| # 2a. Non-runtime benchmarks in parallel | |
| # ══════════════════════════════════════════════════════════════════════ | |
| benchmark: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 180 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| suite: [correctness, incremental, epsilon] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Python dependencies | |
| working-directory: louvain | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r ../requirements-common.txt -r requirements.txt | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: louvain-build | |
| path: louvain/build/ | |
| - name: Make binaries executable | |
| run: chmod +x louvain/build/* | |
| - name: Run ${{ matrix.suite }} benchmark | |
| working-directory: louvain | |
| run: | | |
| mkdir -p results | |
| python scripts/benchmark.py --only ${{ matrix.suite }} | |
| - name: Upload ${{ matrix.suite }} results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: results-${{ matrix.suite }} | |
| path: louvain/results/*.csv | |
| retention-days: 30 | |
| # ══════════════════════════════════════════════════════════════════════ | |
| # 2b. Runtime benchmark split by graph size | |
| # ══════════════════════════════════════════════════════════════════════ | |
| runtime: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 180 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - chunk: small | |
| sizes: "1000,5000" | |
| graph_types: "" | |
| - chunk: medium | |
| sizes: "10000,50000" | |
| graph_types: "" | |
| - chunk: 100k-lfr | |
| sizes: "100000" | |
| graph_types: "LFR" | |
| - chunk: 100k-scalefree | |
| sizes: "100000" | |
| graph_types: "ScaleFree" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Python dependencies | |
| working-directory: louvain | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r ../requirements-common.txt -r requirements.txt | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: louvain-build | |
| path: louvain/build/ | |
| - name: Make binaries executable | |
| run: chmod +x louvain/build/* | |
| - name: Run runtime benchmark (${{ matrix.chunk }}) | |
| working-directory: louvain | |
| run: | | |
| mkdir -p results | |
| python scripts/benchmark.py --only runtime \ | |
| --sizes ${{ matrix.sizes }} \ | |
| --output-suffix _${{ matrix.chunk }} \ | |
| ${{ matrix.graph_types != '' && format('--graph-types {0}', matrix.graph_types) || '' }} | |
| - name: Upload runtime ${{ matrix.chunk }} results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: results-runtime-${{ matrix.chunk }} | |
| path: louvain/results/*.csv | |
| retention-days: 30 | |
| # ══════════════════════════════════════════════════════════════════════ | |
| # 3. Merge results, generate plots, and commit | |
| # ══════════════════════════════════════════════════════════════════════ | |
| visualize: | |
| needs: [benchmark, runtime] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Python dependencies | |
| working-directory: louvain | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r ../requirements-common.txt -r requirements.txt | |
| # Download all benchmark CSVs into results/ | |
| - name: Download correctness results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: results-correctness | |
| path: louvain/results/ | |
| continue-on-error: true | |
| - name: Download runtime (small) results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: results-runtime-small | |
| path: louvain/results/ | |
| continue-on-error: true | |
| - name: Download runtime (medium) results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: results-runtime-medium | |
| path: louvain/results/ | |
| continue-on-error: true | |
| - name: Download runtime (100k-lfr) results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: results-runtime-100k-lfr | |
| path: louvain/results/ | |
| continue-on-error: true | |
| - name: Download runtime (100k-scalefree) results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: results-runtime-100k-scalefree | |
| path: louvain/results/ | |
| continue-on-error: true | |
| - name: Download incremental results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: results-incremental | |
| path: louvain/results/ | |
| continue-on-error: true | |
| - name: Download epsilon results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: results-epsilon | |
| path: louvain/results/ | |
| continue-on-error: true | |
| - name: Merge runtime CSV chunks | |
| working-directory: louvain | |
| run: | | |
| python -c " | |
| import pandas as pd, glob, os | |
| parts = sorted(glob.glob('results/runtime_*.csv')) | |
| if parts: | |
| df = pd.concat([pd.read_csv(p) for p in parts], ignore_index=True) | |
| df.to_csv('results/runtime.csv', index=False) | |
| print(f'Merged {len(parts)} runtime chunks into runtime.csv ({len(df)} rows)') | |
| for p in parts: | |
| os.remove(p) | |
| elif os.path.exists('results/runtime.csv'): | |
| print('runtime.csv already present, skipping merge') | |
| else: | |
| print('WARNING: no runtime CSVs found') | |
| " | |
| - name: Generate visualizations | |
| working-directory: louvain | |
| run: python scripts/visualize.py | |
| continue-on-error: true | |
| # compare_passes needs C++ binaries + fork headers to patch & rebuild | |
| - name: Clone Boost.Graph fork | |
| run: | | |
| git clone --depth 1 --branch feature/louvain-algorithm \ | |
| https://github.com/Becheler/graph.git \ | |
| ${{ github.workspace }}/bgl-fork | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| cmake build-essential libboost-all-dev | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: louvain-build | |
| path: louvain/build/ | |
| - name: Make binaries executable | |
| run: chmod +x louvain/build/* | |
| - name: Generate cumulative dQ comparison | |
| working-directory: louvain | |
| env: | |
| BGL_GRAPH_INCLUDE: ${{ github.workspace }}/bgl-fork/include | |
| run: python scripts/compare_passes.py --nodes 10000 --seed 42 | |
| continue-on-error: true | |
| # Commit everything back | |
| - name: Commit updated results | |
| if: github.event_name == 'push' | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add louvain/results/*.csv louvain/results/*.png | |
| git diff --staged --quiet || \ | |
| git commit -m "ci: update benchmark results [skip ci]" && \ | |
| git push | |
| - name: Upload final results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: benchmark-results | |
| path: | | |
| louvain/results/*.csv | |
| louvain/results/*.png | |
| retention-days: 30 |