|
| 1 | +<!-- |
| 2 | +Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | +
|
| 4 | +This source code is licensed under the MIT license found in the |
| 5 | +LICENSE file in the root directory of this source tree. |
| 6 | +--> |
| 7 | +# GAPBS (multi-instance) |
| 8 | + |
| 9 | +GAPBS is the [GAP Benchmark Suite](https://github.com/sbeamer/gapbs) — a set of |
| 10 | +graph-analytics kernels (`bc`, `bfs`, `cc`, `pr`, `sssp`, `tc`). This package |
| 11 | +adds `gapbs_multi`, a memory-focused, multi-instance driver: it launches N |
| 12 | +core-pinned gapbs instances of one kernel in parallel against a **pre-built** |
| 13 | +graph, each instance in its own cgroup with per-instance memory limits, and |
| 14 | +aggregates the per-instance `Average Time` (mean / min / max). |
| 15 | + |
| 16 | +It is intended for large-memory / tiered-memory (e.g. CXL) characterization, |
| 17 | +where several graph-analytics instances run side by side under controlled cpu |
| 18 | +and memory budgets. |
| 19 | + |
| 20 | +> **Note:** `gapbs_multi` lives in the `mem` benchmark suite, so every command |
| 21 | +> must pass `-b mem`. |
| 22 | +
|
| 23 | +## Install |
| 24 | + |
| 25 | +``` |
| 26 | +./benchpress_cli.py -b mem install gapbs_multi |
| 27 | +``` |
| 28 | + |
| 29 | +This builds the gapbs kernels + `converter` and copies `run-gapbs-multi.sh` and |
| 30 | +`generate_graph.sh` into `./benchmarks/gapbs/`. |
| 31 | + |
| 32 | +## Generate the graph |
| 33 | + |
| 34 | +`gapbs_multi` never generates graphs at run time — build one once with the |
| 35 | +`generate_graph.sh` helper. The default reproduces `kronecker30_k33.sg` |
| 36 | +(a Kronecker graph with 2^30 vertices and average degree 33, ~350 GB): |
| 37 | + |
| 38 | +``` |
| 39 | +./benchmarks/gapbs/generate_graph.sh -g 30 -k 33 |
| 40 | +``` |
| 41 | + |
| 42 | +The script **aborts unless the output filesystem has at least 500 GB free** |
| 43 | +(override with `--min-free-gb`). Useful options: |
| 44 | + |
| 45 | + - `-g <scale>` / `-k <degree>`: graph size (2^scale vertices, avg degree) |
| 46 | + - `-b <name|file>`: output base name or path (default `kronecker<scale>_k<degree>`) |
| 47 | + - `-d <dir>`: output directory (default `./benchmarks/gapbs`) |
| 48 | + - `--weighted`: build a weighted graph (`.wsg`, required for `sssp`) |
| 49 | + - `--undirected`: symmetrize + `U` suffix (`.U.sg`, required for `tc`) |
| 50 | + - `--min-free-gb <n>`: change the disk-space guard (default 500) |
| 51 | + - `--force`: regenerate even if the target already exists |
| 52 | + |
| 53 | +See `./benchmarks/gapbs/generate_graph.sh -h` for the full list. |
| 54 | + |
| 55 | +## Run |
| 56 | + |
| 57 | +### Recommended job - `gapbs_multi` |
| 58 | + |
| 59 | +``` |
| 60 | +./benchpress_cli.py -b mem run gapbs_multi |
| 61 | +``` |
| 62 | + |
| 63 | +Each instance is launched as a transient `systemd-run --scope`, i.e. its **own |
| 64 | +cgroup**, with `AllowedCPUs` (reserved cores) and `MemoryLow` / `MemoryHigh` / |
| 65 | +`MemoryMax` limits. The kernel then runs on `threads_per_instance` cores (exact |
| 66 | +OpenMP thread count). |
| 67 | + |
| 68 | +> **Root required:** per-instance memory limits need root (to create the scope). |
| 69 | +> Without root, the runner warns and falls back to `taskset` pinning **without** |
| 70 | +> memory limits. |
| 71 | +
|
| 72 | +This job has the following optional parameters (override with `-i '{...}'`): |
| 73 | + |
| 74 | + - `num_instances`: number of parallel instances (default `3`) |
| 75 | + - `bench`: kernel to run — `bc` | `bfs` | `cc` | `pr` | `sssp` | `tc` (default `bc`) |
| 76 | + - `graph_file`: graph base name (no extension) or full `.sg`/`.wsg` path, |
| 77 | + resolved per kernel: `bc/bfs/cc/pr` → `.sg`, `sssp` → `.wsg`, `tc` → `U.sg` |
| 78 | + (default `kronecker30_k33`) |
| 79 | + - `trials`: timed trials, passed to gapbs `-n` (default `2`) |
| 80 | + - `core_start` / `cores_per_instance` / `core_stride`: physical-core layout |
| 81 | + (defaults `0` / `32` / `32`). Counts are **physical cores**; SMT siblings are |
| 82 | + auto-added to each instance's reserved cpuset. |
| 83 | + - `threads_per_instance`: active OpenMP thread count per instance (default `16`) |
| 84 | + - `mem_low` / `mem_high` / `mem_max`: per-instance memory limits, accept human |
| 85 | + sizes (e.g. `290G`) or `max` = unlimited (defaults `290G` / `300G` / `310G`) |
| 86 | + - `extra_args`: passed verbatim to the runner (see below) |
| 87 | + |
| 88 | +Available `extra_args` (also visible via `./benchmarks/gapbs/run-gapbs-multi.sh -h`): |
| 89 | + |
| 90 | + - `--ccx`: bind instance *i* to auto-detected CCX[*i*] (sysfs L3 domain) |
| 91 | + instead of the explicit stride layout |
| 92 | + - `--mem-nodes 0,1`: set `cpuset.mems` / `AllowedMemoryNodes` (e.g. DRAM+CXL) |
| 93 | + - `--no-cgroup`: disable systemd scopes and memory limits (taskset only) |
| 94 | + |
| 95 | +### Examples |
| 96 | + |
| 97 | +Run **4 instances, each in its own cgroup** (needs root; default layout reserves |
| 98 | +physical cores `0-31 / 32-63 / 64-95 / 96-127`, so ≥128 physical cores): |
| 99 | + |
| 100 | +``` |
| 101 | +sudo ./benchpress_cli.py -b mem run gapbs_multi -i '{"num_instances": 4}' |
| 102 | +``` |
| 103 | + |
| 104 | +Run 4 instances on a smaller host (16 reserved cores / 8 threads each): |
| 105 | + |
| 106 | +``` |
| 107 | +sudo ./benchpress_cli.py -b mem \ |
| 108 | + -o 'gapbs_multi: -n 4 -b bc -f kronecker30_k33 -t 2 -c 16 --core-stride 16 -T 8 --mem-low 290G --mem-high 300G --mem-max 310G' \ |
| 109 | + run gapbs_multi |
| 110 | +``` |
| 111 | + |
| 112 | +Bind each instance to a detected CCX and place memory on DRAM+CXL (nodes 0,1): |
| 113 | + |
| 114 | +``` |
| 115 | +sudo ./benchpress_cli.py -b mem run gapbs_multi \ |
| 116 | + -i '{"num_instances": 4, "extra_args": "--ccx --mem-nodes 0,1"}' |
| 117 | +``` |
| 118 | + |
| 119 | +Run the `bfs` kernel with 30 trials: |
| 120 | + |
| 121 | +``` |
| 122 | +sudo ./benchpress_cli.py -b mem run gapbs_multi -i '{"bench": "bfs", "trials": 30}' |
| 123 | +``` |
| 124 | + |
| 125 | +## Core layout |
| 126 | + |
| 127 | +For the default (stride) layout, instance *i* reserves the physical cores |
| 128 | + |
| 129 | +``` |
| 130 | +[core_start + i*core_stride, core_start + i*core_stride + cores_per_instance - 1] |
| 131 | +``` |
| 132 | + |
| 133 | +plus each of those cores' SMT siblings — this becomes the cgroup `AllowedCPUs`. |
| 134 | +The kernel actually runs on only `threads_per_instance` physical cores (one |
| 135 | +logical CPU per core), enforced with `taskset` + `OMP_NUM_THREADS`, matching the |
| 136 | +"reserved cores vs. active threads" split used for graph-analytics runs. |
| 137 | + |
| 138 | +With `--ccx`, the reserved cpuset is instead a full auto-detected CCX (the L3 |
| 139 | +`shared_cpu_list` from sysfs); instance *i* maps to CCX[*i*], and the run fails |
| 140 | +if there are fewer CCXs than instances. |
| 141 | + |
| 142 | +## Reporting and Measurement |
| 143 | + |
| 144 | +`gapbs_multi` prints an aggregate block to stdout and reports it in JSON. The |
| 145 | +headline metric is `average_time` — the **mean** of the per-instance |
| 146 | +`Average Time` values (the runner also prints `average_time_min` / |
| 147 | +`average_time_max` / `per_instance_average_time` for reference): |
| 148 | + |
| 149 | +``` |
| 150 | +=== gapbs_multi aggregate (bc, 4 instances) === |
| 151 | +per_instance_average_time: 3.10 3.22 3.05 3.18 |
| 152 | +average_time_mean=3.137500 |
| 153 | +average_time_min=3.050000 |
| 154 | +average_time_max=3.220000 |
| 155 | +spawned_instances=4 |
| 156 | +successful_instances=4 |
| 157 | +Average Time: 3.137500 |
| 158 | +``` |
| 159 | + |
| 160 | +Result locations: |
| 161 | + |
| 162 | + - Parsed metrics JSON: `benchmark_metrics_<run_id>/gapbs_multi_metrics_<timestamp>_iter_*.json` |
| 163 | + (plus `gapbs_multi_system_specs_<timestamp>.json`), under the benchpress root |
| 164 | + or the directory given by `--artifacts-dir` |
| 165 | + - Run history: `./results` (or the directory given by `-r`) |
| 166 | + - Per-instance raw kernel logs (on the host): `/tmp/gapbs_multi_<bench>/benchlog_inst*.txt` |
| 167 | + |
| 168 | +To collect system / microarchitecture metrics during the run, add hooks with |
| 169 | +`-k`, e.g. `-k cpu-mpstat perf`. These are host-wide, time-window collectors and |
| 170 | +cover all instances for the full duration of the run. |
| 171 | + |
| 172 | +## Runner help |
| 173 | + |
| 174 | +``` |
| 175 | +./benchmarks/gapbs/run-gapbs-multi.sh -h |
| 176 | +``` |
0 commit comments