|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +INPUT_JSON="$1" |
| 4 | +GCS_PATH="$2" # Optional GCS path for uploading results for each run |
| 5 | + |
| 6 | +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) |
| 7 | +AUTOTUNE_SCRIPT="$SCRIPT_DIR/auto_tune.sh" |
| 8 | + |
| 9 | +if [[ -z "$INPUT_JSON" ]]; then |
| 10 | + echo "Error: Input JSON file not provided." |
| 11 | + echo "Usage: $0 <path_to_json_file> [gcs_upload_path]" |
| 12 | + exit 1 |
| 13 | +fi |
| 14 | + |
| 15 | +if [[ ! -f "$INPUT_JSON" ]]; then |
| 16 | + echo "Error: File not found at '$INPUT_JSON'" |
| 17 | + exit 1 |
| 18 | +fi |
| 19 | + |
| 20 | +if ! command -v jq &> /dev/null; then |
| 21 | + echo "Error: 'jq' command not found. Please install jq to process the JSON input." |
| 22 | + exit 1 |
| 23 | +fi |
| 24 | + |
| 25 | +if [[ -n "$GCS_PATH" ]] && ! command -v gcloud &> /dev/null; then |
| 26 | + echo "Error: 'gcloud' command not found, but a GCS_PATH was provided." |
| 27 | + exit 1 |
| 28 | +fi |
| 29 | + |
| 30 | +SUCCESS_COUNT=0 |
| 31 | +FAILURE_COUNT=0 |
| 32 | +FAILED_RUNS=() |
| 33 | +SCRIPT_START_TIME=$(date +%s) |
| 34 | + |
| 35 | +json_content=$(cat "$INPUT_JSON") |
| 36 | +if ! num_runs=$(echo "$json_content" | jq 'length'); then |
| 37 | + echo "Error: Invalid JSON in $INPUT_JSON. 'jq' failed to get array length." >&2 |
| 38 | + exit 1 |
| 39 | +fi |
| 40 | + |
| 41 | +echo "Found $num_runs benchmark configurations in $INPUT_JSON." |
| 42 | +echo "Starting benchmark runs..." |
| 43 | +echo "--------------------------------------------------" |
| 44 | + |
| 45 | +for i in $(seq 0 $(($num_runs - 1))); do |
| 46 | + run_object=$(echo "$json_content" | jq ".[$i]") |
| 47 | + |
| 48 | + RUN_START_TIME=$(date +%s) |
| 49 | + ENV_VARS_ARRAY=() |
| 50 | + # Dynamically create env vars from the JSON object's keys |
| 51 | + for key in $(echo "$run_object" | jq -r 'keys_unsorted[]'); do |
| 52 | + value=$(echo "$run_object" | jq -r ".$key") |
| 53 | + var_name=$(echo "$key" | tr '[:lower:]' '[:upper:]' | tr -cd 'A-Z0-9_') |
| 54 | + ENV_VARS_ARRAY+=("${var_name}=${value}") |
| 55 | + done |
| 56 | + |
| 57 | + echo "Executing run #$((i+1))/$num_runs with parameters: ${ENV_VARS_ARRAY[*]}" |
| 58 | + |
| 59 | + # Execute auto_tune.sh and capture output |
| 60 | + RUN_OUTPUT_FILE=$(mktemp) |
| 61 | + if env "${ENV_VARS_ARRAY[@]}" bash "$AUTOTUNE_SCRIPT" > >(tee -a "$RUN_OUTPUT_FILE") 2>&1; then |
| 62 | + STATUS="SUCCESS" |
| 63 | + ((SUCCESS_COUNT++)) |
| 64 | + else |
| 65 | + STATUS="FAILURE" |
| 66 | + ((FAILURE_COUNT++)) |
| 67 | + FAILED_RUNS+=("Run #$((i+1)): $(echo $run_object | jq -c .)") |
| 68 | + fi |
| 69 | + |
| 70 | + RUN_OUTPUT=$(<"$RUN_OUTPUT_FILE") |
| 71 | + rm "$RUN_OUTPUT_FILE" |
| 72 | + |
| 73 | + # Parse results and optionally upload them to GCS |
| 74 | + RUN_ID="" |
| 75 | + RESULTS="" |
| 76 | + GCS_RESULTS_URL="" |
| 77 | + if [[ "$STATUS" == "SUCCESS" ]]; then |
| 78 | + RESULT_FILE_PATH=$(echo "$RUN_OUTPUT" | grep 'RESULT_FILE=' | tail -n 1 | cut -d'=' -f2 | tr -s '/' || true) |
| 79 | + |
| 80 | + if [[ -n "$RESULT_FILE_PATH" && -f "$RESULT_FILE_PATH" ]]; then |
| 81 | + RUN_ID=$(basename "$(dirname "$RESULT_FILE_PATH")") |
| 82 | + RESULT_DIR=$(dirname "$RESULT_FILE_PATH") |
| 83 | + RESULTS=$(cat "$RESULT_FILE_PATH") |
| 84 | + |
| 85 | + if [[ -n "$GCS_PATH" ]]; then |
| 86 | + GCS_RESULTS_URL="${GCS_PATH}/${RUN_ID}" |
| 87 | + echo "Uploading results to GCS..." |
| 88 | + if gcloud storage rsync --recursive "$RESULT_DIR/" "$GCS_RESULTS_URL"; then |
| 89 | + echo "GCS upload successful." |
| 90 | + else |
| 91 | + echo "Warning: GCS upload failed for RUN_ID $RUN_ID." |
| 92 | + fi |
| 93 | + fi |
| 94 | + else |
| 95 | + echo "Warning: Could not find result file for a successful run." |
| 96 | + STATUS="WARNING_NO_RESULT_FILE" |
| 97 | + fi |
| 98 | + fi |
| 99 | + |
| 100 | + # Add the results back into the JSON object for this run |
| 101 | + json_content=$(echo "$json_content" | jq --argjson i "$i" --arg run_id "$RUN_ID" --arg status "$STATUS" --arg results "$RESULTS" --arg gcs_results "$GCS_RESULTS_URL" \ |
| 102 | + '.[$i] += {run_id: $run_id, status: $status, results: $results, gcs_results: $gcs_results}') |
| 103 | + |
| 104 | + RUN_END_TIME=$(date +%s) |
| 105 | + echo "Run finished in $((RUN_END_TIME - RUN_START_TIME)) seconds. Status: $STATUS" |
| 106 | + echo "--------------------------------------------------" |
| 107 | + |
| 108 | + # Save intermediate progress back to the file |
| 109 | + echo "$json_content" > "$INPUT_JSON.tmp" && mv "$INPUT_JSON.tmp" "$INPUT_JSON" |
| 110 | + |
| 111 | +done |
| 112 | + |
| 113 | +SCRIPT_END_TIME=$(date +%s) |
| 114 | +echo "All benchmark runs completed in $((SCRIPT_END_TIME - SCRIPT_START_TIME)) seconds." |
| 115 | +echo |
| 116 | +echo "====================== SUMMARY ======================" |
| 117 | +echo "Successful runs: $SUCCESS_COUNT" |
| 118 | +echo "Failed runs: $FAILURE_COUNT" |
| 119 | +echo "===================================================" |
| 120 | + |
| 121 | +if [[ $FAILURE_COUNT -gt 0 ]]; then |
| 122 | + echo "Details of failed runs (see JSON file for full parameters):" |
| 123 | + for failed in "${FAILED_RUNS[@]}"; do |
| 124 | + echo " - $failed" |
| 125 | + done |
| 126 | +fi |
| 127 | + |
| 128 | +echo "Updated results have been saved to '$INPUT_JSON'." |
0 commit comments