Skip to content

Commit 615e22e

Browse files
excelle08facebook-github-bot
authored andcommitted
Expose driver pipeline depth as a benchpress job parameter
Reviewed By: YifanYuan3 Differential Revision: D113146808
1 parent 2110f2c commit 615e22e

4 files changed

Lines changed: 101 additions & 19 deletions

File tree

benchpress/config/jobs.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@
502502
- '--rpc-fanout-scale={rpc_fanout_scale}'
503503
- '--server-zstd={server_zstd}'
504504
- '--sla-p95-ms={sla_p95_ms}'
505+
- '--depth={depth}'
505506
- '{extra_args}'
506507
vars:
507508
# Hardcode num_instances=1: this job exists specifically for single-instance
@@ -534,6 +535,12 @@
534535
- 'rpc_fanout_scale=0.05'
535536
- 'server_zstd=0'
536537
- 'sla_p95_ms=700'
538+
# Driver pipeline depth (max outstanding requests per driver connection).
539+
# Default 1. Raise (e.g. 2) if the final phase saturates neither CPU nor SLA
540+
# latency (final p95 well below sla_p95_ms while CPU util < ~90%) — often
541+
# needed on high-perf ARM cores. With adaptive depth on (the default), this is
542+
# the starting floor the peak search raises from; see README "Driver depth".
543+
- 'depth=1'
537544
- 'extra_args='
538545
hooks:
539546
- hook: cpu-mpstat
@@ -592,6 +599,7 @@
592599
- '--rpc-fanout-scale={rpc_fanout_scale}'
593600
- '--server-zstd={server_zstd}'
594601
- '--sla-p95-ms={sla_p95_ms}'
602+
- '--depth={depth}'
595603
- '{extra_args}'
596604
vars:
597605
- 'num_instances=-1'
@@ -635,6 +643,12 @@
635643
- 'rpc_fanout_scale=0.05'
636644
- 'server_zstd=0'
637645
- 'sla_p95_ms=700'
646+
# Driver pipeline depth (max outstanding requests per driver connection).
647+
# Default 1. Raise (e.g. 2) if the final phase saturates neither CPU nor SLA
648+
# latency (final p95 well below sla_p95_ms while CPU util < ~90%) — often
649+
# needed on high-perf ARM cores. With adaptive depth on (the default), this is
650+
# the starting floor the peak search raises from; see README "Driver depth".
651+
- 'depth=1'
638652
- 'extra_args='
639653
hooks:
640654
- hook: cpu-mpstat
@@ -695,6 +709,7 @@
695709
- '--rpc-fanout-scale={rpc_fanout_scale}'
696710
- '--server-zstd={server_zstd}'
697711
- '--sla-p95-ms={sla_p95_ms}'
712+
- '--depth={depth}'
698713
- '{extra_args}'
699714
vars:
700715
- 'num_instances=-1'
@@ -735,6 +750,12 @@
735750
- 'rpc_fanout_scale=0.05'
736751
- 'server_zstd=0'
737752
- 'sla_p95_ms=700'
753+
# Driver pipeline depth (max outstanding requests per driver connection).
754+
# Default 1. Raise (e.g. 2) if the final phase saturates neither CPU nor SLA
755+
# latency (final p95 well below sla_p95_ms while CPU util < ~90%) — often
756+
# needed on high-perf ARM cores. With adaptive depth on (the default), this is
757+
# the starting floor the peak search raises from; see README "Driver depth".
758+
- 'depth=1'
738759
- 'extra_args='
739760
hooks:
740761
- hook: copymove

packages/feedsim/README.md

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ taskset -c 0-15 ./benchpress_cli.py install feedsim_dlrm
5555
Unlike FeedSim v1 which spawns a new FeedSim instance per 100 CPU cores,
5656
`feedsim_dlrm` is pinned to **one FeedSim instance per host** because the
5757
redesigned threading model in FeedSim v2 has overcome the scalability issue
58-
on ultra-high-core-count CPUs and ARM CPUs.
58+
on ultra-high-core-count CPUs and ARM CPUs.
5959

6060
The runner searches for the QPS that keeps 95th-percentile end-to-end
6161
latency at or below **700 ms**. When it converges it runs a final 5-minute
@@ -64,7 +64,7 @@ counters) during that final window. We expect the total wall-clock runtime
6464
to be around 30 minutes.
6565

6666
Please make sure to turn CPU turbo-boost on before starting, or FeedSim may
67-
fail to converge and report a low QPS.
67+
fail to converge and report a low QPS.
6868

6969
### Result report
7070

@@ -211,7 +211,7 @@ feedsim server, driver and mock_services instances.
211211

212212
2. Use the `feedsim_autoscale_dlrm` job. This autoscale job will spawn `ceil(nproc / 100)`
213213
FeedSim instances, each pinned to its own CPU range via `taskset`, plus one driver
214-
and one `mock_services` process per instance (also `taskset`-isolated). For example:
214+
and one `mock_services` process per instance (also `taskset`-isolated). For example:
215215
```
216216
./benchpress_cli.py run feedsim_autoscale_dlrm
217217
```
@@ -220,6 +220,41 @@ In multi-instance mode, the overall QPS is the sum across all instances. and the
220220
average latency will be the average of p95 latency values observed across all
221221
instances.
222222

223+
### Driver depth (fixing CPU/latency under-utilization)
224+
225+
The `depth` parameter sets the driver's pipeline depth — the maximum number of
226+
outstanding (in-flight) requests per driver connection. The driver's total
227+
offered concurrency is `driver_threads × connections × depth`, so with the
228+
default `depth=1` the driver can cap the achievable load below what the server
229+
can actually handle.
230+
231+
**Increase `depth` beyond 1 when the final benchmarking phase saturates neither
232+
CPU nor latency** — i.e. the final achieved p95 latency is well below the SLA
233+
limit (`sla_p95_ms`, default 700 ms) *and* the CPU utilization during the final
234+
5-minute benchmarking phase is less than ~90%. In that situation the reported QPS
235+
is limited by driver concurrency rather than by the server, so it understates the
236+
hardware's true capacity. Raising `depth` (start with `2`) lets the driver offer
237+
more concurrent load until the server becomes the bottleneck — either CPU-bound
238+
(~100% utilization) or latency-bound (p95 ≈ SLA). **This is likely necessary on
239+
high-performance ARM cores** (e.g. NVIDIA Grace), which can otherwise sit at
240+
80–90% CPU with p95 far below the SLA at `depth=1`.
241+
242+
```
243+
# Force driver depth 2
244+
./benchpress_cli.py run feedsim_dlrm -i '{"depth": 2}'
245+
```
246+
247+
There is also an **adaptive depth** mechanism (on by default) that raises the
248+
depth automatically during the peak-finding stage until the server saturates
249+
(system CPU ≥ 95% or p95 ≥ SLA). It catches *severe* under-utilization early, but
250+
because it evaluates saturation on the high-load peak/search probes rather than
251+
on the final SLA-converged operating point, it **may not catch all
252+
under-utilization cases**. If you still observe under-utilization in the final
253+
result (low CPU + p95 well under SLA), increase `depth` manually as above. When
254+
adaptive depth is on, a manually-set `depth` acts as the starting floor the
255+
adaptive search raises from; to pin an exact fixed depth, also set the
256+
`FEEDSIM_ADAPTIVE_DEPTH_MAX=0` environment variable to disable adaptive search.
257+
223258
### Other parameters
224259

225260
This section lists additional parameters in `feedsim_dlrm` benchmark. These parameters
@@ -233,6 +268,7 @@ Job-level parameters (can be passed via `-i` flag in Benchpress CLI):
233268
|---|---|---|
234269
| `num_instances` | Number of FeedSim instances to run in parallel. Defaults to 1 in `feedsim_dlrm`; set to -1 to autoscale for `feedsim_autoscale_dlrm`. | `1` |
235270
| `sla_p95_ms` | SLA target in ms. The runner searches for the highest QPS keeping p95 ≤ this. | `700` |
271+
| `depth` | Driver pipeline depth (max outstanding requests per connection; total in-flight = `driver_threads × connections × depth`). Raise (e.g. `2`) when the final phase saturates neither CPU nor latency — often needed on high-perf ARM. See [Driver depth](#driver-depth-fixing-cpulatency-under-utilization). | `1` |
236272
| `io_dist` | I/O latency distribution: `fixed`, `exponential`, or `lognormal`. | `fixed` |
237273
| `io_mean` | Mean I/O latency in ms. | `200` |
238274
| `workload` | Ranking workload: `pagerank` or `dlrm`. `dlrm` is v2. | `dlrm` |

packages/feedsim/run.sh

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ Usage: ${0##*/} [OPTION]...
120120
--rpc-fanout-scale Scale factor applied to per-session fanout counts. Default: 0.05 (t43 c7).
121121
--server-zstd Enable ZSTD compression on server-side response payloads (0=off, 1=on). Default: 0 (t43 c7).
122122
--sla-p95-ms search_qps SLA target (95th percentile latency in ms). Default: 700.
123+
--depth Driver pipeline depth: max outstanding requests per driver connection (max in-flight = driver_threads * connections * depth). Default: 1 (or \$FEEDSIM_DRIVER_DEPTH). Raise (e.g. 2) when the final phase saturates neither CPU nor SLA latency; with adaptive depth on, this is the starting floor the peak search raises from.
123124
EOF
124125
}
125126

@@ -316,6 +317,12 @@ main() {
316317
local sla_p95_ms
317318
sla_p95_ms="700"
318319

320+
# Driver pipeline depth (max outstanding requests per driver connection).
321+
# Env var FEEDSIM_DRIVER_DEPTH is the fallback default; the --depth CLI flag
322+
# (forwarded from the benchpress `depth` job parameter) overrides it.
323+
local driver_depth
324+
driver_depth="${FEEDSIM_DRIVER_DEPTH:-1}"
325+
319326
if [ -z "$IS_AUTOSCALE_RUN" ]; then
320327
echo > $BREPS_LFILE
321328
fi
@@ -644,6 +651,13 @@ main() {
644651
--sla-p95-ms=*)
645652
sla_p95_ms="${1#*=}"
646653
;;
654+
--depth)
655+
driver_depth="$2"
656+
shift
657+
;;
658+
--depth=*)
659+
driver_depth="${1#*=}"
660+
;;
647661
-h|--help)
648662
show_help >&2
649663
exit 1
@@ -1002,7 +1016,9 @@ main() {
10021016
# to reach a real bound instead of capping on driver concurrency (the t19
10031017
# anti-pattern where big boxes sat at ~80% CPU with p95 far below SLA).
10041018
# Enabled by default up to depth 8; set FEEDSIM_ADAPTIVE_DEPTH_MAX=0 to
1005-
# disable and fall back to the fixed FEEDSIM_DRIVER_DEPTH (default 1).
1019+
# disable and use the fixed driver_depth (--depth flag / FEEDSIM_DRIVER_DEPTH,
1020+
# default 1). When adaptive is on, driver_depth is the STARTING floor the peak
1021+
# search raises from (search_qps reads the --depth we pass below).
10061022
sqps_adaptive_arg=""
10071023
adaptive_depth_max="${FEEDSIM_ADAPTIVE_DEPTH_MAX:-8}"
10081024
if [ "$adaptive_depth_max" != "0" ]; then
@@ -1019,7 +1035,7 @@ main() {
10191035
--monitor_port "$client_monitor_port" \
10201036
--threads="${driver_threads}" \
10211037
--connections=4 \
1022-
--depth="${FEEDSIM_DRIVER_DEPTH:-1}" \
1038+
--depth="${driver_depth}" \
10231039
$client_feature_opts \
10241040
$silesia_opts \
10251041
$req_size_opts
@@ -1032,7 +1048,7 @@ main() {
10321048
$driver_bin \
10331049
--monitor_port "$client_monitor_port" \
10341050
--server "0.0.0.0:$port" \
1035-
--depth="${FEEDSIM_DRIVER_DEPTH:-1}" \
1051+
--depth="${driver_depth}" \
10361052
$client_feature_opts \
10371053
$silesia_opts \
10381054
$req_size_opts
@@ -1061,7 +1077,7 @@ main() {
10611077
--monitor_port "$client_monitor_port" \
10621078
--threads="${num_workers}" \
10631079
--connections="${num_connections}" \
1064-
--depth="${FEEDSIM_DRIVER_DEPTH:-1}" \
1080+
--depth="${driver_depth}" \
10651081
$client_feature_opts \
10661082
$silesia_opts \
10671083
$req_size_opts

packages/feedsim/third_party/src/scripts/search_qps.sh

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,11 @@ mutilate (EuroSys \'14) [https://github.com/leverich/mutilate]
120120
-P PID of the process to log runtime breakdowns. Optional
121121
-B Folder to log runtime breakdowns. Optional
122122
-D Adaptive depth: max driver pipeline depth. When set, the peak
123-
phase raises the driver's --depth from 1 until the server is
124-
saturated (system CPU >= 95% OR achieved p95 >= SLA), then holds
125-
that depth for the QPS search. Overrides any --depth in the
126-
driver command. Optional.
123+
phase raises the driver's --depth until the server is saturated
124+
(system CPU >= 95% OR achieved p95 >= SLA), then holds that depth
125+
for the QPS search. The search STARTS from any --depth in the
126+
driver command (default 1), so a manually-set --depth acts as a
127+
floor. Optional.
127128
EOF
128129
}
129130

@@ -394,12 +395,18 @@ fi
394395
# remaining argument is loadtest command
395396
command=$@
396397

397-
# In adaptive-depth mode, search_qps owns the driver's --depth: strip any fixed
398-
# --depth from the command so our per-attempt --depth is the only one, and start
399-
# the peak search at depth=1.
398+
# In adaptive-depth mode, search_qps owns the driver's --depth: capture any fixed
399+
# --depth as the STARTING depth (so a manually-set --depth acts as a floor the
400+
# peak search raises from), then strip it so our per-attempt --depth is the only
401+
# one on the command. Default start is depth=1 (unchanged behavior).
402+
adaptive_start_depth=1
400403
if [ -n "$adaptive_depth_max" ]; then
404+
fixed_depth=$(echo "$command" | grep -oE -- '--depth=[0-9]+' | head -1 | grep -oE '[0-9]+')
405+
if [ -n "$fixed_depth" ] && [ "$fixed_depth" -gt 1 ]; then
406+
adaptive_start_depth=$fixed_depth
407+
fi
401408
command=$(echo "$command" | sed -E 's/[[:space:]]*--depth=[0-9]+//g')
402-
adaptive_depth_arg="--depth=1"
409+
adaptive_depth_arg="--depth=$adaptive_start_depth"
403410
fi
404411

405412
# make sure latency_type and latency_target are specified
@@ -553,12 +560,14 @@ fi
553560
benchreps_tell_state "before peak_qps"
554561
if [ -n "$adaptive_depth_max" ]; then
555562
# Adaptive depth: the peak load test offers at most threads*connections*depth
556-
# concurrent requests. Starting at depth=1, keep raising depth (and re-running
557-
# peak) until the server saturates — system CPU >= 95% OR achieved p95 >= SLA
563+
# concurrent requests. Starting at adaptive_start_depth, keep raising depth (and
564+
# re-running peak) until the server saturates — system CPU >= 95% OR p95 >= SLA
558565
# — so platforms that need more offered concurrency reach a real bound instead
559566
# of capping on driver concurrency (the t19 anti-pattern). The selected depth
560-
# is then held for the QPS search / tuning / final phases.
561-
cur_depth=1
567+
# is then held for the QPS search / tuning / final phases. The starting depth
568+
# is the fixed --depth from the driver command (default 1), so a manually-set
569+
# depth raises the floor.
570+
cur_depth=$adaptive_start_depth
562571
while : ; do
563572
adaptive_depth_arg="--depth=$cur_depth"
564573
# Sample system CPU busy% over a mid-run window while the peak load runs.

0 commit comments

Comments
 (0)