#!/usr/bin/env bash set -euo pipefail ROOT=${ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)} umask "${UCFNET_UMASK:-000}" usage() { cat >&2 <&2 exit 1 ;; esac TEST_JSON=$(resolve_file "$TEST_JSON") require_env_python "$ENV_PYTHON" for path in "$WEIGHTS" "$TEST_JSON" "$TEST_CONFIG"; do if [[ ! -f "$path" ]]; then echo "Missing required file: $path" >&2 exit 1 fi done if [[ ! -d "$LIBFIX_DIR" ]]; then libcuda_so1=$(ldconfig -p 2>/dev/null | awk '/libcuda\.so\.1/{print $NF; exit}') if [[ -n "$libcuda_so1" ]]; then mkdir -p "$LIBFIX_DIR" ln -sf "$libcuda_so1" "$LIBFIX_DIR/libcuda.so" fi fi if [[ -d "$LIBFIX_DIR" ]]; then export LD_LIBRARY_PATH="$LIBFIX_DIR:/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" fi "$ENV_PYTHON" "$ROOT/scripts/materialize_config.py" \ --repo-root "$ROOT" \ --template "$DETECTOR_TEMPLATE" \ --output "$RUNTIME_CONFIG" \ --data-root "$DATA_ROOT" \ --pretrained-root "$PRETRAINED_ROOT" \ --log-dir "$LOG_DIR" >/dev/null IFS=',' read -r -a GPUS <<< "$GPU_LIST" SHARD_COUNT=${SHARD_COUNT:-${#GPUS[@]}} RUN_ID=${RUN_ID:-$(basename "$(dirname "$WEIGHTS")")_${EVAL_MODE}_$(date '+%Y-%m-%d-%H-%M-%S')} OUT_ROOT=${OUT_ROOT:-$ROOT/eval_logs/$RUN_ID} RESULTS_DIR=${RESULTS_DIR:-$ROOT/results/$RUN_ID} mkdir -p "$OUT_ROOT/raw" "$OUT_ROOT/logs" "$RESULTS_DIR" chmod -R a+rwX "$OUT_ROOT" "$RESULTS_DIR" 2>/dev/null || true export OMP_NUM_THREADS=${OMP_NUM_THREADS:-1} export MKL_NUM_THREADS=${MKL_NUM_THREADS:-1} export OPENBLAS_NUM_THREADS=${OPENBLAS_NUM_THREADS:-1} export NUMEXPR_NUM_THREADS=${NUMEXPR_NUM_THREADS:-1} export TORCH_NUM_THREADS=${TORCH_NUM_THREADS:-1} export PIN_MEMORY { echo "started_at=$(date '+%F %T')" echo "root=$ROOT" echo "env_python=$ENV_PYTHON" echo "eval_mode=$EVAL_MODE" echo "test_json=$TEST_JSON" echo "dataset_root=$DATA_ROOT" echo "detector=$RUNTIME_CONFIG" echo "weights=$WEIGHTS" echo "gpu_list=$GPU_LIST" echo "shard_count=$SHARD_COUNT" echo "batch_size=$BATCH_SIZE" echo "workers=$WORKERS" echo "expected_samples=$EXPECTED_SAMPLES" echo "smoke_samples=$SMOKE_SAMPLES" echo "out_root=$OUT_ROOT" echo "results_dir=$RESULTS_DIR" if command -v nvidia-smi >/dev/null 2>&1; then nvidia-smi --query-gpu=index,name,memory.total,memory.used,utilization.gpu --format=csv,noheader,nounits fi } | tee "$OUT_ROOT/logs/run_manifest.txt" cat > "$OUT_ROOT/run_command.sh" < "$OUT_ROOT/logs/shard_${shard}.stdout" 2>&1 & pids+=("$!") sleep 5 done failed=0 for pid in "${pids[@]}"; do if ! wait "$pid"; then failed=1 fi done if [[ "$failed" != 0 ]]; then echo "[$(date '+%F %T')] $MODEL_NAME $EVAL_MODE evaluation failed; inspect $OUT_ROOT/logs" | tee -a "$OUT_ROOT/logs/run.log" >&2 exit 1 fi merge_args=( "$ROOT/scripts/merge_ucfnet_results.py" --model-raw "$OUT_ROOT"/raw/shard_*.npz --output-dir "$OUT_ROOT" --results-dir "$RESULTS_DIR" --model-name "$MODEL_NAME" --detector-type "$DETECTOR_TYPE" --eval-mode "$EVAL_MODE" ) if [[ -n "$SMOKE_SAMPLES" ]]; then merge_args+=(--skip-sample-check --allow-partial-metrics) else merge_args+=(--expected-samples "$EXPECTED_SAMPLES") fi "$ENV_PYTHON" "${merge_args[@]}" | tee -a "$OUT_ROOT/logs/run.log" echo "[$(date '+%F %T')] wrote compact results to $RESULTS_DIR" | tee -a "$OUT_ROOT/logs/run.log"