blob: d6f41cc22aa1e6cd2de858015eaaecd1438ce544 [file] [log] [blame]
SiCong Li8b4c7302019-09-19 12:18:15 +01001# Copyright (c) 2019 ARM Limited.
2#
3# SPDX-License-Identifier: MIT
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to
7# deal in the Software without restriction, including without limitation the
8# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9# sell copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in all
13# copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21# SOFTWARE.
22
23#!/bin/sh
24
25# Global: Global variables and global settings {{{
26# Treat unset variables as an error when substituting
27set -u
28
29CMD=$( basename $0 )
30
31# All supported strategy options
SiCong Liea803482019-09-26 16:55:49 +010032ALL_STRATEGY_OPTIONS=("native" "reshaped_rhs_only" "reshaped")
SiCong Li8b4c7302019-09-19 12:18:15 +010033
34# Names of example binary for each strategy
SiCong Liea803482019-09-26 16:55:49 +010035EXAMPLE_BIN_NATIVE="benchmark_cl_gemm_native"
SiCong Li8b4c7302019-09-19 12:18:15 +010036EXAMPLE_BIN_RESHAPED_RHS_ONLY="benchmark_cl_gemm_reshaped_rhs_only"
SiCong Libc166d52019-09-26 14:58:53 +010037EXAMPLE_BIN_RESHAPED="benchmark_cl_gemm_reshaped"
SiCong Li8b4c7302019-09-19 12:18:15 +010038
39# Default output directory
40DEFAULT_OUT_DIR="out"
41
42# Number of iterations for each benchmark run
SiCong Libc166d52019-09-26 14:58:53 +010043NUM_ITERATION=5
SiCong Li8b4c7302019-09-19 12:18:15 +010044# Global }}}
45
46# Functions {{{
47#######################################
48# Print gemm shape file help message
49# Globals:
50# None
51# Arguments:
52# None
53# Returns:
54# None
55#######################################
56function help_gemm_shape_file() {
57 cat >&2 << EOF
58Gemm shape file:
59 Gemm shape file is a headerless csv file with fields separated by commas and commas only (there cannot be whitespaces
60 around each field).
SiCong Li8abbabd2020-04-03 12:39:41 +010061
62 Note also comments and extraneous empty lines are not permitted.
63
SiCong Li8b4c7302019-09-19 12:18:15 +010064 A gemm shape is a list of 4 positive integers <M, N, K, B> describing the shapes of the two matrices (LHS and RHS)
65 with:
66 M - Number of lhs matrix rows
67 N - Number of rhs matrix columns
68 K - Number of lhs matrix columns/rhs matrix rows
69 B - Batch size
70
71 An example gemm shape file looks like:
72 100,100,30,1
73 100,100,30,3
74 ...
75
76EOF
77}
78
79#######################################
SiCong Liea803482019-09-26 16:55:49 +010080# Print gemm config file for native help message
81# Globals:
82# None
83# Arguments:
84# None
85# Returns:
86# None
87#######################################
88function help_gemm_config_file_native() {
89 cat >&2 << EOF
90Gemm config file (Strategy native):
91 Gemm config file is a headerless csv file with fields separated by commas and commas only (there cannot be whitespaces
92 around each field).
SiCong Li8abbabd2020-04-03 12:39:41 +010093
94 Note also comments and extraneous empty lines are not permitted.
95
96 A gemm config is a list of 3 positive integers <m0, n0, k0>, with:
SiCong Liea803482019-09-26 16:55:49 +010097 m0 - Number of rows processed by the matrix multiplication
98 n0 - Number of columns processed by the matrix multiplication
99 k0 - Number of partial accumulations performed by the matrix multiplication
100
101 Only the following configurations of M0, N0 and K0 are currently supported:
102 M0 = 1, 2, 3, 4, 5, 6, 7, 8
103 N0 = 2, 3, 4, 8, 16
104 K0 = 2, 3, 4, 8, 16
105
106 An example gemm config file looks like:
107 1,4,4
108 2,3,8
109 ...
110
111EOF
112}
113
114#######################################
SiCong Libc166d52019-09-26 14:58:53 +0100115# Print gemm config file for reshaped_rhs_only help message
SiCong Li8b4c7302019-09-19 12:18:15 +0100116# Globals:
117# None
118# Arguments:
119# None
120# Returns:
121# None
122#######################################
123function help_gemm_config_file_reshaped_rhs_only() {
124 cat >&2 << EOF
125Gemm config file (Strategy reshaped_rhs_only):
126 Gemm config file is a headerless csv file with fields separated by commas and commas only (there cannot be whitespaces
127 around each field).
SiCong Li8abbabd2020-04-03 12:39:41 +0100128
129 Note also comments and extraneous empty lines are not permitted.
130
SiCong Li8b4c7302019-09-19 12:18:15 +0100131 A gemm config is a list of 4 positive integers <m0, n0, k0, h0> and 2 boolean values interleave_rhs and transpose_rhs, with:
132 m0 - Number of rows processed by the matrix multiplication
133 n0 - Number of columns processed by the matrix multiplication
134 k0 - Number of partial accumulations performed by the matrix multiplication
135 h0 - Number of horizontal blocks of size (k0xn0) stored on the same output row
136 interleave_rhs - Interleave rhs matrix (1) / Do not interleave rhs matrix (0)
SiCong Libc166d52019-09-26 14:58:53 +0100137 transpose_rhs - Transpose rhs matrix (1) / Do not transpose rhs matrix (0)
SiCong Li8b4c7302019-09-19 12:18:15 +0100138
139 Only the following configurations of M0, N0 and K0 are currently supported:
140 M0 = 1, 2, 3, 4, 5, 6, 7, 8
141 N0 = 2, 3, 4, 8, 16
142 K0 = 2, 3, 4, 8, 16
143 H0 >= 1
144
145 An example gemm config file looks like:
SiCong Libc166d52019-09-26 14:58:53 +0100146 4,4,4,1,1,1
147 4,4,4,3,1,0
148 ...
149
150EOF
151}
152
153#######################################
154# Print gemm config file for reshaped help message
155# Globals:
156# None
157# Arguments:
158# None
159# Returns:
160# None
161#######################################
162function help_gemm_config_file_reshaped() {
163 cat >&2 << EOF
164Gemm config file (Strategy reshaped):
165 Gemm config file is a headerless csv file with fields separated by commas and commas only (there cannot be whitespaces
166 around each field).
SiCong Li8abbabd2020-04-03 12:39:41 +0100167
168 Note also comments and extraneous empty lines are not permitted.
169
SiCong Libc166d52019-09-26 14:58:53 +0100170 A gemm config is a list of 5 positive integers <m0, n0, k0, v0, h0> and 3 boolean values interleave_lhs, interleave_rhs and transpose_rhs, with:
171 m0 - Number of rows processed by the matrix multiplication
172 n0 - Number of columns processed by the matrix multiplication
173 k0 - Number of partial accumulations performed by the matrix multiplication
174 v0 - Number of vertical blocks of size (m0xk0) stored on the same output row
175 h0 - Number of horizontal blocks of size (k0xn0) stored on the same output row
176 interleave_lhs - Interleave lhs matrix (1) / Do not interleave lhs matrix (0)
177 interleave_rhs - Interleave rhs matrix (1) / Do not interleave rhs matrix (0)
178 transpose_rhs - Transpose rhs matrix but not lhs matrix (1) / Do not transpose rhs matrix but do transpose lhs matrix (0)
179
180 If rhs matrix is transposed only the following configurations are currently supported:
181 M0 = 2, 3, 4, 5, 6, 7, 8
182 N0 = 2, 3, 4, 8, 16
183 K0 = 2, 3, 4, 8, 16
184 V0 >= 1
185 H0 >= 1
186
187 If lhs matrix is transposed only the following configurations are currently supported:
188 M0 = 2, 3, 4, 8
189 N0 = 2, 3, 4, 8, 16
190 K0 = 2, 3, 4, 8, 16
191 V0 >= 1
192 H0 >= 1
193
194 An example gemm config file looks like:
195 4,4,4,1,3,1,1,1
196 4,4,4,3,3,1,1,0
SiCong Li8b4c7302019-09-19 12:18:15 +0100197 ...
198
199EOF
200}
201
202#######################################
203# Print usage of this program and exit with Error
204# Globals:
205# Assumes all globals are required
206# Arguments:
207# None
208# Returns:
209# Error(1)
210#######################################
211function usage() {
212 cat >&2 << EOF
213Run gemm examples of a selected strategy, over provided tunable configurationsa and gemm shapes.
214Save the benchmark results to json files in an output directory.
215
SiCong Libc166d52019-09-26 14:58:53 +0100216Usage: ${CMD} [-h] -s <strategy> -e <example_binary_dir> -g <gemm_shape_file> -c <gemm_config_file> [-o <out_dir>]
SiCong Li8b4c7302019-09-19 12:18:15 +0100217
218Options:
219 -h
SiCong Libc166d52019-09-26 14:58:53 +0100220 Print help messages. If a strategy is specified with -s <strategy>, then only display messages relevant to that
221 strategy. Otherwise if no strategy is specified, display messages for all available strategies.
222
223 -s <strategy>
224 Strategy option.
225 Options: ${ALL_STRATEGY_OPTIONS[@]}.
SiCong Li8b4c7302019-09-19 12:18:15 +0100226
227 -e <example_binary_dir>
228 Path to directory that holds all example binaries
229
230 -g <gemm_shape_file>
231 Path to gemm shape csv file
232
233 -c <gemm_config_file>
234 Path to gemm config csv file
235
SiCong Li8b4c7302019-09-19 12:18:15 +0100236 -o <out_dir>
237 Path to output directory that holds output json files
238 Default: ${DEFAULT_OUT_DIR}
239
240EOF
241# Print help messages about gemm shapes and various gemm configs
242$HELP && help_gemm_shape_file
SiCong Liea803482019-09-26 16:55:49 +0100243$HELP && ( [ "${STRATEGY_OPTION}" == "" ] || [ "${STRATEGY_OPTION}" == "native" ] ) && help_gemm_config_file_native
SiCong Li8b4c7302019-09-19 12:18:15 +0100244$HELP && ( [ "${STRATEGY_OPTION}" == "" ] || [ "${STRATEGY_OPTION}" == "reshaped_rhs_only" ] ) && help_gemm_config_file_reshaped_rhs_only
SiCong Libc166d52019-09-26 14:58:53 +0100245$HELP && ( [ "${STRATEGY_OPTION}" == "" ] || [ "${STRATEGY_OPTION}" == "reshaped" ] ) && help_gemm_config_file_reshaped
SiCong Li8b4c7302019-09-19 12:18:15 +0100246exit 1
247}
248
249#######################################
250# Print error message and exit with Error.
251# Globals:
252# None
253# Arguments:
254# $1 - Error message
255# Returns:
256# None
257#######################################
258function error_msg() {
259 echo "Error: $1" 1>&2
260 exit 1
261}
262
263#######################################
264# Convert string to lower-case
265# Globals:
266# None
267# Arguments:
268# target - String
269# Returns:
270# (stdout) - String in lowercase
271#######################################
272function to_lower() {
273 local target=$1
274 echo "$target" | tr '[:upper:]' '[:lower:]'
275}
276
277#######################################
278# Test if the argument is an integer
279# Globals:
280# None
281# Arguments:
282# in - Input
283# Returns:
284# true/false
285#######################################
286function is_integer() {
287 local in=$1
288 [ "$in" -eq "$in" ] 2> /dev/null
289}
290
291#######################################
SiCong Libc166d52019-09-26 14:58:53 +0100292# Test if a string is in an array of strings
293# Globals:
294# None
295# Arguments:
296# target - String to test
297# array - Array of strings to search
298# Returns:
299# true/false
300#######################################
301function arr_contains() {
302 local target=$1
303 shift
304 local array
305 array=("$@")
306 for s in "${array[@]}"
307 do
308 [ "$s" == "${target}" ] && return
309 done
310 false
311}
312
313#######################################
SiCong Lie36b5262019-10-01 19:26:00 +0100314# Run a single example with all tunable gemm configurations on all gemm parameters
SiCong Li8b4c7302019-09-19 12:18:15 +0100315# Globals:
316# OUT_DIR
SiCong Lie36b5262019-10-01 19:26:00 +0100317# OUT_EXTENSION
SiCong Li8b4c7302019-09-19 12:18:15 +0100318# EXAMPLE_BIN_DIR
319# NUM_ITERATION
320# GEMM_CONFIGS_FILE
321# GEMM_SHAPES_FILE
322# Arguments:
323# example_bin Name of the example binary to run
324# Returns:
325# None
326#######################################
327function run() {
328 local example_bin=$1
329 echo "Running all configs for ${example_bin}" 1>&2
330 local example_args
SiCong Lie36b5262019-10-01 19:26:00 +0100331 local expr_count=1
332 # Total number of experiment runs scheduled for this session
333 local total_num_experiment
334 local num_params
335 local num_configs
336 num_params=$( wc -l ${GEMM_SHAPES_FILE} | cut -d " " -f 1)
337 num_configs=$( wc -l ${GEMM_CONFIGS_FILE} | cut -d " " -f 1 )
338 (( total_num_experiment=${num_params} * ${num_configs} ))
339 # Time elapsed since the beginning in seconds
340 local time_elapsed_s
341 # Time estimated to finish in seconds
342 local time_est_s
343 echo "Running a total number of ${total_num_experiment} experiments" 1>&2
344
SiCong Li8b4c7302019-09-19 12:18:15 +0100345 while read gemm_shape
346 do
347 while read gemm_config
348 do
SiCong Lie36b5262019-10-01 19:26:00 +0100349 echo "Running..." 1>&2
SiCong Li8b4c7302019-09-19 12:18:15 +0100350 example_args="${gemm_shape},${gemm_config}"
SiCong Lie36b5262019-10-01 19:26:00 +0100351 # Run experiment
352 ${EXAMPLE_BIN_DIR}/${example_bin} --example_args=${example_args} --iterations=${NUM_ITERATION} --json-file=${OUT_DIR}/${expr_count}.${OUT_EXTENSION} --instruments=OPENCL_TIMER_MS
353 # Print progress
354 print_progress ${expr_count} ${total_num_experiment}
355 # Print time statistics
356 time_elapsed_s=$SECONDS
357 echo "Time elapsed since beginning: $(( $time_elapsed_s / 60 ))m $(( $time_elapsed_s % 60 ))s" 1>&2
358 (( time_est_s=(${total_num_experiment} - ${expr_count}) * ${time_elapsed_s} / ${expr_count} ))
359 echo "Time estimated to finish: $(( $time_est_s / 60 ))m $(( $time_est_s % 60 ))s" 1>&2
360 (( expr_count++ ))
361 echo "Done." 1>&2
SiCong Li8b4c7302019-09-19 12:18:15 +0100362 done < "${GEMM_CONFIGS_FILE}"
363 done < "${GEMM_SHAPES_FILE}"
364 echo "Finished running all configs for ${example_bin}" 1>&2
365 echo "All results saved to ${OUT_DIR}" 1>&2
366}
367
SiCong Lie36b5262019-10-01 19:26:00 +0100368#######################################
369# Print the progress of the current session
370# Globals:
371# None
372# Arguments:
373# current Current number of items
374# total Total number of items
375# Returns:
376# None
377#######################################
378function print_progress() {
379 local current
380 local total
381 current=$1
382 total=$2
383 # Width of progress bar
384 local width
385 width=20
386 (( current_width= $width * current / total ))
387 echo -n -e "Progress [" 1>&2
388 for i in $(seq 1 ${width}); do
389 if [[ $i -le ${current_width} ]]; then
390 echo -n "#" 1>&2
391 else
392 echo -n " " 1>&2
393 fi
394 done
395 echo "] $current / $total Experiments" 1>&2
396}
397
SiCong Li8b4c7302019-09-19 12:18:15 +0100398# Functions }}}
399
400# Main: Main script {{{
401# Path to directory containing all benchmark examples binaries
402EXAMPLE_BIN_DIR=""
403# Path to gemm shapes file
404GEMM_SHAPES_FILE=""
405# Path to gemm configs file
406GEMM_CONFIGS_FILE=""
SiCong Libc166d52019-09-26 14:58:53 +0100407STRATEGY_OPTION=""
SiCong Li8b4c7302019-09-19 12:18:15 +0100408# Path to output directory
409OUT_DIR=${DEFAULT_OUT_DIR}
SiCong Lie36b5262019-10-01 19:26:00 +0100410# Output benchmark result file extension
411OUT_EXTENSION="gemmtuner_benchmark"
SiCong Li8b4c7302019-09-19 12:18:15 +0100412# Toggle help
413HELP=false
414
415# Obtain options
SiCong Libc166d52019-09-26 14:58:53 +0100416while getopts "hs:e:g:c:o:" opt; do
SiCong Li8b4c7302019-09-19 12:18:15 +0100417 case "$opt" in
SiCong Libc166d52019-09-26 14:58:53 +0100418 h) HELP=true ;;
SiCong Li8b4c7302019-09-19 12:18:15 +0100419 s) STRATEGY_OPTION=$(to_lower "${OPTARG}");;
SiCong Libc166d52019-09-26 14:58:53 +0100420 e) EXAMPLE_BIN_DIR="${OPTARG}";;
SiCong Li8b4c7302019-09-19 12:18:15 +0100421 g) GEMM_SHAPES_FILE="${OPTARG}";;
422 c) GEMM_CONFIGS_FILE="${OPTARG}";;
423 o) OUT_DIR="${OPTARG}";;
424 esac
425done
426shift $((OPTIND - 1))
427
428# Lazily print usage (after arguments have been parsed)
429$HELP &&
430 usage
431
432# Parse and validate options
SiCong Libc166d52019-09-26 14:58:53 +0100433# Verify all compulsory arguments are passed in
434( [ ! -z "${STRATEGY_OPTION}" ] && [ ! -z "${EXAMPLE_BIN_DIR}" ] && [ ! -z "${GEMM_SHAPES_FILE}" ] && [ ! -z "${GEMM_CONFIGS_FILE}" ] ) ||
SiCong Li8b4c7302019-09-19 12:18:15 +0100435 usage
436
437# Verify example binaries directory exists
438[ -d "${EXAMPLE_BIN_DIR}" ] ||
439 error_msg "${EXAMPLE_BIN_DIR} does not exist."
440
441# Verify all benchmark example binaries exist
442[ -f "${EXAMPLE_BIN_DIR}/${EXAMPLE_BIN_RESHAPED_RHS_ONLY}" ] ||
443 error_msg "Cannot find ${EXAMPLE_BIN_RESHAPED_RHS_ONLY} at ${EXAMPLE_BIN_DIR}"
444
445# Verify Gemm shapes file exists
446[ -f "${GEMM_SHAPES_FILE}" ] ||
447 error_msg "Cannot find gemm shapes file ${GEMM_SHAPES_FILE}"
448
SiCong Libc166d52019-09-26 14:58:53 +0100449# Verify Gemm configs file exists
SiCong Li8b4c7302019-09-19 12:18:15 +0100450[ -f "${GEMM_CONFIGS_FILE}" ] ||
451 error_msg "Cannot find gemm configs file ${GEMM_CONFIGS_FILE}"
452
453# Verify strategy option is valid
SiCong Libc166d52019-09-26 14:58:53 +0100454arr_contains "${STRATEGY_OPTION}" "${ALL_STRATEGY_OPTIONS[@]}" ||
SiCong Li8b4c7302019-09-19 12:18:15 +0100455 error_msg "Does not support strategy ${STRATEGY_OPTION}"
456
457# Make sure existing benchmark outputs are not overwritten
458[ ! -d "${OUT_DIR}" ] ||
459 error_msg "Output directory ${OUT_DIR} already exists!"
460
461# Make output directory
462mkdir ${OUT_DIR}
463
464# Run selected strategy with all configurations
SiCong Lie36b5262019-10-01 19:26:00 +0100465# Restart the built-in timer
466SECONDS=0
SiCong Liea803482019-09-26 16:55:49 +0100467[ "${STRATEGY_OPTION}" == "native" ] && run $EXAMPLE_BIN_NATIVE
SiCong Li8b4c7302019-09-19 12:18:15 +0100468[ "${STRATEGY_OPTION}" == "reshaped_rhs_only" ] && run $EXAMPLE_BIN_RESHAPED_RHS_ONLY
SiCong Libc166d52019-09-26 14:58:53 +0100469[ "${STRATEGY_OPTION}" == "reshaped" ] && run $EXAMPLE_BIN_RESHAPED
SiCong Li8b4c7302019-09-19 12:18:15 +0100470# Main: Main script }}}