1+ # Copyright 2025 The OpenXLA Authors. All Rights Reserved.
2+ #
3+ # Licensed under the Apache License, Version 2.0 (the "License");
4+ # you may not use this file except in compliance with the License.
5+ # You may obtain a copy of the License at
6+ #
7+ # http://www.apache.org/licenses/LICENSE-2.0
8+ #
9+ # Unless required by applicable law or agreed to in writing, software
10+ # distributed under the License is distributed on an "AS IS" BASIS,
11+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ # See the License for the specific language governing permissions and
13+ # limitations under the License.
14+ # ============================================================================
15+ # .github/workflows/postsubmit_benchmarks.yml
16+ name : Postsubmit - Run Benchmarks
17+
18+ permissions :
19+ contents : read
20+
21+ on :
22+ workflow_dispatch :
23+ inputs :
24+ halt-for-connection :
25+ description : ' Should this workflow run wait for a remote connection?'
26+ type : choice
27+ required : true
28+ default : ' no'
29+ options :
30+ - ' yes'
31+ - ' no'
32+ pull_request : # TODO(juliagmt): update after testing
33+ branches :
34+ - main
35+
36+ # Cancel in-progress runs for the same branch if a new commit is pushed
37+ concurrency :
38+ group : ${{ github.workflow }}-${{ github.ref }}
39+ cancel-in-progress : true
40+
41+ jobs :
42+ # =================================================================
43+ # Job 1: Generate the matrix specifically for POSTSUBMIT benchmarks
44+ # =================================================================
45+ generate_matrix :
46+ name : Generate Postsubmit Matrix
47+ # Condition: Run if manually dispatched OR if it's a push event to the main branch.
48+ # TODO(juliagmt): update after testing.
49+ # if: |
50+ # github.event_name == 'workflow_dispatch' ||
51+ # (github.event_name == 'pull_request' && github.ref == 'refs/heads/main')
52+ uses : ./.github/workflows/generate_benchmark_matrix.yml
53+ with :
54+ workflow_type : ' POSTSUBMIT'
55+ registry_file : ' xla/tools/benchmarks/registries/default_registry.yml'
56+ checkout_ref : ${{ github.sha }} # On push/dispatch to main, github.sha is the commit SHA
57+
58+ run_benchmarks :
59+ name : Run Benchmark (${{ matrix.benchmark_entry.config_id }}) # config_id will indicate the workflow type, e.g., '_postsubmit'
60+ needs : generate_matrix
61+ # Also check if the generate_matrix job itself was skipped due to its `if` condition
62+ if : success() && needs.generate_matrix.result != 'skipped' && needs.generate_matrix.outputs.matrix_include_json != '[]' && needs.generate_matrix.outputs.matrix_include_json != ''
63+
64+ strategy :
65+ fail-fast : false # Continue running other benchmarks even if one fails
66+ matrix :
67+ benchmark_entry : ${{ fromJson(needs.generate_matrix.outputs.matrix_include_json || '[]') }}
68+
69+ runs-on : ${{ matrix.benchmark_entry.runner_label }}
70+ container : ${{ matrix.benchmark_entry.container_image }}
71+
72+ defaults :
73+ run :
74+ shell : bash
75+
76+ timeout-minutes : 60
77+
78+ env :
79+ # Variables from the matrix
80+ BENCHMARK_NAME : ${{ matrix.benchmark_entry.benchmark_name }}
81+ CONFIG_ID : ${{ matrix.benchmark_entry.config_id }}
82+ RUNNER_LABEL : ${{ matrix.benchmark_entry.runner_label }}
83+ CONTAINER_IMAGE : ${{ matrix.benchmark_entry.container_image }}
84+ ARTIFACT_LOCATION : ${{ matrix.benchmark_entry.artifact_location }}
85+ IS_GCS_ARTIFACT : ${{ matrix.benchmark_entry.is_gcs_artifact }}
86+ INPUT_FORMAT : ${{ matrix.benchmark_entry.input_format }}
87+ XLA_FLAGS_JSON : ${{ toJson(matrix.benchmark_entry.xla_compilation_flags) }}
88+ RUNTIME_FLAGS_JSON : ${{ toJson(matrix.benchmark_entry.runtime_flags) }}
89+ TARGET_METRICS_JSON : ${{ toJson(matrix.benchmark_entry.target_metrics) }}
90+ TOPOLOGY_JSON : ${{ toJson(matrix.benchmark_entry.topology) }}
91+ HARDWARE_CATEGORY : ${{ matrix.benchmark_entry.hardware_category }} # e.g., NVIDIA_GPU_B200
92+
93+ # Workflow context variables
94+ CHECKOUT_REF : ${{ github.sha }} # For postsubmit, use the commit SHA from the push/dispatch event
95+ COMMIT_SHA : ${{ github.sha }} # For postsubmit, use the commit SHA
96+ WORKFLOW_RUN_ID : ${{ github.run_id }}
97+
98+ # Paths and script locations
99+ OUTPUT_DIR_NAME : benchmark_output_${{ matrix.benchmark_entry.config_id }} # config_id includes workflow type
100+ SCRIPT_DIR_RELATIVE : .github/workflows/benchmarks
101+ BASELINE_YAML_FILE_RELATIVE : xla/tools/benchmarks/baseline/postsubmit_baseline.yml
102+ COMPARISON_SCRIPT_RELATIVE : .github/workflows/benchmarks/compare_with_baseline.py
103+
104+ steps :
105+ - name : " Wait For Connection"
106+ uses : google-ml-infra/actions/ci_connection@7f5ca0c263a81ed09ea276524c1b9192f1304e3c
107+ with :
108+ halt-dispatch-input : ${{ inputs.halt-for-connection }}
109+
110+ - name : Print Job Info & Set Full Paths in ENV
111+ run : |
112+ # Resolve full paths based on GITHUB_WORKSPACE and relative paths defined in env
113+ FULL_OUTPUT_DIR_PATH="${GITHUB_WORKSPACE}/${OUTPUT_DIR_NAME}"
114+ RESOLVED_SCRIPT_DIR_PATH="${GITHUB_WORKSPACE}/${SCRIPT_DIR_RELATIVE}"
115+ RESOLVED_BASELINE_YAML_PATH="${GITHUB_WORKSPACE}/${BASELINE_YAML_FILE_RELATIVE}" # Will use postsubmit_baseline.yml
116+ RESOLVED_COMPARISON_SCRIPT_PATH="${GITHUB_WORKSPACE}/${COMPARISON_SCRIPT_RELATIVE}"
117+ RESOLVED_RUN_COMPARISON_SCRIPT_PATH="${GITHUB_WORKSPACE}/${SCRIPT_DIR_RELATIVE}/run_comparison.sh"
118+
119+ echo "--- Benchmark Job Info (Postsubmit) ---"
120+ echo "Config ID (from matrix): $CONFIG_ID"
121+ echo "Benchmark Name: $BENCHMARK_NAME"
122+ echo "Runner Label: $RUNNER_LABEL"
123+ echo "Hardware Category: $HARDWARE_CATEGORY"
124+ echo "Output Directory Name (relative): $OUTPUT_DIR_NAME"
125+ echo "Full Output Directory Path: $FULL_OUTPUT_DIR_PATH"
126+ echo "Full Script Directory Path: $RESOLVED_SCRIPT_DIR_PATH"
127+ echo "Full Baseline YAML Path: $RESOLVED_BASELINE_YAML_PATH" # This will point to postsubmit_baseline.yml
128+ echo "Full Comparison Script Path: $RESOLVED_COMPARISON_SCRIPT_PATH"
129+ echo "Full Run Comparison Script Path: $RESOLVED_RUN_COMPARISON_SCRIPT_PATH"
130+ echo "GITHUB_WORKSPACE: ${GITHUB_WORKSPACE}"
131+ echo "Current PWD: $(pwd)"
132+ echo "---------------------------------------"
133+
134+ # Make resolved paths available to subsequent steps via GITHUB_ENV
135+ echo "RESOLVED_OUTPUT_DIR=$FULL_OUTPUT_DIR_PATH" >> $GITHUB_ENV
136+ echo "RESOLVED_SCRIPT_DIR=$RESOLVED_SCRIPT_DIR_PATH" >> $GITHUB_ENV
137+ echo "RESOLVED_BASELINE_YAML=$RESOLVED_BASELINE_YAML_PATH" >> $GITHUB_ENV
138+ echo "RESOLVED_COMPARISON_SCRIPT=$RESOLVED_COMPARISON_SCRIPT_PATH" >> $GITHUB_ENV
139+ echo "RESOLVED_RUN_COMPARISON_SCRIPT=$RESOLVED_RUN_COMPARISON_SCRIPT_PATH" >> $GITHUB_ENV
140+
141+ # Create the output directory; scripts will assume it exists
142+ mkdir -p "$FULL_OUTPUT_DIR_PATH"
143+ if [ ! -d "$FULL_OUTPUT_DIR_PATH" ]; then
144+ echo "::error::Failed to create output directory: $FULL_OUTPUT_DIR_PATH"
145+ exit 1
146+ fi
147+
148+ - name : Checkout OpenXLA Repository
149+ uses : actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
150+ with :
151+ ref : ${{ env.CHECKOUT_REF }}
152+
153+ - name : Build Binaries
154+ id : build_binaries
155+ run : |
156+ bash "${RESOLVED_SCRIPT_DIR}/build_binaries.sh"
157+ env :
158+ OUTPUT_DIR : ${{ env.RESOLVED_OUTPUT_DIR }}
159+
160+ - name : Prepare Benchmark Artifact
161+ id : prep_artifact
162+ run : |
163+ bash "${RESOLVED_SCRIPT_DIR}/prepare_artifact.sh"
164+ env :
165+ OUTPUT_DIR : ${{ env.RESOLVED_OUTPUT_DIR }}
166+
167+ - name : Run Benchmark and Generate Stats
168+ id : run_hlo
169+ env :
170+ RUNNER_BINARY : " ${{ steps.build_binaries.outputs.runner_binary }}"
171+ STATS_BINARY : " ${{ steps.build_binaries.outputs.stats_binary }}"
172+ DEVICE_TYPE_FLAG : " ${{ steps.build_binaries.outputs.device_type_flag }}"
173+ LOCAL_ARTIFACT_PATH : " ${{ steps.prep_artifact.outputs.artifact_local_path }}"
174+ OUTPUT_DIR : ${{ env.RESOLVED_OUTPUT_DIR }}
175+ # Other job-level env vars are automatically inherited
176+ run : |
177+ # The run_benchmark.sh script is expected to create $RESOLVED_OUTPUT_DIR/results.json
178+ bash "${RESOLVED_SCRIPT_DIR}/run_benchmark.sh"
179+
180+ # Print the content of results.json for debugging purposes
181+ RESULTS_JSON_FILE_PATH="${RESOLVED_OUTPUT_DIR}/results.json"
182+ echo "--- Content of results.json (from workflow) ---"
183+ if [ -f "$RESULTS_JSON_FILE_PATH" ]; then
184+ if command -v jq &> /dev/null && jq '.' "$RESULTS_JSON_FILE_PATH" > /dev/null 2>&1; then
185+ jq '.' "$RESULTS_JSON_FILE_PATH"
186+ else
187+ echo "results.json may not be valid JSON or jq failed, printing with cat:"
188+ cat "$RESULTS_JSON_FILE_PATH"
189+ fi
190+ elif [ -f "${RESULTS_JSON_FILE_PATH}.txt" ]; then # Fallback for non-JSON or renamed output
191+ echo "results.json not found, printing fallback .txt file:"
192+ cat "${RESULTS_JSON_FILE_PATH}.txt"
193+ else
194+ echo "::warning::Neither results.json nor results.json.txt found at $RESULTS_JSON_FILE_PATH"
195+ fi
196+ echo "---------------------------------------------"
197+
198+ - name : Compare Results to Baseline
199+ if : (steps.run_hlo.outcome == 'success' || (steps.run_hlo.outcome == 'failure' && (hashFiles(format('{0}/results.json', env.RESOLVED_OUTPUT_DIR)) != '' || hashFiles(format('{0}/results.json.txt', env.RESOLVED_OUTPUT_DIR)) != ''))) && env.skip_comparison_due_to_yaml_install_failure != 'true'
200+ run : |
201+ echo "Starting baseline comparison (against postsubmit baseline)..."
202+ bash "$RESOLVED_RUN_COMPARISON_SCRIPT" # This script calls the Python comparison script
203+ echo "Baseline comparison finished."
204+ echo "---------------------------------------------"
205+
206+ - name : Upload Benchmark Artifacts
207+ if : always()
208+ uses : actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
209+ with :
210+ name : results-${{ env.CONFIG_ID }}
211+ path : ${{ env.RESOLVED_OUTPUT_DIR }}
212+ retention-days : 14
213+ if-no-files-found : error
0 commit comments