gem/scripts/analyze-decode-host-overhead.sh
2026-08-30 18:24:55 -06:00

96 lines
3.9 KiB
Bash
Executable file

#!/bin/sh
set -eu
if [ "$#" -ne 1 ] && [ "$#" -ne 2 ]; then
echo "usage: $0 DECODE_PROFILE_JSON [OUTPUT_JSON]" >&2
exit 2
fi
input=$1
output=${2:-}
if [ ! -r "$input" ]; then
echo "gem: decode host-overhead input is not readable: $input" >&2
exit 2
fi
if [ -n "$output" ] && [ -e "$output" ]; then
echo "gem: refusing to overwrite decode host-overhead output: $output" >&2
exit 2
fi
if ! command -v shasum >/dev/null 2>&1; then
echo "gem: shasum is required for analysis provenance" >&2
exit 2
fi
input_sha=$(shasum -a 256 "$input" | awk '{print $1}')
analyze()
{
jq -n --arg input_path "$input" --arg input_sha "$input_sha" \
--slurpfile input "$input" '
def finite_nonnegative: type == "number" and . >= 0 and . < 1e100;
def finite_positive: type == "number" and . > 0 and . < 1e100;
$input[0] as $d | $d.production_execution as $p |
($p.mean_host_prepare_seconds + $p.mean_host_encode_seconds +
$p.mean_host_submit_wait_seconds + $p.mean_host_cleanup_seconds +
$p.mean_host_readback_seconds) as $phase_sum |
if ($d.schema_version == 1 and $d.engine == "gem-native-c-metal" and
$d.workload == "authentic-one-token-decode-stage-profile" and
$d.rows == 1 and $d.repetitions >= 3 and $d.command_buffers == 1 and
$d.dispatches > 0 and ($p.mean_wall_seconds | finite_positive) and
($p.mean_gpu_seconds | finite_positive) and
($p.mean_host_prepare_seconds | finite_nonnegative) and
($p.mean_host_encode_seconds | finite_nonnegative) and
($p.mean_host_submit_wait_seconds | finite_positive) and
($p.mean_host_cleanup_seconds | finite_nonnegative) and
($p.mean_host_readback_seconds | finite_nonnegative) and
$p.mean_gpu_seconds <= $p.mean_wall_seconds and
$p.mean_gpu_seconds <= $p.mean_host_submit_wait_seconds and
(($phase_sum / $p.mean_wall_seconds - 1) | fabs) < 0.001 and
(($p.mean_gpu_seconds / $p.mean_wall_seconds - $p.gpu_wall_fraction) | fabs) < 0.0001 and
(($p.mean_wall_seconds - $p.mean_gpu_seconds -
$p.mean_wall_minus_gpu_seconds) | fabs) < 0.000001 and
($p.wall_seconds_samples | length) == $d.repetitions and
($p.gpu_seconds_samples | length) == $d.repetitions)
then
(100 * $p.mean_wall_minus_gpu_seconds / $p.mean_wall_seconds) as $ceiling |
{
schema_version: 1,
engine: "gem-native-c-metal",
workload: "decode-host-overhead-ceiling-screen",
model: $d.model,
context: $d.context,
position: $d.position,
prefix_mode: $d.prefix_mode,
attention_kernel: $d.attention_kernel,
input: {path: $input_path, sha256: $input_sha},
observed: {
wall_seconds: $p.mean_wall_seconds,
gpu_seconds: $p.mean_gpu_seconds,
wall_minus_gpu_seconds: $p.mean_wall_minus_gpu_seconds,
wall_minus_gpu_ceiling_pct: $ceiling,
phase_sum_seconds: $phase_sum,
prepare_seconds: $p.mean_host_prepare_seconds,
encode_seconds: $p.mean_host_encode_seconds,
submit_wait_seconds: $p.mean_host_submit_wait_seconds,
cleanup_seconds: $p.mean_host_cleanup_seconds,
readback_seconds: $p.mean_host_readback_seconds
},
screening: {
whole_token_floor_pct: 3,
host_axis_admissible: ($ceiling >= 3),
promotion_eligible: false,
interpretation: (if $ceiling >= 3 then
"host/control overhead is large enough to admit one isolated diagnostic"
else
"even eliminating all non-GPU wall time cannot clear the whole-token floor"
end)
}
}
else error("decode host-overhead input fails production-path accounting invariants") end'
}
if [ -n "$output" ]; then
analyze > "$output"
else
analyze
fi