Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9830ba7
[CI] Add HeCBench to CI
maarquitos14 Aug 17, 2026
ab5ba0c
Fix error.
maarquitos14 Aug 17, 2026
ddefa31
Build and stage hipcc, needed for HeCBench.
maarquitos14 Aug 18, 2026
c9d730d
Set longer timeout
maarquitos14 Aug 18, 2026
ec2d2f5
Match rocm_examples' timeout.
maarquitos14 Aug 18, 2026
9f9c5f9
Fix errors.
maarquitos14 Aug 19, 2026
749e2bd
Add temporary instrumentation to debug benchmark failures
maarquitos14 Aug 27, 2026
76438a0
Merge remote-tracking branch 'origin/amd-staging' into maronas/hecben…
maarquitos14 Aug 27, 2026
971a869
Quarantine benchmark until fix lands upstream
maarquitos14 Aug 27, 2026
404460a
Revert "Add temporary instrumentation to debug benchmark failures"
maarquitos14 Aug 27, 2026
95f4fbc
Remove unused code.
maarquitos14 Aug 28, 2026
c37e3e8
Use single source of truth for log dir.
maarquitos14 Aug 28, 2026
b89c9fb
Use single source of truth for SCRIPTS dir.
maarquitos14 Aug 28, 2026
f8b9726
Trim comments.
maarquitos14 Aug 28, 2026
db1e7f6
Update HeCBench pin
maarquitos14 Aug 28, 2026
9dfd81a
Further reduction
maarquitos14 Aug 28, 2026
d55f160
Merge remote-tracking branch 'origin/amd-staging' into maronas/hecben…
maarquitos14 Aug 28, 2026
feed0c2
Debug slow download step
maarquitos14 Sep 1, 2026
cc38b8e
Revert "Debug slow download step"
maarquitos14 Sep 14, 2026
9281694
Merge remote-tracking branch 'origin/amd-staging' into maronas/hecben…
maarquitos14 Sep 14, 2026
5b443e0
Bump HeCBench pin
maarquitos14 Sep 16, 2026
7381e7c
Merge branch 'amd-staging' into maronas/hecbench-ci
maarquitos14 Sep 16, 2026
bf87888
Update benchmark deps.
maarquitos14 Sep 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
277 changes: 277 additions & 0 deletions .github/hecbench/bench.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
#!/usr/bin/env bash
# Build and run the HeCBench HIP subset for the amdgcnspirv SPIR-V backend,
# self-verifying each benchmark's output. Results land in a bench_logs_* dir;
# the CI "Gate on HeCBench results" step reads those logs.
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPT_NAME="$(basename "$0")"

# shellcheck source=lib/common.sh
source "${SCRIPT_DIR}/lib/common.sh"

# ==============================================================================
# DEFAULTS
# ==============================================================================

# "amdgcnspirv-be" is the user-facing token (log dir suffix, prints); the make
# HIP_ARCH is plain amdgcnspirv, built via the default SPIR-V backend.
ARCH="amdgcnspirv-be"
HIPCC_ARCH="amdgcnspirv"

TIMEOUT_SECONDS=${TIMEOUT_SECONDS:-300}
GPU_ID=${GPU_ID:-0}
BENCHMARK_FILTER=${BENCHMARK_FILTER:-}

show_usage() {
cat <<EOF
Usage: $SCRIPT_NAME --filter LIST [OPTIONS]

Build and run the HeCBench HIP subset for the amdgcnspirv SPIR-V backend.

Options:
--filter LIST Comma-separated benchmark dir names (e.g. dp4a-hip,fft-hip)
--timeout SECONDS Per-benchmark timeout (default: $TIMEOUT_SECONDS)
--gpu-id N ROCR_VISIBLE_DEVICES value (default: $GPU_ID)
--help, -h Show this help

Environment Variables:
ROCM_PATH REQUIRED. Path to ROCm installation.
HECBENCH_SRC Path to HeCBench src (auto-detected if not set)
HIP_CLANG_PATH clang bin dir for hipcc to drive (default: \$ROCM_PATH/bin)

Output:
$HECBENCH_LOG_DIR (CI), else bench_logs_YYYYMMDD_HHMMSS_amdgcnspirv-be/
timings.csv benchmark,build_seconds,run_seconds
success.log built and ran cleanly
failed.log non-zero exit (build or run)
suspect.log exit 0 but output contains validation failures
timeout.log exceeded --timeout
<benchmark>.log per-benchmark combined build+run output
EOF
}

# ==============================================================================
# ARG PARSING
# ==============================================================================

while [[ $# -gt 0 ]]; do
case "$1" in
--help|-h) show_usage; exit 0 ;;
--filter) BENCHMARK_FILTER="$2"; shift 2 ;;
--timeout) TIMEOUT_SECONDS="$2"; shift 2 ;;
--gpu-id) GPU_ID="$2"; shift 2 ;;
*) log_error "Unknown argument: $1"; show_usage; exit 1 ;;
esac
done

if [[ -z "$BENCHMARK_FILTER" ]]; then
log_error "--filter is required"
show_usage
exit 1
fi

# ==============================================================================
# VALIDATION & SETUP
# ==============================================================================

require_rocm_path || exit 1
HECBENCH_SRC=$(find_hecbench_src "$SCRIPT_DIR") || {
log_error "Cannot find HeCBench src directory"
exit 1
}

# CI sets HECBENCH_LOG_DIR (single source of truth); local runs get a timestamp.
LOG_DIR="${HECBENCH_LOG_DIR:-${SCRIPT_DIR}/bench_logs_$(date +%Y%m%d_%H%M%S)_${ARCH}}"
mkdir -p "$LOG_DIR"

export PATH="${ROCM_PATH}/bin:${PATH}"
export LD_LIBRARY_PATH="${ROCM_PATH}/lib:${LD_LIBRARY_PATH:-}"
export HIP_PATH="${ROCM_PATH}"
# HIP_CLANG_PATH points hipcc at the clang to drive; CI sets it to the freshly
# built LLVM bin dir. Unset -> fall back to $ROCM_PATH/bin.
if [[ -n "${HIP_CLANG_PATH:-}" ]]; then
export HIP_CLANG_PATH
export PATH="${HIP_CLANG_PATH}:${PATH}"
export LD_LIBRARY_PATH="$(dirname "${HIP_CLANG_PATH}")/lib:${LD_LIBRARY_PATH}"
fi
# Runtime JIT (comgr) honors this for AMDGCN bitcode lookup; device libs are
# installed at the canonical ROCm layout ${ROCM_PATH}/amdgcn/bitcode.
export HIP_DEVICE_LIB_PATH="${ROCM_PATH}/amdgcn/bitcode"
export ROCR_VISIBLE_DEVICES="$GPU_ID"
ulimit -s unlimited 2>/dev/null || true

# libhipcxx <chrono> hard-errors on amdgcnspirv (no compile-time __gfx*__ macro);
# the define lets it through. NDEBUG keeps host asserts out of timing paths.
declare -a MAKE_ARGS=(
HIP_ARCH="$HIPCC_ARCH"
"EXTRA_CFLAGS=-D_LIBCUDACXX_ALLOW_UNSUPPORTED_ARCHITECTURE -DNDEBUG"
)

echo "benchmark,build_seconds,run_seconds" > "$LOG_DIR/timings.csv"
touch "$LOG_DIR/success.log" \
"$LOG_DIR/failed.log" \
"$LOG_DIR/suspect.log" \
"$LOG_DIR/timeout.log"

log_info "==========================================="
log_info "HeCBench bench (build+run merged)"
log_info "==========================================="
log_info "ROCm path: $ROCM_PATH"
log_info "HeCBench src: $HECBENCH_SRC"
log_info "Arch: $ARCH"
log_info "Timeout: ${TIMEOUT_SECONDS}s"
log_info "GPU ID: $GPU_ID"
log_info "Logs: $LOG_DIR"

# Clear the COMGR JIT cache: keys are the SPIR-V hash, so a runtime-only update
# (same SPIR-V) would otherwise serve stale native code.
if [[ -d "${HOME}/.cache/comgr" ]]; then
log_info "Clearing COMGR cache (${HOME}/.cache/comgr) ..."
rm -rf "${HOME}/.cache/comgr"
fi

echo ""

# ==============================================================================
# PER-BENCHMARK
# ==============================================================================

# check_output_validation() is defined in lib/common.sh.

bench_one() {
local dir="$1"
local name; name=$(basename "$dir")
local log="$LOG_DIR/${name}.log"

# Reclaim leaked OpenMPI/RCCL backing files in /dev/shm so an MPI benchmark
# whose predecessor was SIGKILL'd doesn't fail with "not enough space".
cleanup_stale_shm

cd "$dir" || { log_error "$name: cannot cd to $dir"; return; }

# Clean to ensure a deterministic build state.
make clean &>/dev/null || true

local build_start build_elapsed run_start run_elapsed rc

# ---- Phase 1: BUILD (default target only) ----
build_start=$(date +%s.%N)
set +e
timeout "$TIMEOUT_SECONDS" make "${MAKE_ARGS[@]}" &>"$log"
rc=$?
set -e
build_elapsed=$(awk "BEGIN {printf \"%.3f\", $(date +%s.%N) - $build_start}")

if [[ $rc -ne 0 ]]; then
if [[ $rc -eq 124 ]]; then
log_error "Timeout (build): $name (>${TIMEOUT_SECONDS}s)"
echo "$name" >> "$LOG_DIR/timeout.log"
else
log_error "Failed (build): $name (exit $rc)"
echo "$name" >> "$LOG_DIR/failed.log"
fi
cd "$SCRIPT_DIR"
return
fi

# ---- Phase 2: RUN (no make overhead) ----
# Ask the Makefile what `make run` runs (binary already built, so -n just
# prints); join backslash-continuation lines into whole commands.
local -a runcmds=()
local accum=""
while IFS= read -r line; do
if [[ "$line" == *'\' ]]; then
accum+="${line%\\} "
else
accum+="$line"
[[ -n "$accum" ]] && runcmds+=("$accum")
accum=""
fi
done < <(make -n run "${MAKE_ARGS[@]}" 2>/dev/null)
[[ -n "$accum" ]] && runcmds+=("$accum")

if [[ ${#runcmds[@]} -eq 0 ]]; then
log_error "Failed: $name (no run commands found)"
echo "$name" >> "$LOG_DIR/failed.log"
cd "$SCRIPT_DIR"
return
fi

run_start=$(date +%s.%N)
set +e
rc=0
for cmd in "${runcmds[@]}"; do
echo "+ $cmd" >>"$log"
timeout "$TIMEOUT_SECONDS" bash -c "$cmd" &>>"$log" 2>&1
rc=$?
[[ $rc -ne 0 ]] && break
done
set -e
run_elapsed=$(awk "BEGIN {printf \"%.3f\", $(date +%s.%N) - $run_start}")

if [[ $rc -eq 0 ]]; then
local time_detail="build ${build_elapsed}s, run ${run_elapsed}s"
if check_output_validation "$log" >/dev/null; then
log_success "$name (${time_detail})"
echo "$name" >> "$LOG_DIR/success.log"
else
log_warn "$name (${time_detail}) — exit 0 but output validation suspect"
echo "$name" >> "$LOG_DIR/suspect.log"
fi
echo "$name,$build_elapsed,$run_elapsed" >> "$LOG_DIR/timings.csv"
elif [[ $rc -eq 124 ]]; then
log_error "Timeout (run): $name (>${TIMEOUT_SECONDS}s)"
echo "$name" >> "$LOG_DIR/timeout.log"
else
log_error "Failed (run): $name (exit $rc)"
echo "$name" >> "$LOG_DIR/failed.log"
fi

cd "$SCRIPT_DIR"
}

# ==============================================================================
# DISCOVER & ITERATE
# ==============================================================================

declare -a dirs=()
IFS=',' read -ra wanted <<< "$BENCHMARK_FILTER"
for w in "${wanted[@]}"; do
w="${w## }"; w="${w%% }"
[[ -z "$w" ]] && continue
local_dir="$HECBENCH_SRC/$w"
[[ -d "$local_dir" ]] && dirs+=("$local_dir")
done
if [[ ${#dirs[@]} -eq 0 ]]; then
log_error "Filter matched no benchmarks: $BENCHMARK_FILTER"
exit 1
fi

log_info "Processing ${#dirs[@]} benchmarks..."
echo ""

for d in "${dirs[@]}"; do
bench_one "$d"
done

# ==============================================================================
# SUMMARY
# ==============================================================================

count() {
local f="$LOG_DIR/$1"
[[ -f "$f" ]] && wc -l <"$f" | tr -d ' ' || echo 0
}

echo ""
log_info "==========================================="
log_info "Summary"
log_info "==========================================="
log_info " Success: $(count success.log)"
log_info " Suspect: $(count suspect.log) (exit 0 but output has failures)"
log_info " Failed: $(count failed.log)"
log_info " Timeout: $(count timeout.log)"
log_info ""
log_info "Logs: $LOG_DIR"
log_info "Timings: $LOG_DIR/timings.csv"
78 changes: 78 additions & 0 deletions .github/hecbench/ci_benchmarks.deps.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# GENERATED by update_deps.sh — do not edit by hand.
# In-tree HeCBench dirs referenced (transitively) via '../' by the benchmarks in
# ci_benchmarks.txt: sibling *-cuda data dirs, shared include/, etc. The
# test_hecbench CI job checks these out alongside the benchmarks so their builds
# resolve. Regenerate with .github/hecbench/update_deps.sh (see that script).
accuracy-cuda
ace-cuda
adam-cuda
adamw-cuda
addBiasQKV-cuda
affine-cuda
atomicPerf-cuda
atomicReduction-cuda
backprop-cuda
base64e-cuda
blockAccess-cuda
boxfilter-sycl
ccsd-trpdrv-cuda
channelSum-cuda
che-cuda
cobahh-cuda
complex-cuda
damage-cuda
data
debayer-sycl
dpid-cuda
dxtc2-sycl
easyWave-omp
ecdh-cuda
extend2-sycl
extrema-cuda
fft-cuda
fpdc-cuda
fwt-cuda
gabor-cuda
ga-cuda
groupnorm-cuda
hellinger-cuda
idivide-cuda
inversek2j-sycl
is-cuda
kiss-cuda
laplace3d-cuda
ldpc-cuda
log2-cuda
lud-cuda
marchingCubes-cuda
medianfilter-cuda
medianfilter-sycl
mis-cuda
mrc-cuda
mr-cuda
multinomial-cuda
nlll-cuda
nms-cuda
opticalFlow-cuda
overlay-cuda
p4-cuda
pad-cuda
particlefilter-cuda
particles-cuda
perplexity-cuda
phmm-cuda
projectile-cuda
pso-cuda
reaction-cuda
recursiveGaussian-cuda
rmsnorm-cuda
romberg-cuda
rowwiseMoments-cuda
rsc-cuda
sc-cuda
shmembench-cuda
tqs-cuda
tsa-cuda
wyllie-cuda
zeropoint-cuda
zoom-cuda
Loading