xref: /libCEED/benchmarks/benchmark.sh (revision e1ef875599c3a6b02a7bf1f21ab905966273ff45)
12f4d9adbSJeremy L Thompson#!/bin/bash
22f4d9adbSJeremy L Thompson
32f4d9adbSJeremy L Thompson# Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC.
42f4d9adbSJeremy L Thompson# Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707.
52f4d9adbSJeremy L Thompson# All Rights reserved. See files LICENSE and NOTICE for details.
62f4d9adbSJeremy L Thompson#
72f4d9adbSJeremy L Thompson# This file is part of CEED, a collection of benchmarks, miniapps, software
82f4d9adbSJeremy L Thompson# libraries and APIs for efficient high-order finite element and spectral
92f4d9adbSJeremy L Thompson# element discretizations for exascale applications. For more information and
102f4d9adbSJeremy L Thompson# source code availability see http://github.com/ceed.
112f4d9adbSJeremy L Thompson#
122f4d9adbSJeremy L Thompson# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
132f4d9adbSJeremy L Thompson# a collaborative effort of two U.S. Department of Energy organizations (Office
142f4d9adbSJeremy L Thompson# of Science and the National Nuclear Security Administration) responsible for
152f4d9adbSJeremy L Thompson# the planning and preparation of a capable exascale ecosystem, including
162f4d9adbSJeremy L Thompson# software, applications, hardware, advanced system engineering and early
172f4d9adbSJeremy L Thompson# testbed platforms, in support of the nation's exascale computing imperative.
182f4d9adbSJeremy L Thompson
192f4d9adbSJeremy L Thompsonthis_file="${BASH_SOURCE[0]}"
202f4d9adbSJeremy L Thompsonif [[ "${#BASH_ARGV[@]}" -ne "$#" ]]; then
212f4d9adbSJeremy L Thompson   script_is_sourced="yes"
222f4d9adbSJeremy L Thompson   exit_cmd=return
232f4d9adbSJeremy L Thompsonelse
242f4d9adbSJeremy L Thompson   script_is_sourced=""
252f4d9adbSJeremy L Thompson   exit_cmd=exit
262f4d9adbSJeremy L Thompsonfi
272f4d9adbSJeremy L Thompsontest_file=""
282f4d9adbSJeremy L Thompsonbackend_list="/cpu/self"
290c59ef15SJeremy L Thompsonbp_list="bp1 bp3"
302f4d9adbSJeremy L Thompsonrun=""
312f4d9adbSJeremy L Thompsonnum_proc_run=${num_proc_run:-""}
322f4d9adbSJeremy L Thompsonnum_proc_node=${num_proc_node:-""}
332f4d9adbSJeremy L Thompsondry_run="" # empty string = NO
342f4d9adbSJeremy L Thompsonstart_shell=""
352f4d9adbSJeremy L Thompsonverbose=""
362f4d9adbSJeremy L Thompsoncur_dir="$PWD"
372f4d9adbSJeremy L Thompson
382f4d9adbSJeremy L Thompsonmpiexec="mpirun"
392f4d9adbSJeremy L Thompsonmpiexec_np="-np"
402f4d9adbSJeremy L Thompsonmpiexec_opts=""
412f4d9adbSJeremy L Thompsonmpiexec_post_opts=""
422f4d9adbSJeremy L Thompsonprofiler=""
432f4d9adbSJeremy L Thompson
442f4d9adbSJeremy L Thompsonfunction abspath()
452f4d9adbSJeremy L Thompson{
462f4d9adbSJeremy L Thompson   local outvar="$1" path="$2" cur_dir="$PWD"
472f4d9adbSJeremy L Thompson   cd "$path" && path="$PWD" && cd "$cur_dir" && eval "$outvar=\"$path\""
482f4d9adbSJeremy L Thompson}
492f4d9adbSJeremy L Thompson
502f4d9adbSJeremy L Thompsonabspath root_dir ".." || $exit_cmd 1
512f4d9adbSJeremy L Thompsonbuild_root="$root_dir/build"
522f4d9adbSJeremy L Thompson
532f4d9adbSJeremy L Thompsonif [[ -t 1 ]]; then
542f4d9adbSJeremy L Thompson   # ANSI color codes
552f4d9adbSJeremy L Thompson   none=$'\E[0m'
562f4d9adbSJeremy L Thompson   red=$'\E[0;31m'
572f4d9adbSJeremy L Thompson   green=$'\E[0;32m'
582f4d9adbSJeremy L Thompson   yellow=$'\E[0;33m'
592f4d9adbSJeremy L Thompson   blue=$'\E[0;34m'
602f4d9adbSJeremy L Thompson   bblue=$'\E[1;34m'
612f4d9adbSJeremy L Thompson   magenta=$'\E[0;35m'
622f4d9adbSJeremy L Thompson   cyan=$'\E[0;36m'
632f4d9adbSJeremy L Thompson   clear="$(tput sgr0)"
642f4d9adbSJeremy L Thompsonfi
652f4d9adbSJeremy L Thompson
662f4d9adbSJeremy L Thompsonhelp_msg="
672f4d9adbSJeremy L Thompson$this_file [options]
682f4d9adbSJeremy L Thompson
692f4d9adbSJeremy L ThompsonOptions:
702f4d9adbSJeremy L Thompson   -h|--help                print this usage information and exit
710c59ef15SJeremy L Thompson   -b|--bp \"list\"           choose the benchmark problems to run
722f4d9adbSJeremy L Thompson   -c|--ceed \"list\"         choose the libCEED backends to benchmark
732f4d9adbSJeremy L Thompson   -r|--run <name>          run the tests in the script <name>
742f4d9adbSJeremy L Thompson   -n|--num-proc \"list\"     total number of MPI tasks to use in the tests
752f4d9adbSJeremy L Thompson   -p|--proc-node \"list\"    number of MPI tasks per node to use in the tests
762f4d9adbSJeremy L Thompson   -d|--dry-run             show (but do not run) the commands for the tests
772f4d9adbSJeremy L Thompson   -s|--shell               execute bash shell commands before running the test
782f4d9adbSJeremy L Thompson   -v|--verbose             print additional messages
792f4d9adbSJeremy L Thompson   -x                       enable script tracing with 'set -x'
802f4d9adbSJeremy L Thompson   var=value                define shell variables; evaluated with 'eval'
812f4d9adbSJeremy L Thompson
822f4d9adbSJeremy L ThompsonThis script builds and runs a set of benchmarks for a list of specified
832f4d9adbSJeremy L Thompsonbackends.
842f4d9adbSJeremy L Thompson
852f4d9adbSJeremy L ThompsonExample usage:
86cb32e2e7SValeria Barra  $this_file  --run petsc-bpsraw.sh
87*e1ef8755Svaleriabarra  $this_file  --run petsc-bps.sh
882f4d9adbSJeremy L Thompson"
892f4d9adbSJeremy L Thompson
902f4d9adbSJeremy L Thompson
912f4d9adbSJeremy L Thompsonfunction build_examples()
922f4d9adbSJeremy L Thompson{
932f4d9adbSJeremy L Thompson   for example; do
942f4d9adbSJeremy L Thompson      # We require the examples to be already built because we do not know what
952f4d9adbSJeremy L Thompson      # options to use when building the library + examples.
962f4d9adbSJeremy L Thompson      if [ ! -e $build_root/$example ]; then
972f4d9adbSJeremy L Thompson         echo "Error: example is not built: $example"
982f4d9adbSJeremy L Thompson         return 1
992f4d9adbSJeremy L Thompson      fi
1002f4d9adbSJeremy L Thompson   done
1012f4d9adbSJeremy L Thompson}
1022f4d9adbSJeremy L Thompson
1032f4d9adbSJeremy L Thompson
1042f4d9adbSJeremy L Thompsonfunction compose_mpi_run_command()
1052f4d9adbSJeremy L Thompson{
1062f4d9adbSJeremy L Thompson   mpi_run="${mpiexec:-mpirun} ${mpiexec_opts}"
1072f4d9adbSJeremy L Thompson   mpi_run+=" ${mpiexec_np:--np} ${num_proc_run} ${mpiexec_post_opts}"
1082f4d9adbSJeremy L Thompson   if [[ -n "$profiler" ]]; then
1092f4d9adbSJeremy L Thompson      mpi_run+=" $profiler"
1102f4d9adbSJeremy L Thompson   fi
1112f4d9adbSJeremy L Thompson}
1122f4d9adbSJeremy L Thompson
1132f4d9adbSJeremy L Thompson
1142f4d9adbSJeremy L Thompsonfunction quoted_echo()
1152f4d9adbSJeremy L Thompson{
1162f4d9adbSJeremy L Thompson   local arg= string=
1172f4d9adbSJeremy L Thompson   for arg; do
1182f4d9adbSJeremy L Thompson      if [[ -z "${arg##* *}" ]]; then
1192f4d9adbSJeremy L Thompson         string+=" \"${arg//\"/\\\"}\""
1202f4d9adbSJeremy L Thompson      else
1212f4d9adbSJeremy L Thompson         string+=" $arg"
1222f4d9adbSJeremy L Thompson      fi
1232f4d9adbSJeremy L Thompson   done
1242f4d9adbSJeremy L Thompson   printf "%s\n" "${string# }"
1252f4d9adbSJeremy L Thompson}
1262f4d9adbSJeremy L Thompson
1272f4d9adbSJeremy L Thompson
1282f4d9adbSJeremy L Thompsonfunction set_num_nodes()
1292f4d9adbSJeremy L Thompson{
1302f4d9adbSJeremy L Thompson   if [[ -n "$num_proc_node" ]]; then
1312f4d9adbSJeremy L Thompson      ((num_proc_run % num_proc_node != 0)) && {
1322f4d9adbSJeremy L Thompson         echo "The total number of tasks ($num_proc_run) must be a multiple of"
1332f4d9adbSJeremy L Thompson         echo "the number of tasks per node ($num_proc_node). Stop."
1342f4d9adbSJeremy L Thompson         return 1
1352f4d9adbSJeremy L Thompson      }
1362f4d9adbSJeremy L Thompson      ((num_nodes = num_proc_run / num_proc_node))
1372f4d9adbSJeremy L Thompson   else
1382f4d9adbSJeremy L Thompson      num_proc_node="unknown number of"
1392f4d9adbSJeremy L Thompson      num_nodes=""
1402f4d9adbSJeremy L Thompson   fi
1412f4d9adbSJeremy L Thompson   echo "Running the tests using a total of $num_proc_run MPI tasks ..." | tee -a $output_file
1422f4d9adbSJeremy L Thompson   echo "... with $num_proc_node tasks per node ..." | tee -a $output_file
1432f4d9adbSJeremy L Thompson   echo | tee -a $output_file
1442f4d9adbSJeremy L Thompson}
1452f4d9adbSJeremy L Thompson
1462f4d9adbSJeremy L Thompson
1472f4d9adbSJeremy L Thompson### Process command line parameters
1482f4d9adbSJeremy L Thompson
1492f4d9adbSJeremy L Thompsonwhile [ $# -gt 0 ]; do
1502f4d9adbSJeremy L Thompson
1512f4d9adbSJeremy L Thompsoncase "$1" in
1522f4d9adbSJeremy L Thompson   -h|--help)
1532f4d9adbSJeremy L Thompson      # Echo usage information
1542f4d9adbSJeremy L Thompson      echo "$help_msg"
1552f4d9adbSJeremy L Thompson      $exit_cmd
1562f4d9adbSJeremy L Thompson      ;;
1570c59ef15SJeremy L Thompson   -b|--bp)
1580c59ef15SJeremy L Thompson      shift
1590c59ef15SJeremy L Thompson      [ $# -gt 0 ] || {
1600c59ef15SJeremy L Thompson      echo "Missing \"list\" in --bp \"list\""; $exit_cmd 1; }
1610c59ef15SJeremy L Thompson      bp_list="$1"
1620c59ef15SJeremy L Thompson      ;;
1632f4d9adbSJeremy L Thompson   -c|--ceed)
1642f4d9adbSJeremy L Thompson      shift
1652f4d9adbSJeremy L Thompson      [ $# -gt 0 ] || {
1662f4d9adbSJeremy L Thompson      echo "Missing \"list\" in --ceed \"list\""; $exit_cmd 1; }
1672f4d9adbSJeremy L Thompson      backend_list="$1"
1682f4d9adbSJeremy L Thompson      ;;
1692f4d9adbSJeremy L Thompson   -r|--run)
1702f4d9adbSJeremy L Thompson      run=on
1712f4d9adbSJeremy L Thompson      shift
1722f4d9adbSJeremy L Thompson      [ $# -gt 0 ] || { echo "Missing <name> in --run <name>"; $exit_cmd 1; }
1732f4d9adbSJeremy L Thompson      test_file="$1"
1742f4d9adbSJeremy L Thompson      [[ -r "$test_file" ]] || {
1752f4d9adbSJeremy L Thompson         echo "Test script not found: '$1'"; $exit_cmd 1
1762f4d9adbSJeremy L Thompson      }
1772f4d9adbSJeremy L Thompson      ;;
1782f4d9adbSJeremy L Thompson   -n|--num-proc)
1792f4d9adbSJeremy L Thompson      shift
1802f4d9adbSJeremy L Thompson      [ $# -gt 0 ] || {
1812f4d9adbSJeremy L Thompson      echo "Missing \"list\" in --num-proc \"list\""; $exit_cmd 1; }
1822f4d9adbSJeremy L Thompson      num_proc_run="$1"
1832f4d9adbSJeremy L Thompson      ;;
1842f4d9adbSJeremy L Thompson   -p|--proc-node)
1852f4d9adbSJeremy L Thompson      shift
1862f4d9adbSJeremy L Thompson      [ $# -gt 0 ] || {
1872f4d9adbSJeremy L Thompson      echo "Missing \"list\" in --proc-node \"list\""; $exit_cmd 1; }
1882f4d9adbSJeremy L Thompson      num_proc_node="$1"
1892f4d9adbSJeremy L Thompson      ;;
1902f4d9adbSJeremy L Thompson   -d|--dry-run)
1912f4d9adbSJeremy L Thompson      dry_run="quoted_echo"
1922f4d9adbSJeremy L Thompson      ;;
1932f4d9adbSJeremy L Thompson   -s|--shell)
1942f4d9adbSJeremy L Thompson      start_shell="yes"
1952f4d9adbSJeremy L Thompson      ;;
1962f4d9adbSJeremy L Thompson   -v|--verbose)
1972f4d9adbSJeremy L Thompson      verbose="yes"
1982f4d9adbSJeremy L Thompson      ;;
1992f4d9adbSJeremy L Thompson   -x)
2002f4d9adbSJeremy L Thompson      set -x
2012f4d9adbSJeremy L Thompson      ;;
2022f4d9adbSJeremy L Thompson   *=*)
2032f4d9adbSJeremy L Thompson      eval "$1" || { echo "Error evaluating argument: $1"; $exit_cmd 1; }
2042f4d9adbSJeremy L Thompson      ;;
2052f4d9adbSJeremy L Thompson   *)
2062f4d9adbSJeremy L Thompson      echo "Unknown option: '$1'"
2072f4d9adbSJeremy L Thompson      $exit_cmd 1
2082f4d9adbSJeremy L Thompson      ;;
2092f4d9adbSJeremy L Thompsonesac
2102f4d9adbSJeremy L Thompson
2112f4d9adbSJeremy L Thompsonshift
2122f4d9adbSJeremy L Thompsondone # while ...
2132f4d9adbSJeremy L Thompson# Done processing command line parameters
2142f4d9adbSJeremy L Thompson
2152f4d9adbSJeremy L Thompson
2162f4d9adbSJeremy L Thompsonnum_proc_list=(${num_proc_run:-4})
2172f4d9adbSJeremy L Thompsonnum_proc_list_size=${#num_proc_list[@]}
2182f4d9adbSJeremy L Thompsonnum_proc_node_list=(${num_proc_node:-4})
2192f4d9adbSJeremy L Thompsonnum_proc_node_list_size=${#num_proc_node_list[@]}
2202f4d9adbSJeremy L Thompson(( num_proc_list_size != num_proc_node_list_size )) && {
2212f4d9adbSJeremy L Thompson   echo "
2222f4d9adbSJeremy L ThompsonThe size of the number-of-processors list (option --num-proc) must be the same
2232f4d9adbSJeremy L Thompsonas the size of the number-of-processors-per-node list (option --proc-node)."
2242f4d9adbSJeremy L Thompson   echo
2252f4d9adbSJeremy L Thompson   $exit_cmd 1
2262f4d9adbSJeremy L Thompson}
2272f4d9adbSJeremy L Thompson
2280c59ef15SJeremy L Thompson### Loop over BPs
2290c59ef15SJeremy L Thompson
2300c59ef15SJeremy L Thompsonfor bp in $bp_list; do
2312f4d9adbSJeremy L Thompson
2322f4d9adbSJeremy L Thompson### Loop over backends
2332f4d9adbSJeremy L Thompson
2342f4d9adbSJeremy L Thompsonfor backend in $backend_list; do
2352f4d9adbSJeremy L Thompson(  ## Run each backend in its own environment
2362f4d9adbSJeremy L Thompson
2372f4d9adbSJeremy L Thompson### Setup output
2382f4d9adbSJeremy L Thompson### Test name
2392f4d9adbSJeremy L Thompsoncd "$cur_dir"
2402f4d9adbSJeremy L Thompsonabspath test_dir "$(dirname "$test_file")" || $exit_cmd 1
2412f4d9adbSJeremy L Thompsontest_basename="$(basename "$test_file")"
2422f4d9adbSJeremy L Thompsontest_file="${test_dir}/${test_basename}"
2432f4d9adbSJeremy L Thompson### Backend name
2442f4d9adbSJeremy L Thompsonshort_backend=${backend//[\/]}
2452f4d9adbSJeremy L Thompson### Output file
2460c59ef15SJeremy L Thompsonoutput_file="${test_file%%.*}-$bp-$short_backend-output.txt"
2472f4d9adbSJeremy L Thompsonrm -rf output_file
2482f4d9adbSJeremy L Thompson
2492f4d9adbSJeremy L Thompson### Setup the environment based on $backend
2502f4d9adbSJeremy L Thompson
2512f4d9adbSJeremy L Thompsonecho
2522f4d9adbSJeremy L Thompsonecho "Using backend $backend ..." | tee $output_file
2532f4d9adbSJeremy L Thompson
2542f4d9adbSJeremy L Thompson### Run the tests (building and running $test_file)
2552f4d9adbSJeremy L Thompson
2562f4d9adbSJeremy L Thompson[ -n "$run" ] && {
2572f4d9adbSJeremy L Thompson
2582f4d9adbSJeremy L Thompson[[ "$verbose" = "yes" ]] && {
2592f4d9adbSJeremy L Thompson   echo "Test problem file, $test_basename:" | tee -a $output_file
2602f4d9adbSJeremy L Thompson   echo "------------------------------------------------" | tee -a $output_file
2612f4d9adbSJeremy L Thompson   cat $test_file | tee -a $output_file
2622f4d9adbSJeremy L Thompson   echo "------------------------------------------------" | tee -a $output_file
2632f4d9adbSJeremy L Thompson   echo | tee -a $output_file
2642f4d9adbSJeremy L Thompson}
2652f4d9adbSJeremy L Thompson
2662f4d9adbSJeremy L Thompsontest_exe_dir="$build_root"
2672f4d9adbSJeremy L Thompson
2682f4d9adbSJeremy L Thompsontrap 'printf "\nScript interrupted.\n"; '$exit_cmd' 33' INT
2692f4d9adbSJeremy L Thompson
2702f4d9adbSJeremy L Thompson## Source the test script file.
2712f4d9adbSJeremy L Thompsonecho "Reading test file: $test_file" | tee -a $output_file
2722f4d9adbSJeremy L Thompsonecho | tee -a $output_file
2732f4d9adbSJeremy L Thompsontest_required_examples=""
2742f4d9adbSJeremy L Thompson. "$test_file" || $exit_cmd 1
2752f4d9adbSJeremy L Thompson
2762f4d9adbSJeremy L Thompson## Build files required by the test
2772f4d9adbSJeremy L Thompsonecho "Example(s) required by the test: $test_required_examples" | tee -a $output_file
2782f4d9adbSJeremy L Thompsonbuild_examples $test_required_examples || $exit_cmd 1
2792f4d9adbSJeremy L Thompsonecho | tee -a $output_file
2802f4d9adbSJeremy L Thompson
2812f4d9adbSJeremy L Thompson## Loop over the number-of-processors list.
2822f4d9adbSJeremy L Thompsonfor (( num_proc_idx = 0; num_proc_idx < num_proc_list_size; num_proc_idx++ ))
2832f4d9adbSJeremy L Thompsondo
2842f4d9adbSJeremy L Thompson
2852f4d9adbSJeremy L Thompsonnum_proc_run="${num_proc_list[$num_proc_idx]}"
2862f4d9adbSJeremy L Thompsonnum_proc_node="${num_proc_node_list[$num_proc_idx]}"
2872f4d9adbSJeremy L Thompson
2882f4d9adbSJeremy L Thompsonset_num_nodes || $exit_cmd 1
2892f4d9adbSJeremy L Thompsoncompose_mpi_run_command
2902f4d9adbSJeremy L Thompson
2912f4d9adbSJeremy L Thompsonif [[ "$start_shell" = "yes" ]]; then
2922f4d9adbSJeremy L Thompson   if [[ ! -t 1 ]]; then
2932f4d9adbSJeremy L Thompson      echo "Standard output is not a terminal. Stop." | tee -a $output_file
2942f4d9adbSJeremy L Thompson      $exit_cmd 1
2952f4d9adbSJeremy L Thompson   fi
2962f4d9adbSJeremy L Thompson   echo "Reading shell commands, type 'c' to continue, 'exit' to stop ..." | tee -a $output_file
2972f4d9adbSJeremy L Thompson   echo | tee -a $output_file
2982f4d9adbSJeremy L Thompson   cd "$cur_dir"
2992f4d9adbSJeremy L Thompson   set -o emacs
3002f4d9adbSJeremy L Thompson   PS1='$ '
3012f4d9adbSJeremy L Thompson   [[ -r $HOME/.bashrc ]] && source $HOME/.bashrc
3022f4d9adbSJeremy L Thompson   HISTFILE="$root_dir/.bash_history"
3032f4d9adbSJeremy L Thompson   history -c
3042f4d9adbSJeremy L Thompson   history -r
3052f4d9adbSJeremy L Thompson   # bind '"\\C-i": menu-complete'
3062f4d9adbSJeremy L Thompson   alias c='break'
3072f4d9adbSJeremy L Thompson   while cwd="$PWD/" cwd="${cwd#${root_dir}/}" cwd="${cwd%/}" \
3082f4d9adbSJeremy L Thompson         prompt="[${cyan}benchmarks$none:$blue$cwd$clear]\$ " && \
3092f4d9adbSJeremy L Thompson         read -p "$prompt" -e line; do
3102f4d9adbSJeremy L Thompson      history -s "$line"
3112f4d9adbSJeremy L Thompson      history -w
3122f4d9adbSJeremy L Thompson      shopt -q -s expand_aliases
3132f4d9adbSJeremy L Thompson      eval "$line"
3142f4d9adbSJeremy L Thompson      shopt -q -u expand_aliases
3152f4d9adbSJeremy L Thompson   done
3162f4d9adbSJeremy L Thompson   [[ "${#line}" -eq 0 ]] && { echo; $exit_cmd 0; }
3172f4d9adbSJeremy L Thompson   shopt -q -u expand_aliases
3182f4d9adbSJeremy L Thompson   echo "Continuing ..." | tee -a $output_file
3192f4d9adbSJeremy L Thompsonfi
3202f4d9adbSJeremy L Thompson
3212f4d9adbSJeremy L Thompson# Call the function run_tests defined inside the $test_file
3222f4d9adbSJeremy L Thompsonceed=$backend
3232f4d9adbSJeremy L Thompsonif [ -z "$dry_run" ]; then
3242f4d9adbSJeremy L Thompson   run_tests >> $output_file
3252f4d9adbSJeremy L Thompsonelse
3262f4d9adbSJeremy L Thompson   run_tests
3272f4d9adbSJeremy L Thompsonfi
3282f4d9adbSJeremy L Thompsonecho
3292f4d9adbSJeremy L Thompson
3302f4d9adbSJeremy L Thompsondone ## End of loop over processor numbers
3312f4d9adbSJeremy L Thompson
3322f4d9adbSJeremy L Thompsontrap - INT
3332f4d9adbSJeremy L Thompson
3342f4d9adbSJeremy L Thompson} ## run is on
3352f4d9adbSJeremy L Thompson
3362f4d9adbSJeremy L Thompson$exit_cmd 0
3372f4d9adbSJeremy L Thompson
3382f4d9adbSJeremy L Thompson) || {
3392f4d9adbSJeremy L Thompson   echo "Sub-shell for backend '$backend' returned error code $?. Stop."
3402f4d9adbSJeremy L Thompson   $exit_cmd 1
3412f4d9adbSJeremy L Thompson}
3422f4d9adbSJeremy L Thompsondone ## Loop over $backend_list
3432f4d9adbSJeremy L Thompson
3440c59ef15SJeremy L Thompsondone ## Loop over $bp_list
3450c59ef15SJeremy L Thompson
3462f4d9adbSJeremy L Thompson
3472f4d9adbSJeremy L Thompson$exit_cmd 0
3482f4d9adbSJeremy L Thompson
349