hpc-lab-code/lab1/do_lab.sh
2025-11-17 20:29:14 +08:00

97 lines
2.7 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
# cd to the directory where this script lives
cd "$(dirname "$0")"
echo "Running make..."
make
# detect MPI launcher
if command -v mpirun >/dev/null 2>&1; then
MPI_LAUNCHER=mpirun
MPI_FLAG="-np"
elif command -v mpiexec >/dev/null 2>&1; then
MPI_LAUNCHER=mpiexec
MPI_FLAG="-n"
else
echo "Error: neither mpirun nor mpiexec found in PATH." >&2
exit 2
fi
# detect number of processes (fallback to 4)
if command -v nproc >/dev/null 2>&1; then
NP=$(nproc)
elif [ -n "${NUMBER_OF_PROCESSORS-}" ]; then
NP=$NUMBER_OF_PROCESSORS
else
NP=4
fi
echo "Using $MPI_LAUNCHER $MPI_FLAG $NP"
# helper to measure elapsed "real" time (seconds) while also showing program output
measure_time() {
local label="$1"; shift
local -a cmd=("$@")
echo "---- Running: $label ----"
echo "Command: ${cmd[*]}"
local outfile timefile
outfile=$(mktemp)
timefile=$(mktemp)
if command -v /usr/bin/time >/dev/null 2>&1; then
# /usr/bin/time prints real time with %e (seconds) into timefile
/usr/bin/time -f "%e" -o "$timefile" "${cmd[@]}" 2>&1 | tee "$outfile"
elapsed=$(<"$timefile")
else
# bash builtin time: capture stderr (which receives the timing) and stdout separately
TIMEFORMAT='%R'
{ time "${cmd[@]}" 1> "$outfile"; } 2> "$timefile"
elapsed=$(<"$timefile")
# also print program output
cat "$outfile"
fi
rm -f "$outfile" "$timefile"
# normalize elapsed to a number (strip spaces)
echo "${elapsed//[[:space:]]/}"
}
# ensure executables exist
for exe in mpi_hello_world mpi_pi serial_pi; do
if [ ! -x "./$exe" ]; then
echo "Error: executable ./$exe not found or not executable. Did make build it?" >&2
exit 3
fi
done
# run mpi_hello_world (show output, don't measure for comparison)
echo "==> Executing mpi_hello_world"
"$MPI_LAUNCHER" "$MPI_FLAG" "$NP" ./mpi_hello_world
# measure mpi_pi
mpi_elapsed=$(measure_time "mpi_pi" "$MPI_LAUNCHER" "$MPI_FLAG" "$NP" ./mpi_pi)
# measure serial_pi
serial_elapsed=$(measure_time "serial_pi" ./serial_pi)
# compute comparison
# protect against zero
if awk "BEGIN{exit($mpi_elapsed <= 0)}"; then
echo "Error: measured mpi_pi time is zero or negative." >&2
exit 4
fi
speedup=$(awk -v s="$serial_elapsed" -v m="$mpi_elapsed" 'BEGIN{ if(m==0){print "inf"; exit} printf "%.3f", s/m }')
diff=$(awk -v s="$serial_elapsed" -v m="$mpi_elapsed" 'BEGIN{printf "%.3f", s-m }')
echo
echo "Summary:"
echo " mpi_pi time (s): $mpi_elapsed"
echo " serial_pi time (s): $serial_elapsed"
echo " Difference (serial - mpi) (s): $diff"
echo " Speedup (serial / mpi): $speedup x"
exit 0