diff --git a/Dockerfile b/Dockerfile index 84b7175..304c332 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ ### GENERAL SETUP ################################################################################ -FROM ubuntu:latest as llvm +FROM ubuntu:22.04 as llvm # User directory ENV USER=user @@ -10,15 +10,17 @@ ENV HOME=/home/user WORKDIR $HOME # Install dependencies -RUN apt update -y && \ - apt install -y \ - wget \ - git \ - cmake \ - ninja-build \ - clang \ - lld \ - python3-pip +RUN apt-get update -y && \ + apt-get install -y --no-install-recommends \ + wget=1.21.2-2ubuntu1 \ + git=1:2.34.1-1ubuntu1.5 \ + cmake=3.22.1-1ubuntu1.22.04.1 \ + ninja-build=1.10.1-1 \ + clang=1:14.0-55~exp2 \ + lld=1:14.0-55~exp2 \ + python3-pip=22.0.2+dfsg-1 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* ################################################################################ ### Install mlir-dace @@ -40,36 +42,22 @@ RUN cmake -G Ninja ../llvm \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ -DLLVM_ENABLE_LLD=ON \ - -DLLVM_INSTALL_UTILS=ON - -RUN ninja - -# Install and clear build folder -RUN mkdir -p $HOME/llvm-dcir -RUN DESTDIR=$HOME/llvm-dcir ninja install - -# Add binaries to PATH -ENV PATH=$HOME/llvm-dcir/usr/local/bin:$PATH + -DLLVM_INSTALL_UTILS=ON && \ + ninja # Build mlir-dace WORKDIR $HOME/mlir-dace/build RUN cmake -G Ninja .. \ - -DMLIR_DIR=$HOME/llvm-dcir/usr/local/lib/cmake/mlir \ - -DLLVM_EXTERNAL_LIT=$HOME/llvm-dcir/usr/local/bin/llvm-lit \ + -DMLIR_DIR=$HOME/mlir-dace/llvm-project/build/lib/cmake/mlir \ + -DLLVM_EXTERNAL_LIT=$HOME/mlir-dace/llvm-project/build/bin/llvm-lit \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ - -DCMAKE_BUILD_TYPE=Release - -RUN ninja - -RUN DESTDIR=$HOME/llvm-dcir ninja install - -WORKDIR $HOME/bin -RUN cp $HOME/mlir-dace/build/bin/* . - -# Clean up build folders for space -RUN rm -rf $HOME/mlir-dace $HOME/llvm-dcir + -DCMAKE_BUILD_TYPE=Release && \ + ninja && \ + mkdir -p $HOME/bin && \ + cp $HOME/mlir-dace/build/bin/* $HOME/bin && \ + rm -rf $HOME/mlir-dace # Go home WORKDIR $HOME @@ -79,8 +67,8 @@ WORKDIR $HOME ################################################################################ # Install python dependencies -RUN pip install --upgrade pip -RUN pip install --upgrade "jax[cpu]" +RUN pip install --upgrade --no-cache-dir pip==22.3.1 && \ + pip install --upgrade --no-cache-dir "jax[cpu]"==0.4.1 # Get MLIR-HLO RUN git clone --depth 1 --branch cgo23 https://github.com/Berke-Ates/mlir-hlo.git @@ -90,10 +78,10 @@ WORKDIR $HOME/mlir-hlo RUN git clone https://github.com/llvm/llvm-project.git WORKDIR $HOME/mlir-hlo/llvm-project -RUN git checkout $(cat ../build_tools/llvm_version.txt) +RUN git checkout "$(cat ../build_tools/llvm_version.txt)" WORKDIR $HOME/mlir-hlo -RUN build_tools/build_mlir.sh ${PWD}/llvm-project/ ${PWD}/llvm-build +RUN build_tools/build_mlir.sh "$PWD"/llvm-project/ "$PWD"/llvm-build # Build MLIR-HLO WORKDIR $HOME/mlir-hlo/build @@ -102,16 +90,10 @@ RUN cmake .. -GNinja \ -DLLVM_ENABLE_LLD=ON \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_ASSERTIONS=On \ - -DMLIR_DIR=${PWD}/../llvm-build/lib/cmake/mlir - -RUN DESTDIR=$HOME/llvm-mlir-hlo ninja install - -# Copy binaries -WORKDIR $HOME/bin -RUN cp $HOME/mlir-hlo/build/bin/mlir-hlo-opt . - -# Clean up build folders for space -RUN rm -rf $HOME/mlir-hlo $HOME/llvm-mlir-hlo + -DMLIR_DIR="$PWD"/../llvm-build/lib/cmake/mlir && \ + ninja && \ + cp $HOME/mlir-hlo/build/bin/mlir-hlo-opt $HOME/bin && \ + rm -rf $HOME/mlir-hlo # Go home WORKDIR $HOME @@ -134,18 +116,12 @@ RUN cmake -G Ninja ../llvm-project/llvm \ -DLLVM_EXTERNAL_POLYGEIST_SOURCE_DIR=.. \ -DLLVM_TARGETS_TO_BUILD="host" \ -DLLVM_ENABLE_ASSERTIONS=ON \ - -DCMAKE_BUILD_TYPE=Release - -RUN DESTDIR=$HOME/llvm-polygeist ninja install - -# Copy binaries -WORKDIR $HOME/bin -RUN cp $HOME/llvm-polygeist/usr/local/bin/cgeist . -RUN cp $HOME/llvm-polygeist/usr/local/bin/mlir-opt . -RUN cp $HOME/llvm-polygeist/usr/local/bin/mlir-translate . - -# Clean up build folders for space -RUN rm -rf $HOME/Polygeist $HOME/llvm-polygeist + -DCMAKE_BUILD_TYPE=Release && \ + ninja && \ + cp $HOME/Polygeist/build/bin/cgeist $HOME/bin && \ + cp $HOME/Polygeist/build/bin/mlir-opt $HOME/bin && \ + cp $HOME/Polygeist/build/bin/mlir-translate $HOME/bin && \ + rm -rf $HOME/Polygeist # Go home WORKDIR $HOME @@ -155,7 +131,7 @@ WORKDIR $HOME ################################################################################ # Copy binaries -FROM ubuntu:latest +FROM ubuntu:22.04 # User directory ENV USER=user @@ -163,41 +139,50 @@ ENV HOME=/home/user WORKDIR $HOME # Move dotfiles -RUN mv /root/.bashrc . -RUN mv /root/.profile . +RUN mv /root/.bashrc . && mv /root/.profile . # Make terminal colorful ENV TERM=xterm-color # Install dependencies -RUN apt update -y && \ - apt install -y \ - wget \ - git \ - clang-13 \ - lld \ - python3-pip +RUN apt-get update -y && \ + apt-get install -y --no-install-recommends \ + wget=1.21.2-2ubuntu1 \ + git=1:2.34.1-1ubuntu1.5 \ + cmake=3.22.1-1ubuntu1.22.04.1 \ + make=4.3-4.1build1 \ + ninja-build=1.10.1-1 \ + clang-13=1:13.0.1-2ubuntu2.1 \ + gcc=4:11.2.0-1ubuntu1 \ + lld=1:14.0-55~exp2 \ + python3-pip=22.0.2+dfsg-1 \ + python3=3.10.6-1~22.04 \ + python3-dev=3.10.6-1~22.04 \ + gpg=2.2.27-3ubuntu2.1 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* # Launch bash shell at home -ENTRYPOINT cd $HOME && bash +ENTRYPOINT ["/bin/bash", "-c"] +CMD ["cd $HOME && bash"] + +# Python dependencies +RUN pip install --upgrade --no-cache-dir pip==22.3.1 && \ + pip install --upgrade --no-cache-dir seaborn==0.12.2 -# Dependencies for plotting -RUN pip install --upgrade pip -RUN pip install --upgrade seaborn +# Get Polybench comparator +RUN git clone --depth 1 --branch cgo23 https://github.com/Berke-Ates/polybench-comparator.git # Copy Binaries COPY --from=llvm $HOME/bin $HOME/bin # Add clang copy -RUN cp `which clang-13` $HOME/bin/clang -RUN cp `which clang-13` $HOME/bin/clang++ +RUN cp "$(which clang-13)" $HOME/bin/clang && \ + cp "$(which clang-13)" $HOME/bin/clang++ # Add binaries to PATH ENV PATH=$HOME/bin:$PATH -# Get Polybench comparator -RUN git clone --depth 1 --branch cgo23 https://github.com/Berke-Ates/polybench-comparator.git - ################################################################################ ### Install torch-mlir ################################################################################ @@ -208,8 +193,9 @@ WORKDIR $HOME/torch-mlir RUN git submodule update --init --recursive --depth 1 # Install python dependencies -RUN pip install --upgrade pip -RUN pip install -r requirements.txt +RUN pip install --upgrade --no-cache-dir pip==22.3.1 && \ + sed -i -e 's/1.14.0.dev20221109/2.0.0.dev20221231/g' pytorch-requirements.txt && \ + pip install --no-cache-dir -r requirements.txt # Build torch-mlir in-tree WORKDIR $HOME/torch-mlir/build @@ -230,9 +216,8 @@ RUN cmake -G Ninja ../externals/llvm-project/llvm \ -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" \ -DLLVM_INSTALL_UTILS=ON \ -DLIBTORCH_SRC_BUILD=ON \ - -DLIBTORCH_VARIANT=shared - -RUN ninja + -DLIBTORCH_VARIANT=shared && \ + ninja # Go home WORKDIR $HOME @@ -246,16 +231,25 @@ ENV PYTHONPATH=$HOME/torch-mlir/build/../examples:$PYTHONPATH ### Install ICC ################################################################################ -RUN wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \ +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +RUN wget --progress=dot:giga -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \ | gpg --dearmor \ | tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null RUN echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" \ | tee /etc/apt/sources.list.d/oneAPI.list -RUN apt update -y && apt install -y intel-hpckit +RUN apt-get update -y && \ + apt-get install -y --no-install-recommends \ + intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic=2023.0.0-25370 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN echo "source /opt/intel/oneapi/compiler/latest/env/vars.sh" >> $HOME/.bashrc -RUN echo "source /opt/intel/oneapi/compiler/2022.2.1/env/vars.sh" >> $HOME/.bashrc +# Go home +WORKDIR $HOME ################################################################################ ### Install dace @@ -264,10 +258,11 @@ RUN echo "source /opt/intel/oneapi/compiler/2022.2.1/env/vars.sh" >> $HOME/.bash RUN git clone --depth 1 --branch cgo23 https://github.com/Berke-Ates/dace.git WORKDIR $HOME/dace -RUN git submodule update --init --recursive --depth 1 - -RUN pip install --editable . +RUN git submodule update --init --recursive --depth 1 && \ + pip install --no-cache-dir --editable . && \ + pip install --no-cache-dir mxnet-mkl==1.6.0 numpy==1.23.1 +# Go home WORKDIR $HOME ################################################################################ diff --git a/benchmarks/pytorch/mish/pytorch_jit.py b/benchmarks/pytorch/mish/pytorch_jit.py new file mode 100644 index 0000000..c58e529 --- /dev/null +++ b/benchmarks/pytorch/mish/pytorch_jit.py @@ -0,0 +1,78 @@ +#!/usr/bin/python3 + +# Desc: Runs the Mish benchmark using Pytorch with JIT +# Usage: python3 pytorch_jit.py + +import sys +import numpy as np +import torch +from torch import nn +import time +import torch_mlir + +from torch_mlir_e2e_test.mhlo_backends.linalg_on_tensors import LinalgOnTensorsMhloBackend + +if len(sys.argv) != 3: + print("PyTorch(JIT) Mish Benchmarking Tool") + print("Arguments:") + print(" Repetitions: How many times to run the benchmark") + print(" Test Output (T/F): If 'T', tests the output against Torch-MLIR") + exit(1) + +repetitions = int(sys.argv[1]) +test_output = sys.argv[2] == 'T' + + +# Load model +class Mish(nn.Module): + + def __init__(self): + super().__init__() + + def forward(self, x): + x = torch.log(1 + torch.exp(x)) + return x + + +data = torch.rand(8, 32, 224, 224) +model = torch.jit.trace(Mish(), data).to(torch.device('cpu')) +model.eval() + +# Benchmark +for i in range(repetitions): + data = torch.rand(8, 32, 224, 224) + start = time.time() + model.forward(data) + runtime = time.time() - start + print(runtime * 1000) + +# Test output +if test_output: + data = torch.zeros(8, 32, 224, 224) + + for i in range(8): + for j in range(32): + for k in range(224): + for l in range(224): + data[i, j, k, l] = (i + j + k + l) / (8 + 32 + 224 + 224) + + prediction_pytorch = model.forward(data).numpy() + + # Generate MHLO + backend = LinalgOnTensorsMhloBackend() + + model_mlir = nn.Sequential(Mish()).to(torch.device('cpu')) + model_mlir.eval() + module = torch_mlir.compile(model_mlir, + data, + output_type=torch_mlir.OutputType.MHLO) + + compiled = backend.compile(module) + jit_module = backend.load(compiled) + + prediction_torch_mlir = jit_module.forward(data.numpy()) + + # Compare + if not np.allclose( + prediction_pytorch, prediction_torch_mlir, rtol=1e-5, atol=1e-8): + exit(1) diff --git a/scripts/Polybench/clang.sh b/scripts/Polybench/clang.sh index 32482d3..0d57611 100755 --- a/scripts/Polybench/clang.sh +++ b/scripts/Polybench/clang.sh @@ -4,6 +4,11 @@ # intermediate results and the times in the CSV format # Usage: ./clang.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./clang.sh " @@ -16,10 +21,10 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } @@ -28,32 +33,33 @@ check_tool gcc check_tool python3 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Helpers -input_name=$(basename ${input_file%.*}) -input_dir=$(dirname $input_file) +input_name=$(basename "${input_file%.*}") +input_dir=$(dirname "$input_file") utils_dir=$input_dir/../utilities -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +scripts_dir=$(dirname "$0")/.. +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" reference=$output_dir/${input_name}_reference.txt actual=$output_dir/${input_name}_actual_clang.txt # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Flags for the benchmark @@ -66,22 +72,23 @@ if [[ "$input_name" == "gramschmidt" ]]; then fi # Compile -clang -I $utils_dir -O$opt_lvl_cc $flags -o $output_dir/${input_name}_clang.out \ - $input_file $utils_dir/polybench.c -lm +# shellcheck disable=SC2086 +clang -I "$utils_dir" -O$opt_lvl_cc $flags -o "$output_dir"/"${input_name}"_clang.out \ + "$input_file" "$utils_dir"/polybench.c -lm # Check output -clang -I $utils_dir -O$opt_lvl_cc $flags -DPOLYBENCH_DUMP_ARRAYS \ - -o $output_dir/${input_name}_clang_dump.out $input_file $utils_dir/polybench.c -lm - -gcc -I $utils_dir -O0 $flags -DPOLYBENCH_DUMP_ARRAYS \ - -o $output_dir/${input_name}_gcc_ref.out $input_file $utils_dir/polybench.c -lm +# shellcheck disable=SC2086 +clang -I "$utils_dir" -O$opt_lvl_cc $flags -DPOLYBENCH_DUMP_ARRAYS \ + -o "$output_dir"/"${input_name}"_clang_dump.out "$input_file" "$utils_dir"/polybench.c -lm -$output_dir/${input_name}_clang_dump.out 2> $actual 1> /dev/null -$output_dir/${input_name}_gcc_ref.out 2> $reference 1> /dev/null +# shellcheck disable=SC2086 +gcc -I "$utils_dir" -O0 $flags -DPOLYBENCH_DUMP_ARRAYS \ + -o "$output_dir"/"${input_name}"_gcc_ref.out "$input_file" "$utils_dir"/polybench.c -lm -python3 $scripts_dir/../polybench-comparator/comparator.py $reference $actual +"$output_dir"/"${input_name}"_clang_dump.out 2>"$actual" 1>/dev/null +"$output_dir"/"${input_name}"_gcc_ref.out 2>"$reference" 1>/dev/null -if [ $? -ne 0 ]; then +if ! python3 "$scripts_dir"/../polybench-comparator/comparator.py "$reference" "$actual"; then echo "Output incorrect!" exit 1 fi @@ -89,7 +96,7 @@ fi # Running the benchmark add_csv "Clang" -for i in $(seq 1 $repetitions); do - time=$(OMP_NUM_THREADS=1 taskset -c 0 ./$output_dir/${input_name}_clang.out) +for _ in $(seq 1 "$repetitions"); do + time=$(OMP_NUM_THREADS=1 taskset -c 0 ./"$output_dir"/"${input_name}"_clang.out) add_csv "$time" done diff --git a/scripts/Polybench/dace.sh b/scripts/Polybench/dace.sh index 8f40f69..6cf8a71 100755 --- a/scripts/Polybench/dace.sh +++ b/scripts/Polybench/dace.sh @@ -4,6 +4,11 @@ # intermediate results and the times in the CSV format # Usage: ./dace.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./dace.sh " @@ -16,49 +21,49 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } check_tool python3 -check_tool icc +check_tool clang +check_tool clang++ # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Clear .dacecache rm -rf .dacecache # Helpers -input_name=$(basename ${input_file%.*}) -input_dir=$(dirname $input_file) -utils_dir=$input_dir/../utilities -current_dir=$(dirname $0) -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +input_name=$(basename "${input_file%.*}") +input_dir=$(dirname "$input_file") +current_dir=$(dirname "$0") +scripts_dir=$(dirname "$0")/.. +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Flags for the benchmark -flags="-DLARGE_DATASET -DDATA_TYPE_IS_DOUBLE -DPOLYBENCH_TIME -fPIC -march=native" opt_lvl_cc=3 # Optimization level for the control-centric optimizations opt_lvl_dc=3 # Optimization level for the data-centric optimizations @@ -67,43 +72,47 @@ if [[ "$input_name" == "gramschmidt" ]]; then opt_lvl_cc=2 fi -if [[ "$input_name" == "durbin" ]] || \ - [[ "$input_name" == "gemver" ]] || \ - [[ "$input_name" == "doitgen" ]]; then +if [[ "$input_name" == "durbin" ]] || + [[ "$input_name" == "gemver" ]] || + [[ "$input_name" == "doitgen" ]]; then opt_lvl_dc=2 fi -if [[ "$input_name" == "floyd-warshall" ]] || \ - [[ "$input_name" == "3mm" ]] || \ - [[ "$input_name" == "cholesky" ]] || \ - [[ "$input_name" == "gemm" ]] || \ - [[ "$input_name" == "lu" ]] || \ - [[ "$input_name" == "ludcmp" ]] || \ - [[ "$input_name" == "symm" ]] || \ - [[ "$input_name" == "syr2k" ]]; then +if [[ "$input_name" == "floyd-warshall" ]] || + [[ "$input_name" == "3mm" ]] || + [[ "$input_name" == "cholesky" ]] || + [[ "$input_name" == "gemm" ]] || + [[ "$input_name" == "lu" ]] || + [[ "$input_name" == "ludcmp" ]] || + [[ "$input_name" == "symm" ]] || + [[ "$input_name" == "syr2k" ]]; then opt_lvl_dc=1 fi # Dace Settings -export DACE_compiler_cpu_executable="$(which clang++)" -export CC=`which clang` -export CXX=`which clang++` +DACE_compiler_cpu_executable="$(which clang++)" +export DACE_compiler_cpu_executable +CC=$(which clang) +export CC +CXX=$(which clang++) +export CXX export DACE_compiler_cpu_openmp_sections=0 export DACE_instrumentation_report_each_invocation=0 export DACE_compiler_cpu_args="-fPIC -O$opt_lvl_cc -march=native" +export PYTHONWARNINGS="ignore" # Optimizing data-centrically with DaCe -python3 $scripts_dir/opt_sdfg.py $input_dir/${input_name}_c2dace.sdfg \ - $output_dir/${input_name}_c2dace_opt.sdfg $opt_lvl_dc T +python3 "$scripts_dir"/opt_sdfg.py "$input_dir"/"${input_name}"_c2dace.sdfg \ + "$output_dir"/"${input_name}"_c2dace_opt.sdfg $opt_lvl_dc T # Running the benchmark -OMP_NUM_THREADS=1 taskset -c 0 python3 $current_dir/bench_dace.py \ - $output_dir/${input_name}_c2dace_opt.sdfg $repetitions +OMP_NUM_THREADS=1 taskset -c 0 python3 "$current_dir"/bench_dace.py \ + "$output_dir"/"${input_name}"_c2dace_opt.sdfg "$repetitions" &>/dev/null add_csv "DaCe" -for i in $(seq 1 $repetitions); do - time=$(python3 $scripts_dir/get_sdfg_times.py \ - $output_dir/${input_name}_c2dace_opt.sdfg $((i-1)) T) +for i in $(seq 1 "$repetitions"); do + time=$(python3 "$scripts_dir"/get_sdfg_times.py \ + "$output_dir"/"${input_name}"_c2dace_opt.sdfg $((i - 1)) T) add_csv "$time" done diff --git a/scripts/Polybench/dcir.sh b/scripts/Polybench/dcir.sh index 206ce05..f1508d6 100755 --- a/scripts/Polybench/dcir.sh +++ b/scripts/Polybench/dcir.sh @@ -4,6 +4,11 @@ # intermediate results and the times in the CSV format # Usage: ./dcir.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./dcir.sh " @@ -16,14 +21,15 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } check_tool clang +check_tool clang++ check_tool clang-13 check_tool gcc check_tool cgeist @@ -31,39 +37,39 @@ check_tool mlir-opt check_tool sdfg-opt check_tool sdfg-translate check_tool python3 -check_tool icc # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Clear .dacecache rm -rf .dacecache # Helpers -input_name=$(basename ${input_file%.*}) -input_dir=$(dirname $input_file) +input_name=$(basename "${input_file%.*}") +input_dir=$(dirname "$input_file") utils_dir=$input_dir/../utilities -current_dir=$(dirname $0) -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +current_dir=$(dirname "$0") +scripts_dir=$(dirname "$0")/.. +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" reference=$output_dir/${input_name}_reference.txt actual=$output_dir/${input_name}_actual_dcir.txt # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Flags for the benchmark @@ -76,9 +82,9 @@ if [[ "$input_name" == "gramschmidt" ]]; then opt_lvl_cc=2 fi -if [[ "$input_name" == "durbin" ]] || \ - [[ "$input_name" == "gemver" ]] || \ - [[ "$input_name" == "doitgen" ]]; then +if [[ "$input_name" == "durbin" ]] || + [[ "$input_name" == "gemver" ]] || + [[ "$input_name" == "doitgen" ]]; then opt_lvl_dc=2 fi @@ -87,84 +93,93 @@ if [[ "$input_name" == "floyd-warshall" ]]; then fi # Dace Settings -export DACE_compiler_cpu_executable="$(which clang++)" -export CC=`which clang` -export CXX=`which clang++` +DACE_compiler_cpu_executable="$(which clang++)" +export DACE_compiler_cpu_executable +CC=$(which clang) +export CC +CXX=$(which clang++) +export CXX export DACE_compiler_cpu_openmp_sections=0 export DACE_instrumentation_report_each_invocation=0 export DACE_compiler_cpu_args="-fPIC -O$opt_lvl_cc -march=native" +export PYTHONWARNINGS="ignore" # Generating MLIR from C using Polygeist -cgeist -resource-dir=$(clang-13 -print-resource-dir) -I $utils_dir \ - -S --memref-fullrank -O$opt_lvl_cc --raise-scf-to-affine $flags $input_file \ - > $output_dir/${input_name}_cgeist.mlir +# shellcheck disable=SC2086 +cgeist -resource-dir="$(clang-13 -print-resource-dir)" -I "$utils_dir" \ + -S --memref-fullrank -O$opt_lvl_cc --raise-scf-to-affine $flags "$input_file" \ + >"$output_dir"/"${input_name}"_cgeist.mlir # Optimizing with MLIR -mlir-opt --affine-loop-invariant-code-motion $output_dir/${input_name}_cgeist.mlir | \ -mlir-opt --affine-scalrep | mlir-opt --lower-affine | \ -mlir-opt --cse --inline > $output_dir/${input_name}_opt.mlir +mlir-opt --affine-loop-invariant-code-motion "$output_dir"/"${input_name}"_cgeist.mlir | + mlir-opt --affine-scalrep | mlir-opt --lower-affine | + mlir-opt --cse --inline >"$output_dir"/"${input_name}"_opt.mlir # Converting to DCIR -sdfg-opt --convert-to-sdfg $output_dir/${input_name}_opt.mlir \ - > $output_dir/${input_name}_sdfg.mlir +sdfg-opt --convert-to-sdfg "$output_dir"/"${input_name}"_opt.mlir \ + >"$output_dir"/"${input_name}"_sdfg.mlir # Translating to SDFG -sdfg-translate --mlir-to-sdfg $output_dir/${input_name}_sdfg.mlir \ - > $output_dir/$input_name.sdfg +sdfg-translate --mlir-to-sdfg "$output_dir"/"${input_name}"_sdfg.mlir \ + >"$output_dir"/"$input_name".sdfg # Optimizing data-centrically with DaCe -python3 $scripts_dir/opt_sdfg.py $output_dir/$input_name.sdfg \ - $output_dir/${input_name}_opt.sdfg $opt_lvl_dc T +python3 "$scripts_dir"/opt_sdfg.py "$output_dir"/"$input_name".sdfg \ + "$output_dir"/"${input_name}"_opt.sdfg $opt_lvl_dc T # Check output -gcc -I $utils_dir -O0 $flags -DPOLYBENCH_DUMP_ARRAYS \ - -o $output_dir/${input_name}_gcc_ref.out $input_file $utils_dir/polybench.c -lm +# shellcheck disable=SC2086 +gcc -I "$utils_dir" -O0 $flags -DPOLYBENCH_DUMP_ARRAYS \ + -o "$output_dir"/"${input_name}"_gcc_ref.out "$input_file" "$utils_dir"/polybench.c -lm -python3 $current_dir/bench_dcir.py $output_dir/${input_name}_opt.sdfg 1 T 2> $actual 1> /dev/null -$output_dir/${input_name}_gcc_ref.out 2> $reference 1> /dev/null +python3 "$current_dir"/bench_dcir.py "$output_dir"/"${input_name}"_opt.sdfg 1 T 2>"$actual" 1>/dev/null +"$output_dir"/"${input_name}"_gcc_ref.out 2>"$reference" 1>/dev/null ## Obtain array names -touch $output_dir/arrNames.txt +touch "$output_dir"/arr_names.txt -grep "begin dump:" $reference | while read -r line ; do - arrTmp=($line) - arrName=${arrTmp[2]} - echo -n "$arrName " >> $output_dir/arrNames.txt +grep "begin dump:" "$reference" | while read -r line; do + # shellcheck disable=SC2206 + arr_tmp=($line) + arr_name=${arr_tmp[2]} + echo -n "$arr_name " >>"$output_dir"/arr_names.txt done -arrNames=($(cat $output_dir/arrNames.txt)) -rm $output_dir/arrNames.txt +mapfile -t -d " " arr_names < <(cat "$output_dir"/arr_names.txt) +rm "$output_dir"/arr_names.txt ## Remove Warnings from output -sed -i '0,/^==BEGIN DUMP_ARRAYS==$/d' $actual -printf '%s\n%s\n' "==BEGIN DUMP_ARRAYS==" "$(cat $actual)" > $actual +sed -i '0,/^==BEGIN DUMP_ARRAYS==$/d' "$actual" +content_actual=$(cat "$actual") +printf '%s\n%s\n' "==BEGIN DUMP_ARRAYS==" "$content_actual" >"$actual" ## Use original array names idx=0 -grep "begin dump:" $actual | while read -r line ; do - arrTmp=($line) - arrName=${arrTmp[2]} - repArrName=${arrNames[idx]} - sed -i -e "s/$arrName/$repArrName/g" $actual - idx=$((idx+1)) +grep "begin dump:" "$actual" | while read -r line; do + # shellcheck disable=SC2206 + arr_tmp=($line) + arr_name=${arr_tmp[2]} + rep_arr_name=${arr_names[idx]} + sed -i -e "s/$arr_name/$rep_arr_name/g" "$actual" + idx=$((idx + 1)) done ## Compare the outputs -python3 $scripts_dir/../polybench-comparator/comparator.py $reference $actual - -if [ $? -ne 0 ]; then +set +e +if ! python3 "$scripts_dir"/../polybench-comparator/comparator.py "$reference" "$actual"; then echo "Output incorrect!" exit 1 fi +set -e # Running the benchmark -OMP_NUM_THREADS=1 taskset -c 0 python3 $current_dir/bench_dcir.py \ - $output_dir/${input_name}_opt.sdfg $repetitions F +OMP_NUM_THREADS=1 taskset -c 0 python3 "$current_dir"/bench_dcir.py \ + "$output_dir"/"${input_name}"_opt.sdfg "$repetitions" F add_csv "DCIR" -for i in $(seq 1 $repetitions); do - time=$(python3 $scripts_dir/get_sdfg_times.py \ - $output_dir/${input_name}_opt.sdfg $((i-1)) T) +for i in $(seq 1 "$repetitions"); do + time=$(python3 "$scripts_dir"/get_sdfg_times.py \ + "$output_dir"/"${input_name}"_opt.sdfg $((i - 1)) T) add_csv "$time" done diff --git a/scripts/Polybench/gcc.sh b/scripts/Polybench/gcc.sh index 8bff2fe..8de67da 100755 --- a/scripts/Polybench/gcc.sh +++ b/scripts/Polybench/gcc.sh @@ -4,6 +4,11 @@ # intermediate results and the times in the CSV format # Usage: ./gcc.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./gcc.sh " @@ -16,10 +21,10 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } @@ -28,32 +33,33 @@ check_tool clang check_tool python3 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Helpers -input_name=$(basename ${input_file%.*}) -input_dir=$(dirname $input_file) +input_name=$(basename "${input_file%.*}") +input_dir=$(dirname "$input_file") utils_dir=$input_dir/../utilities -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +scripts_dir=$(dirname "$0")/.. +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" reference=$output_dir/${input_name}_reference.txt actual=$output_dir/${input_name}_actual_gcc.txt # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Flags for the benchmark @@ -66,22 +72,23 @@ if [[ "$input_name" == "gramschmidt" ]]; then fi # Compile -gcc -I $utils_dir -O$opt_lvl_cc $flags -o $output_dir/${input_name}_gcc.out \ - $input_file $utils_dir/polybench.c -lm +# shellcheck disable=SC2086 +gcc -I "$utils_dir" -O$opt_lvl_cc $flags -o "$output_dir"/"${input_name}"_gcc.out \ + "$input_file" "$utils_dir"/polybench.c -lm # Check output -gcc -I $utils_dir -O$opt_lvl_cc $flags -DPOLYBENCH_DUMP_ARRAYS \ - -o $output_dir/${input_name}_gcc_dump.out $input_file $utils_dir/polybench.c -lm - -clang -I $utils_dir -O0 $flags -DPOLYBENCH_DUMP_ARRAYS \ - -o $output_dir/${input_name}_clang_ref.out $input_file $utils_dir/polybench.c -lm +# shellcheck disable=SC2086 +gcc -I "$utils_dir" -O$opt_lvl_cc $flags -DPOLYBENCH_DUMP_ARRAYS \ + -o "$output_dir"/"${input_name}"_gcc_dump.out "$input_file" "$utils_dir"/polybench.c -lm -$output_dir/${input_name}_gcc_dump.out 2> $actual 1> /dev/null -$output_dir/${input_name}_clang_ref.out 2> $reference 1> /dev/null +# shellcheck disable=SC2086 +clang -I "$utils_dir" -O0 $flags -DPOLYBENCH_DUMP_ARRAYS \ + -o "$output_dir"/"${input_name}"_clang_ref.out "$input_file" "$utils_dir"/polybench.c -lm -python3 $scripts_dir/../polybench-comparator/comparator.py $reference $actual +"$output_dir"/"${input_name}"_gcc_dump.out 2>"$actual" 1>/dev/null +"$output_dir"/"${input_name}"_clang_ref.out 2>"$reference" 1>/dev/null -if [ $? -ne 0 ]; then +if ! python3 "$scripts_dir"/../polybench-comparator/comparator.py "$reference" "$actual"; then echo "Output incorrect!" exit 1 fi @@ -89,7 +96,7 @@ fi # Running the benchmark add_csv "GCC" -for i in $(seq 1 $repetitions); do - time=$(OMP_NUM_THREADS=1 taskset -c 0 ./$output_dir/${input_name}_gcc.out) +for _ in $(seq 1 "$repetitions"); do + time=$(OMP_NUM_THREADS=1 taskset -c 0 ./"$output_dir"/"${input_name}"_gcc.out) add_csv "$time" done diff --git a/scripts/Polybench/mlir.sh b/scripts/Polybench/mlir.sh index e3042d5..dc3704f 100755 --- a/scripts/Polybench/mlir.sh +++ b/scripts/Polybench/mlir.sh @@ -1,9 +1,14 @@ #!/bin/bash -# Desc: Runs a Polybench benchmark using Polygeist + MLIR. The output contains +# Desc: Runs a Polybench benchmark using Polygeist + MLIR. The output contains # any intermediate results and the times in the CSV format # Usage: ./mlir.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./mlir.sh " @@ -16,10 +21,10 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } @@ -32,32 +37,33 @@ check_tool mlir-translate check_tool python3 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Helpers -input_name=$(basename ${input_file%.*}) -input_dir=$(dirname $input_file) +input_name=$(basename "${input_file%.*}") +input_dir=$(dirname "$input_file") utils_dir=$input_dir/../utilities -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +scripts_dir=$(dirname "$0")/.. +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" reference=$output_dir/${input_name}_reference.txt actual=$output_dir/${input_name}_actual_mlir.txt # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Flags for the benchmark @@ -70,37 +76,39 @@ if [[ "$input_name" == "gramschmidt" ]]; then fi # Compiling with MLIR -compile_with_mlir(){ +compile_with_mlir() { additional_flags=$1 output_name=$2 # Generating MLIR from C using Polygeist - cgeist -resource-dir=$(clang-13 -print-resource-dir) -I $utils_dir \ + # shellcheck disable=SC2086 + cgeist -resource-dir="$(clang-13 -print-resource-dir)" -I "$utils_dir" \ -S --memref-fullrank -O$opt_lvl_cc --raise-scf-to-affine $flags \ - $additional_flags $input_file > $output_dir/${output_name}_cgeist.mlir + $additional_flags "$input_file" >"$output_dir"/"${output_name}"_cgeist.mlir # Optimizing with MLIR mlir-opt --affine-loop-invariant-code-motion \ - $output_dir/${output_name}_cgeist.mlir | \ - mlir-opt --affine-scalrep | mlir-opt --lower-affine | \ - mlir-opt --cse --inline > $output_dir/${output_name}_opt.mlir + "$output_dir"/"${output_name}"_cgeist.mlir | + mlir-opt --affine-scalrep | mlir-opt --lower-affine | + mlir-opt --cse --inline >"$output_dir"/"${output_name}"_opt.mlir # Lower to LLVM dialect mlir-opt --convert-scf-to-cf --convert-func-to-llvm --convert-cf-to-llvm \ --convert-math-to-llvm --lower-host-to-llvm --reconcile-unrealized-casts \ - $output_dir/${output_name}_opt.mlir > $output_dir/${output_name}_ll.mlir + "$output_dir"/"${output_name}"_opt.mlir >"$output_dir"/"${output_name}"_ll.mlir # Translate - mlir-translate --mlir-to-llvmir $output_dir/${output_name}_ll.mlir \ - > $output_dir/${output_name}.ll + mlir-translate --mlir-to-llvmir "$output_dir"/"${output_name}"_ll.mlir \ + >"$output_dir"/"${output_name}".ll # Compile - llc -O$opt_lvl_cc --relocation-model=pic $output_dir/${output_name}.ll \ - -o $output_dir/${output_name}.s + llc -O$opt_lvl_cc --relocation-model=pic "$output_dir"/"${output_name}".ll \ + -o "$output_dir"/"${output_name}".s # Assemble - clang -O$opt_lvl_cc $flags $additional_flags $output_dir/${output_name}.s \ - $utils_dir/polybench.c -o $output_dir/${output_name}.out -lm + # shellcheck disable=SC2086 + clang -O$opt_lvl_cc $flags $additional_flags "$output_dir"/"${output_name}".s \ + "$utils_dir"/polybench.c -o "$output_dir"/"${output_name}".out -lm } # Compile @@ -109,15 +117,14 @@ compile_with_mlir "" "${input_name}_mlir" # Check output compile_with_mlir "-DPOLYBENCH_DUMP_ARRAYS" "${input_name}_mlir_dump" -gcc -I $utils_dir -O0 $flags -DPOLYBENCH_DUMP_ARRAYS \ - -o $output_dir/${input_name}_clang_ref.out $input_file $utils_dir/polybench.c -lm - -$output_dir/${input_name}_mlir_dump.out 2> $actual 1> /dev/null -$output_dir/${input_name}_clang_ref.out 2> $reference 1> /dev/null +# shellcheck disable=SC2086 +gcc -I "$utils_dir" -O0 $flags -DPOLYBENCH_DUMP_ARRAYS \ + -o "$output_dir"/"${input_name}"_clang_ref.out "$input_file" "$utils_dir"/polybench.c -lm -python3 $scripts_dir/../polybench-comparator/comparator.py $reference $actual +"$output_dir"/"${input_name}"_mlir_dump.out 2>"$actual" 1>/dev/null +"$output_dir"/"${input_name}"_clang_ref.out 2>"$reference" 1>/dev/null -if [ $? -ne 0 ]; then +if ! python3 "$scripts_dir"/../polybench-comparator/comparator.py "$reference" "$actual"; then echo "Output incorrect!" exit 1 fi @@ -125,7 +132,7 @@ fi # Running the benchmark add_csv "Polygeist + MLIR" -for i in $(seq 1 $repetitions); do - time=$(OMP_NUM_THREADS=1 taskset -c 0 ./$output_dir/${input_name}_mlir.out) +for _ in $(seq 1 "$repetitions"); do + time=$(OMP_NUM_THREADS=1 taskset -c 0 ./"$output_dir"/"${input_name}"_mlir.out) add_csv "$time" done diff --git a/scripts/Polybench/run_all.sh b/scripts/Polybench/run_all.sh index dfa0cfd..d4acac5 100755 --- a/scripts/Polybench/run_all.sh +++ b/scripts/Polybench/run_all.sh @@ -1,10 +1,15 @@ #!/bin/bash -# Desc: Runs all Polybench benchmarks using GCC, Clang, Polygeist + MLIR, DCIR -# and DaCe. The output contains any intermediate results and the times in the +# Desc: Runs all Polybench benchmarks using GCC, Clang, Polygeist + MLIR, DCIR +# and DaCe. The output contains any intermediate results and the times in the # CSV format as well as a plot with all the benchmarks. # Usage: ./run_all.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 2 ]; then echo "Usage: ./run_all.sh " @@ -16,17 +21,20 @@ output_dir=$1 repetitions=$2 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi +# Silence Python warnings +export PYTHONWARNINGS="ignore" + # Helpers -runners_dir=$(dirname $0) -scripts_dir=$(dirname $0)/.. -benchmarks_dir=$(dirname $0)/../../benchmarks/Polybench +runners_dir=$(dirname "$0") +scripts_dir=$(dirname "$0")/.. +benchmarks_dir=$(dirname "$0")/../../benchmarks/Polybench # Run benchmarks -benchmarks=$(find $benchmarks_dir/* -name '*.c' -not -path "$benchmarks_dir/utilities/*") +benchmarks=$(find "$benchmarks_dir"/* -name '*.c' -not -path "$benchmarks_dir/utilities/*") total=$(echo "$benchmarks" | wc -l) runners="$runners_dir/gcc.sh $runners_dir/clang.sh $runners_dir/dace.sh \ @@ -37,24 +45,24 @@ for runner in $runners; do echo "Running with: $runner" for benchmark in $benchmarks; do - bname="$(basename $benchmark .c)" - count=$((count+1)) - diff=$(($total - $count)) - percent=$(($count * 100 / $total)) - - prog='' - for i in $(seq 1 $count); do - prog="$prog#" - done - - for i in $(seq 1 $diff); do - prog="$prog-" - done - - echo -ne "\033[2K\r" - echo -ne "$prog ($percent%) ($bname) " - - $runner $benchmark $output_dir $repetitions + bname="$(basename "$benchmark" .c)" + count=$((count + 1)) + diff=$((total - count)) + percent=$((count * 100 / total)) + + prog='' + for _ in $(seq 1 $count); do + prog="$prog#" + done + + for _ in $(seq 1 $diff); do + prog="$prog-" + done + + echo -ne "\033[2K\r" + echo -ne "$prog ($percent%) ($bname) " + + $runner "$benchmark" "$output_dir" "$repetitions" done echo "" @@ -63,10 +71,11 @@ done csv_files=() for benchmark in $benchmarks; do - bname="$(basename $benchmark .c)" - mv "$output_dir/${bname}_timings.csv" "$output_dir/${bname}.csv" - csv_files+=("$output_dir/${bname}.csv") - cp "$output_dir/${bname}.csv" "$output_dir/fig6_${bname}.csv" + bname="$(basename "$benchmark" .c)" + mv "$output_dir/${bname}_timings.csv" "$output_dir/${bname}.csv" + csv_files+=("$output_dir/${bname}.csv") + cp "$output_dir/${bname}.csv" "$output_dir/fig6_${bname}.csv" done -python3 $scripts_dir/multi_plot.py ${csv_files[*]} $output_dir/fig6.pdf +# shellcheck disable=SC2086,SC2048 +python3 "$scripts_dir"/multi_plot.py ${csv_files[*]} "$output_dir"/fig6.pdf diff --git a/scripts/mhlo2std.sh b/scripts/mhlo2std.sh index 0c13b7b..7d5cebb 100755 --- a/scripts/mhlo2std.sh +++ b/scripts/mhlo2std.sh @@ -3,6 +3,11 @@ # Desc: Converts the mhlo dialect to builtin dialect for further conversion # Usage: ./mhlo2std.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 1 ]; then echo "Usage: ./mhlo2std.sh " @@ -12,9 +17,18 @@ fi # Read args input_file=$1 +# Check tools +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 + fi +} + +check_tool mlir-hlo-opt + # Execute conversion -mlir-hlo-opt --hlo-legalize-to-linalg $input_file `# mhli -> linalg` | \ -mlir-hlo-opt --linalg-bufferize `# bufferize linalg` | \ -mlir-hlo-opt --convert-linalg-to-affine-loops `# linalg -> affine` | \ -mlir-hlo-opt --computeop-and-func-bufferize \ - --final-bufferize=alignment=128 # tensor -> memref +mlir-hlo-opt --hlo-legalize-to-linalg "$input_file" | + mlir-hlo-opt --linalg-bufferize | + mlir-hlo-opt --convert-linalg-to-affine-loops | + mlir-hlo-opt --computeop-and-func-bufferize --final-bufferize=alignment=128 diff --git a/scripts/multi_plot.py b/scripts/multi_plot.py index 6401095..082be68 100755 --- a/scripts/multi_plot.py +++ b/scripts/multi_plot.py @@ -15,7 +15,7 @@ if len(sys.argv) < 3: print("Multi Benchmark Plotting Tool") print("Arguments:") - print(" Input CSVs: A list of CSV files to plot") + print(" Input CSVs: A list of CSV files to plot (at least 4)") print(" Output File: The filepath of the generated plot") exit(1) @@ -27,6 +27,11 @@ dt = [] num_bench = len(input_files) + +if (num_bench < 4): + print("This plotter requires at least 4 CSV files") + exit(1) + rows = 3 cols = ceil(num_bench / rows) color = ['#4D678D', '#4D678D', '#4D678D', '#4D678D', '#EA7878'] diff --git a/scripts/pytorch/dcir.sh b/scripts/pytorch/dcir.sh index af2c347..5267719 100755 --- a/scripts/pytorch/dcir.sh +++ b/scripts/pytorch/dcir.sh @@ -4,6 +4,11 @@ # intermediate results and the times in the CSV format # Usage: ./dcir.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./dcir.sh " @@ -16,15 +21,13 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } -check_tool clang -check_tool cgeist check_tool mlir-opt check_tool sdfg-opt check_tool sdfg-translate @@ -32,86 +35,90 @@ check_tool python3 check_tool icc # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Clear .dacecache rm -rf .dacecache # Helpers -input_dir=$(dirname $input_file) -input_name=$(basename $input_dir) +input_dir=$(dirname "$input_file") +input_name=$(basename "$input_dir") gen_file=$input_dir/dcir_gen.py bench_file=$input_dir/dcir_bench.py -current_dir=$(dirname $0) -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +scripts_dir=$(dirname "$0")/.. +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Dace Settings -export DACE_compiler_cpu_executable="$(which icc)" -export CC=`which icc` -export CXX=`which icc` +DACE_compiler_cpu_executable="$(which icc)" +export DACE_compiler_cpu_executable +CC=$(which icc) +export CC +CXX=$(which icc) +export CXX export DACE_compiler_cpu_openmp_sections=0 export DACE_instrumentation_report_each_invocation=0 export DACE_compiler_cpu_args="-fPIC -O3 -march=native" +export PYTHONWARNINGS="ignore" # Generating MLIR using Torch-MLIR -python3 $gen_file > $output_dir/${input_name}_mhlo.mlir +python3 "$gen_file" >"$output_dir"/"${input_name}"_mhlo.mlir # Renaming `forward` to `main` (required by DCIR) -sed -i -e "s/forward/main/g" $output_dir/${input_name}_mhlo.mlir +sed -i -e "s/forward/main/g" "$output_dir"/"${input_name}"_mhlo.mlir # Converting MHLO to standard dialects -$scripts_dir/mhlo2std.sh $output_dir/${input_name}_mhlo.mlir \ - > $output_dir/${input_name}_std.mlir +"$scripts_dir"/mhlo2std.sh "$output_dir"/"${input_name}"_mhlo.mlir \ + >"$output_dir"/"${input_name}"_std.mlir # Optimizing with MLIR -mlir-opt --affine-loop-invariant-code-motion $output_dir/${input_name}_std.mlir | \ -mlir-opt --affine-scalrep | mlir-opt --lower-affine | \ -mlir-opt --cse --inline > $output_dir/${input_name}_opt.mlir +mlir-opt --affine-loop-invariant-code-motion "$output_dir"/"${input_name}"_std.mlir | + mlir-opt --affine-scalrep | mlir-opt --lower-affine | + mlir-opt --cse --inline >"$output_dir"/"${input_name}"_opt.mlir # Converting to DCIR -sdfg-opt --convert-to-sdfg $output_dir/${input_name}_opt.mlir \ - > $output_dir/${input_name}_sdfg.mlir +sdfg-opt --convert-to-sdfg "$output_dir"/"${input_name}"_opt.mlir \ + >"$output_dir"/"${input_name}"_sdfg.mlir # Translating to SDFG -sdfg-translate --mlir-to-sdfg $output_dir/${input_name}_sdfg.mlir \ - > $output_dir/$input_name.sdfg +sdfg-translate --mlir-to-sdfg "$output_dir"/"${input_name}"_sdfg.mlir \ + >"$output_dir"/"$input_name".sdfg # Optimizing data-centrically with DaCe -python3 $scripts_dir/opt_sdfg.py $output_dir/$input_name.sdfg \ - $output_dir/${input_name}_opt.sdfg 3 T +python3 "$scripts_dir"/opt_sdfg.py "$output_dir"/"$input_name".sdfg \ + "$output_dir"/"${input_name}"_opt.sdfg 3 T # Check output -if ! python3 $bench_file $output_dir/${input_name}_opt.sdfg 0 T; then +if ! python3 "$bench_file" "$output_dir"/"${input_name}"_opt.sdfg 0 T; then echo "Output incorrect!" exit 1 fi # Running the benchmark -OMP_NUM_THREADS=1 taskset -c 0 python3 $bench_file \ - $output_dir/${input_name}_opt.sdfg $repetitions F +OMP_NUM_THREADS=1 taskset -c 0 python3 "$bench_file" \ + "$output_dir"/"${input_name}"_opt.sdfg "$repetitions" F add_csv "DCIR" -for i in $(seq 1 $repetitions); do - time=$(python3 $scripts_dir/get_sdfg_times.py \ - $output_dir/${input_name}_opt.sdfg $((i-1)) F) +for i in $(seq 1 "$repetitions"); do + time=$(python3 "$scripts_dir"/get_sdfg_times.py \ + "$output_dir"/"${input_name}"_opt.sdfg $((i - 1)) F) add_csv "$time" done diff --git a/scripts/pytorch/pytorch.sh b/scripts/pytorch/pytorch.sh index d35ce68..5c81594 100755 --- a/scripts/pytorch/pytorch.sh +++ b/scripts/pytorch/pytorch.sh @@ -4,6 +4,11 @@ # intermediate results and the times in the CSV format # Usage: ./pytorch.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./pytorch.sh " @@ -16,55 +21,56 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } check_tool python3 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi +# Silence Python warnings +export PYTHONWARNINGS="ignore" + # Helpers -input_dir=$(dirname $input_file) -input_name=$(basename $input_dir) +input_dir=$(dirname "$input_file") +input_name=$(basename "$input_dir") input_file=$input_dir/pytorch.py -current_dir=$(dirname $0) -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Check output -if ! python3 $input_file 0 T; then +if ! python3 "$input_file" 0 T; then echo "Output incorrect!" exit 1 fi # Running the benchmark -runtimes=$(OMP_NUM_THREADS=1 taskset -c 0 python3 $input_file $repetitions F) +runtimes=$(OMP_NUM_THREADS=1 taskset -c 0 python3 "$input_file" "$repetitions" F) add_csv "PyTorch" for i in $runtimes; do add_csv "$i" done - diff --git a/scripts/pytorch/pytorch_jit.sh b/scripts/pytorch/pytorch_jit.sh new file mode 100755 index 0000000..5008ceb --- /dev/null +++ b/scripts/pytorch/pytorch_jit.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# Desc: Runs a pytorch benchmark using Pytorch with JIT. The output contains any +# intermediate results and the times in the CSV format +# Usage: ./pytorch_jit.sh + +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + +# Check args +if [ $# -ne 3 ]; then + echo "Usage: ./pytorch_jit.sh " + exit 1 +fi + +# Read args +input_file=$1 +output_dir=$2 +repetitions=$3 + +# Check tools +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 + fi +} + +check_tool python3 + +# Create output directory +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" +fi + +# Silence Python warnings +export PYTHONWARNINGS="ignore" + +# Helpers +input_dir=$(dirname "$input_file") +input_name=$(basename "$input_dir") +input_file=$input_dir/pytorch_jit.py +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" + +# Adds a value to the timings file, jumps to the next row after a write +csv_line=1 +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" + done + + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" + fi + + sed -i "${csv_line}s/$/$1/" "$timings_file" + csv_line=$((csv_line + 1)) +} + +# Check output +if ! python3 "$input_file" 0 T; then + echo "Output incorrect!" + exit 1 +fi + +# Running the benchmark +runtimes=$(OMP_NUM_THREADS=1 taskset -c 0 python3 "$input_file" "$repetitions" F) + +add_csv "PyTorch (JIT)" + +for i in $runtimes; do + add_csv "$i" +done diff --git a/scripts/pytorch/run_all.sh b/scripts/pytorch/run_all.sh index afb338f..37b694f 100755 --- a/scripts/pytorch/run_all.sh +++ b/scripts/pytorch/run_all.sh @@ -1,10 +1,15 @@ #!/bin/bash -# Desc: Runs all pytorch benchmarks using PyTorch, Torch-MLIR and DCIR. The -# output contains any intermediate results and the times in the CSV format as +# Desc: Runs all pytorch benchmarks using PyTorch, Torch-MLIR and DCIR. The +# output contains any intermediate results and the times in the CSV format as # well as all the plots. # Usage: ./run_all.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 2 ]; then echo "Usage: ./run_all.sh " @@ -16,53 +21,59 @@ output_dir=$1 repetitions=$2 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi +# Silence Python warnings +export PYTHONWARNINGS="ignore" + # Helpers -runners_dir=$(dirname $0) -scripts_dir=$(dirname $0)/.. -benchmarks_dir=$(dirname $0)/../../benchmarks/pytorch +runners_dir=$(dirname "$0") +scripts_dir=$(dirname "$0")/.. +benchmarks_dir=$(dirname "$0")/../../benchmarks/pytorch # Run benchmarks -benchmarks=$(find $benchmarks_dir/* -name 'pytorch.py') +benchmarks=$(find "$benchmarks_dir"/* -name 'pytorch.py') total=$(echo "$benchmarks" | wc -l) -runners="$runners_dir/pytorch.sh $runners_dir/torch-mlir.sh $runners_dir/dcir.sh" +runners="$runners_dir/pytorch.sh $runners_dir/pytorch_jit.sh \ + $runners_dir/torch-mlir.sh $runners_dir/dcir.sh" for runner in $runners; do count=0 echo "Running with: $runner" for benchmark in $benchmarks; do - bname="$(basename $benchmark .c)" - count=$((count+1)) - diff=$(($total - $count)) - percent=$(($count * 100 / $total)) - - prog='' - for i in $(seq 1 $count); do - prog="$prog#" - done - - for i in $(seq 1 $diff); do - prog="$prog-" - done - - echo -ne "\033[2K\r" - echo -ne "$prog ($percent%) ($bname) " - - $runner $benchmark $output_dir $repetitions + bench_dir=$(dirname "$benchmark") + bench_name=$(basename "$bench_dir") + + count=$((count + 1)) + diff=$((total - count)) + percent=$((count * 100 / total)) + + prog='' + for _ in $(seq 1 $count); do + prog="$prog#" + done + + for _ in $(seq 1 $diff); do + prog="$prog-" + done + + echo -ne "\033[2K\r" + echo -ne "$prog ($percent%) ($bench_name) " + + $runner "$benchmark" "$output_dir" "$repetitions" done echo "" done for benchmark in $benchmarks; do - bench_dir=$(dirname $benchmark) - bench_name=$(basename $bench_dir) - mv "$output_dir/${bench_name}_timings.csv" "$output_dir/${bench_name}.csv" - python3 $scripts_dir/single_plot.py "$output_dir/${bench_name}.csv" \ - $output_dir/$bench_name.pdf + bench_dir=$(dirname "$benchmark") + bench_name=$(basename "$bench_dir") + mv "$output_dir/${bench_name}_timings.csv" "$output_dir/${bench_name}.csv" + python3 "$scripts_dir"/single_plot.py "$output_dir/${bench_name}.csv" \ + "$output_dir"/"$bench_name".pdf done diff --git a/scripts/pytorch/torch-mlir.sh b/scripts/pytorch/torch-mlir.sh index baf7ec0..fc59c79 100755 --- a/scripts/pytorch/torch-mlir.sh +++ b/scripts/pytorch/torch-mlir.sh @@ -4,6 +4,11 @@ # intermediate results and the times in the CSV format # Usage: ./torch-mlir.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./torch-mlir.sh " @@ -16,51 +21,53 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } check_tool python3 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi +# Silence Python warnings +export PYTHONWARNINGS="ignore" + # Helpers -input_dir=$(dirname $input_file) -input_name=$(basename $input_dir) +input_dir=$(dirname "$input_file") +input_name=$(basename "$input_dir") input_file=$input_dir/torch-mlir.py -current_dir=$(dirname $0) -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Check output -if ! python3 $input_file 0 T; then +if ! python3 "$input_file" 0 T; then echo "Output incorrect!" exit 1 fi # Running the benchmark -runtimes=$(OMP_NUM_THREADS=1 taskset -c 0 python3 $input_file $repetitions F) +runtimes=$(OMP_NUM_THREADS=1 taskset -c 0 python3 "$input_file" "$repetitions" F) add_csv "Torch-MLIR" diff --git a/scripts/run_all.sh b/scripts/run_all.sh index de1bd50..4afcc7a 100755 --- a/scripts/run_all.sh +++ b/scripts/run_all.sh @@ -1,9 +1,14 @@ #!/bin/bash -# Desc: Runs all the benchmarks. The output contains any intermediate results +# Desc: Runs all the benchmarks. The output contains any intermediate results # and the times in the CSV format as well as all the plots. # Usage: ./run_all.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 2 ]; then echo "Usage: ./run_all.sh " @@ -15,14 +20,17 @@ output_dir=$1 repetitions=$2 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi +# Silence Python warnings +export PYTHONWARNINGS="ignore" + # Helpers -scripts_dir=$(dirname $0) +scripts_dir=$(dirname "$0") # Run benchmarks -./$scripts_dir/Polybench/run_all.sh "$output_dir" "$repetitions" -./$scripts_dir/pytorch/run_all.sh "$output_dir" "$repetitions" -./$scripts_dir/snippets/run_all.sh "$output_dir" "$repetitions" +./"$scripts_dir"/Polybench/run_all.sh "$output_dir" "$repetitions" +./"$scripts_dir"/pytorch/run_all.sh "$output_dir" "$repetitions" +./"$scripts_dir"/snippets/run_all.sh "$output_dir" "$repetitions" diff --git a/scripts/single_plot.py b/scripts/single_plot.py index 2c7adb2..17747ee 100755 --- a/scripts/single_plot.py +++ b/scripts/single_plot.py @@ -38,8 +38,7 @@ def add_median_labels(ax, precision='.2f'): ha='center', va='bottom', fontweight='bold', - color='black', - fontfamily='Arial') + color='black') dt = pd.read_csv(input_file) diff --git a/scripts/snippets/clang.sh b/scripts/snippets/clang.sh index 6e7cb8e..b0fca29 100755 --- a/scripts/snippets/clang.sh +++ b/scripts/snippets/clang.sh @@ -4,6 +4,11 @@ # intermediate results and the times in the CSV format # Usage: ./clang.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./clang.sh " @@ -16,42 +21,41 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } check_tool clang check_tool gcc -check_tool python3 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Helpers -input_name=$(basename ${input_file%.*}) -input_dir=$(dirname $input_file) +input_name=$(basename "${input_file%.*}") +input_dir=$(dirname "$input_file") input_chrono="$input_dir/$input_name-chrono.c" -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Flags for the benchmark @@ -59,15 +63,19 @@ flags="-fPIC -march=native" opt_lvl_cc=3 # Optimization level for the control-centric optimizations # Compile -clang -O$opt_lvl_cc $flags -o $output_dir/${input_name}_clang.out $input_chrono -lm +# shellcheck disable=SC2086 +clang -O$opt_lvl_cc $flags -o "$output_dir"/"${input_name}"_clang.out "$input_chrono" -lm &>/dev/null # Check output -gcc -O0 $flags -o $output_dir/${input_name}_gcc_ref.out $input_chrono -lm +# shellcheck disable=SC2086 +gcc -O0 $flags -o "$output_dir"/"${input_name}"_gcc_ref.out "$input_chrono" -lm &>/dev/null -$output_dir/${input_name}_clang.out &> /dev/null +set +e +"$output_dir"/"${input_name}"_clang.out &>/dev/null actual=$? -$output_dir/${input_name}_gcc_ref.out &> /dev/null +"$output_dir"/"${input_name}"_gcc_ref.out &>/dev/null reference=$? +set -e if [ "$actual" -ne "$reference" ]; then echo "Output incorrect!" @@ -77,7 +85,9 @@ fi # Running the benchmark add_csv "Clang" -for i in $(seq 1 $repetitions); do - time=$(OMP_NUM_THREADS=1 taskset -c 0 ./$output_dir/${input_name}_clang.out) +for _ in $(seq 1 "$repetitions"); do + set +e + time=$(OMP_NUM_THREADS=1 taskset -c 0 ./"$output_dir"/"${input_name}"_clang.out) + set -e add_csv "$time" done diff --git a/scripts/snippets/dace.sh b/scripts/snippets/dace.sh index 667dfe5..296bb94 100755 --- a/scripts/snippets/dace.sh +++ b/scripts/snippets/dace.sh @@ -4,6 +4,11 @@ # intermediate results and the times in the CSV format # Usage: ./dace.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./dace.sh " @@ -16,51 +21,50 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } check_tool clang +check_tool clang++ check_tool python3 -check_tool icc # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Clear .dacecache rm -rf .dacecache # Helpers -input_name=$(basename ${input_file%.*}) -input_dir=$(dirname $input_file) -input_chrono="$input_dir/$input_name-chrono.c" -input_dace="$input_dir/$input_name.sdfg" -current_dir=$(dirname $0) -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +input_name=$(basename "${input_file%.*}") +input_dir=$(dirname "$input_file") +current_dir=$(dirname "$0") +scripts_dir=$(dirname "$0")/.. +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Flags for the benchmark -flags="-fPIC -march=native" +opt_lvl_cc=3 # Optimization level for the control-centric optimizations opt_lvl_dc=3 # Optimization level for the data-centric optimizations # Lower optimization level for specific benchmarks @@ -73,26 +77,29 @@ if [[ "$input_name" == "demo" ]]; then fi # Dace Settings -export DACE_compiler_cpu_executable="$(which clang++)" -export CC=`which clang` -export CXX=`which clang++` +DACE_compiler_cpu_executable="$(which clang++)" +export DACE_compiler_cpu_executable +CC=$(which clang) +export CC +CXX=$(which clang++) +export CXX export DACE_compiler_cpu_openmp_sections=0 export DACE_instrumentation_report_each_invocation=0 export DACE_compiler_cpu_args="-fPIC -O$opt_lvl_cc -march=native" +export PYTHONWARNINGS="ignore" # Optimizing data-centrically with DaCe -python3 $scripts_dir/opt_sdfg.py $input_dir/${input_name}_c2dace.sdfg \ - $output_dir/${input_name}_c2dace_opt.sdfg $opt_lvl_dc T +python3 "$scripts_dir"/opt_sdfg.py "$input_dir"/"${input_name}"_c2dace.sdfg \ + "$output_dir"/"${input_name}"_c2dace_opt.sdfg $opt_lvl_dc T # Running the benchmark -OMP_NUM_THREADS=1 taskset -c 0 python3 $current_dir/bench_dace.py \ - $output_dir/${input_name}_c2dace_opt.sdfg $repetitions +OMP_NUM_THREADS=1 taskset -c 0 python3 "$current_dir"/bench_dace.py \ + "$output_dir"/"${input_name}"_c2dace_opt.sdfg "$repetitions" add_csv "DaCe" -for i in $(seq 1 $repetitions); do - time=$(python3 $scripts_dir/get_sdfg_times.py \ - $output_dir/${input_name}_c2dace_opt.sdfg $((i-1)) F) +for i in $(seq 1 "$repetitions"); do + time=$(python3 "$scripts_dir"/get_sdfg_times.py \ + "$output_dir"/"${input_name}"_c2dace_opt.sdfg $((i - 1)) F) add_csv "$time" done - diff --git a/scripts/snippets/dcir.sh b/scripts/snippets/dcir.sh index b7e36c6..ed9956e 100755 --- a/scripts/snippets/dcir.sh +++ b/scripts/snippets/dcir.sh @@ -1,9 +1,14 @@ #!/bin/bash -# Desc: Runs a Polybench benchmark using DCIR. The output contains any +# Desc: Runs a snippet benchmark using DCIR. The output contains any # intermediate results and the times in the CSV format # Usage: ./dcir.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./dcir.sh " @@ -16,51 +21,52 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } check_tool clang +check_tool clang++ check_tool clang-13 check_tool cgeist check_tool mlir-opt check_tool sdfg-opt check_tool sdfg-translate check_tool python3 -check_tool icc # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Clear .dacecache rm -rf .dacecache # Helpers -input_name=$(basename ${input_file%.*}) -input_dir=$(dirname $input_file) +input_name=$(basename "${input_file%.*}") +input_dir=$(dirname "$input_file") input_chrono="$input_dir/$input_name-chrono.c" -current_dir=$(dirname $0) -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +current_dir=$(dirname "$0") +scripts_dir=$(dirname "$0")/.. +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Flags for the benchmark @@ -69,41 +75,49 @@ opt_lvl_cc=3 # Optimization level for the control-centric optimizations opt_lvl_dc=3 # Optimization level for the data-centric optimizations # Dace Settings -export DACE_compiler_cpu_executable="$(which clang++)" -export CC=`which clang` -export CXX=`which clang++` +DACE_compiler_cpu_executable="$(which clang++)" +export DACE_compiler_cpu_executable +CC=$(which clang) +export CC +CXX=$(which clang++) +export CXX export DACE_compiler_cpu_openmp_sections=0 export DACE_instrumentation_report_each_invocation=0 export DACE_compiler_cpu_args="-fPIC -O$opt_lvl_cc -march=native" +export PYTHONWARNINGS="ignore" # Generating MLIR from C using Polygeist -cgeist -resource-dir=$(clang-13 -print-resource-dir) -S --memref-fullrank \ - -O$opt_lvl_cc --raise-scf-to-affine $flags $input_file \ - > $output_dir/${input_name}_cgeist.mlir +# shellcheck disable=SC2086 +cgeist -resource-dir="$(clang-13 -print-resource-dir)" -S --memref-fullrank \ + -O$opt_lvl_cc --raise-scf-to-affine $flags "$input_file" \ + 1>"$output_dir"/"${input_name}"_cgeist.mlir 2>/dev/null # Optimizing with MLIR -mlir-opt --affine-loop-invariant-code-motion $output_dir/${input_name}_cgeist.mlir | \ -mlir-opt --affine-scalrep | mlir-opt --lower-affine | \ -mlir-opt --cse --inline > $output_dir/${input_name}_opt.mlir +mlir-opt --affine-loop-invariant-code-motion "$output_dir"/"${input_name}"_cgeist.mlir | + mlir-opt --affine-scalrep | mlir-opt --lower-affine | + mlir-opt --cse --inline >"$output_dir"/"${input_name}"_opt.mlir # Converting to DCIR -sdfg-opt --convert-to-sdfg $output_dir/${input_name}_opt.mlir \ - > $output_dir/${input_name}_sdfg.mlir +sdfg-opt --convert-to-sdfg "$output_dir"/"${input_name}"_opt.mlir \ + >"$output_dir"/"${input_name}"_sdfg.mlir # Translating to SDFG -sdfg-translate --mlir-to-sdfg $output_dir/${input_name}_sdfg.mlir \ - > $output_dir/$input_name.sdfg +sdfg-translate --mlir-to-sdfg "$output_dir"/"${input_name}"_sdfg.mlir \ + >"$output_dir"/"$input_name".sdfg # Optimizing data-centrically with DaCe -python3 $scripts_dir/opt_sdfg.py $output_dir/$input_name.sdfg \ - $output_dir/${input_name}_opt.sdfg $opt_lvl_dc T +python3 "$scripts_dir"/opt_sdfg.py "$output_dir"/"$input_name".sdfg \ + "$output_dir"/"${input_name}"_opt.sdfg $opt_lvl_dc T # Check output -actual=$(python3 $current_dir/bench_dcir.py $output_dir/${input_name}_opt.sdfg 1 T) +actual=$(python3 "$current_dir"/bench_dcir.py "$output_dir"/"${input_name}"_opt.sdfg 1 T) -clang -O0 $flags -o $output_dir/${input_name}_clang_ref.out $input_chrono -lm -$output_dir/${input_name}_clang_ref.out &> /dev/null +# shellcheck disable=SC2086 +clang -O0 $flags -o "$output_dir"/"${input_name}"_clang_ref.out "$input_chrono" -lm &>/dev/null +set +e +"$output_dir"/"${input_name}"_clang_ref.out &>/dev/null reference=$? +set -e if [ "$actual" -ne "$reference" ]; then echo "Output incorrect!" @@ -111,13 +125,13 @@ if [ "$actual" -ne "$reference" ]; then fi # Running the benchmark -OMP_NUM_THREADS=1 taskset -c 0 python3 $current_dir/bench_dcir.py \ - $output_dir/${input_name}_opt.sdfg $repetitions F +OMP_NUM_THREADS=1 taskset -c 0 python3 "$current_dir"/bench_dcir.py \ + "$output_dir"/"${input_name}"_opt.sdfg "$repetitions" F add_csv "DCIR" -for i in $(seq 1 $repetitions); do - time=$(python3 $scripts_dir/get_sdfg_times.py \ - $output_dir/${input_name}_opt.sdfg $((i-1)) F) +for i in $(seq 1 "$repetitions"); do + time=$(python3 "$scripts_dir"/get_sdfg_times.py \ + "$output_dir"/"${input_name}"_opt.sdfg $((i - 1)) F) add_csv "$time" done diff --git a/scripts/snippets/gcc.sh b/scripts/snippets/gcc.sh index fd12872..0816a29 100755 --- a/scripts/snippets/gcc.sh +++ b/scripts/snippets/gcc.sh @@ -4,6 +4,11 @@ # intermediate results and the times in the CSV format # Usage: ./gcc.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./gcc.sh " @@ -16,42 +21,41 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } check_tool gcc check_tool clang -check_tool python3 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Helpers -input_name=$(basename ${input_file%.*}) -input_dir=$(dirname $input_file) +input_name=$(basename "${input_file%.*}") +input_dir=$(dirname "$input_file") input_chrono="$input_dir/$input_name-chrono.c" -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Flags for the benchmark @@ -59,15 +63,19 @@ flags="-fPIC -march=native" opt_lvl_cc=3 # Optimization level for the control-centric optimizations # Compile -gcc -O$opt_lvl_cc $flags -o $output_dir/${input_name}_gcc.out $input_chrono -lm +# shellcheck disable=SC2086 +gcc -O$opt_lvl_cc $flags -o "$output_dir"/"${input_name}"_gcc.out "$input_chrono" -lm &>/dev/null # Check output -clang -O0 $flags -o $output_dir/${input_name}_clang_ref.out $input_chrono -lm +# shellcheck disable=SC2086 +clang -O0 $flags -o "$output_dir"/"${input_name}"_clang_ref.out "$input_chrono" -lm &>/dev/null -$output_dir/${input_name}_gcc.out &> /dev/null +set +e +"$output_dir"/"${input_name}"_gcc.out &>/dev/null actual=$? -$output_dir/${input_name}_clang_ref.out &> /dev/null +"$output_dir"/"${input_name}"_clang_ref.out &>/dev/null reference=$? +set -e if [ "$actual" -ne "$reference" ]; then echo "Output incorrect!" @@ -77,7 +85,9 @@ fi # Running the benchmark add_csv "GCC" -for i in $(seq 1 $repetitions); do - time=$(OMP_NUM_THREADS=1 taskset -c 0 ./$output_dir/${input_name}_gcc.out) +for _ in $(seq 1 "$repetitions"); do + set +e + time=$(OMP_NUM_THREADS=1 taskset -c 0 ./"$output_dir"/"${input_name}"_gcc.out) + set -e add_csv "$time" done diff --git a/scripts/snippets/mlir.sh b/scripts/snippets/mlir.sh index 72a2b69..0dd7234 100755 --- a/scripts/snippets/mlir.sh +++ b/scripts/snippets/mlir.sh @@ -1,9 +1,14 @@ #!/bin/bash -# Desc: Runs a snippet benchmark using Polygeist + MLIR. The output contains +# Desc: Runs a snippet benchmark using Polygeist + MLIR. The output contains # any intermediate results and the times in the CSV format # Usage: ./mlir.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 3 ]; then echo "Usage: ./mlir.sh " @@ -16,10 +21,10 @@ output_dir=$2 repetitions=$3 # Check tools -check_tool(){ - if ! command -v $1 &> /dev/null; then - echo "$1 could not be found" - exit 1 +check_tool() { + if ! command -v "$1" &>/dev/null; then + echo "$1 could not be found" + exit 1 fi } @@ -29,33 +34,32 @@ check_tool clang-13 check_tool cgeist check_tool mlir-opt check_tool mlir-translate -check_tool python3 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi # Helpers -input_name=$(basename ${input_file%.*}) -input_dir=$(dirname $input_file) +input_name=$(basename "${input_file%.*}") +input_dir=$(dirname "$input_file") input_chrono="$input_dir/$input_name-chrono.c" -scripts_dir=$(dirname $0)/.. -timings_file=$output_dir/${input_name}_timings.csv; touch $timings_file +timings_file=$output_dir/${input_name}_timings.csv +touch "$timings_file" # Adds a value to the timings file, jumps to the next row after a write csv_line=1 -add_csv(){ - while [[ $(grep -c ^ $timings_file) < $csv_line ]]; do - echo '' >> $timings_file +add_csv() { + while [[ $(grep -c ^ "$timings_file") -lt $csv_line ]]; do + echo '' >>"$timings_file" done - if [ ! -z "$(sed "${csv_line}q;d" $timings_file)" ]; then - sed -i "${csv_line}s/$/,/" $timings_file + if [ -n "$(sed "${csv_line}q;d" "$timings_file")" ]; then + sed -i "${csv_line}s/$/,/" "$timings_file" fi sed -i "${csv_line}s/$/$1/" "$timings_file" - csv_line=$((csv_line+1)) + csv_line=$((csv_line + 1)) } # Flags for the benchmark @@ -63,49 +67,55 @@ flags="-fPIC -march=native" opt_lvl_cc=3 # Optimization level for the control-centric optimizations # Compiling with MLIR -compile_with_mlir(){ +compile_with_mlir() { additional_flags=$1 output_name=$2 # Generating MLIR from C using Polygeist - cgeist -resource-dir=$(clang-13 -print-resource-dir) \ + # shellcheck disable=SC2086 + cgeist -resource-dir="$(clang-13 -print-resource-dir)" \ -S --memref-fullrank -O$opt_lvl_cc --raise-scf-to-affine $flags \ - $additional_flags $input_chrono > $output_dir/${output_name}_cgeist.mlir + $additional_flags "$input_chrono" 1>"$output_dir"/"${output_name}"_cgeist.mlir \ + 2>/dev/null # Optimizing with MLIR mlir-opt --affine-loop-invariant-code-motion \ - $output_dir/${output_name}_cgeist.mlir | \ - mlir-opt --affine-scalrep | mlir-opt --lower-affine | \ - mlir-opt --cse --inline > $output_dir/${output_name}_opt.mlir + "$output_dir"/"${output_name}"_cgeist.mlir | + mlir-opt --affine-scalrep | mlir-opt --lower-affine | + mlir-opt --cse --inline >"$output_dir"/"${output_name}"_opt.mlir # Lower to LLVM dialect mlir-opt --convert-scf-to-cf --convert-func-to-llvm --convert-cf-to-llvm \ --convert-math-to-llvm --lower-host-to-llvm --reconcile-unrealized-casts \ - $output_dir/${output_name}_opt.mlir > $output_dir/${output_name}_ll.mlir + "$output_dir"/"${output_name}"_opt.mlir >"$output_dir"/"${output_name}"_ll.mlir # Translate - mlir-translate --mlir-to-llvmir $output_dir/${output_name}_ll.mlir \ - > $output_dir/${output_name}.ll + mlir-translate --mlir-to-llvmir "$output_dir"/"${output_name}"_ll.mlir \ + >"$output_dir"/"${output_name}".ll # Compile - llc -O$opt_lvl_cc --relocation-model=pic $output_dir/${output_name}.ll \ - -o $output_dir/${output_name}.s + llc -O$opt_lvl_cc --relocation-model=pic "$output_dir"/"${output_name}".ll \ + -o "$output_dir"/"${output_name}".s # Assemble - clang -O$opt_lvl_cc $flags $additional_flags $output_dir/${output_name}.s \ - -o $output_dir/${output_name}.out -lm + # shellcheck disable=SC2086 + clang -O$opt_lvl_cc $flags $additional_flags "$output_dir"/"${output_name}".s \ + -o "$output_dir"/"${output_name}".out -lm } # Compile compile_with_mlir "" "${input_name}_mlir" # Check output -clang -O0 $flags -o $output_dir/${input_name}_clang_ref.out $input_file -lm +# shellcheck disable=SC2086 +clang -O0 $flags -o "$output_dir"/"${input_name}"_clang_ref.out "$input_file" -lm &>/dev/null -$output_dir/${input_name}_mlir.out &> /dev/null +set +e +"$output_dir"/"${input_name}"_mlir.out &>/dev/null actual=$? -$output_dir/${input_name}_clang_ref.out &> /dev/null +"$output_dir"/"${input_name}"_clang_ref.out &>/dev/null reference=$? +set -e if [ "$actual" -ne "$reference" ]; then echo "Output incorrect!" @@ -115,7 +125,9 @@ fi # Running the benchmark add_csv "Polygeist + MLIR" -for i in $(seq 1 $repetitions); do - time=$(OMP_NUM_THREADS=1 taskset -c 0 ./$output_dir/${input_name}_mlir.out) +for _ in $(seq 1 "$repetitions"); do + set +e + time=$(OMP_NUM_THREADS=1 taskset -c 0 ./"$output_dir"/"${input_name}"_mlir.out) + set -e add_csv "$time" done diff --git a/scripts/snippets/run_all.sh b/scripts/snippets/run_all.sh index 0a4a6ab..23e4731 100755 --- a/scripts/snippets/run_all.sh +++ b/scripts/snippets/run_all.sh @@ -1,10 +1,15 @@ #!/bin/bash -# Desc: Runs all snippet benchmarks using GCC, Clang, Polygeist + MLIR, DCIR -# and DaCe. The output contains any intermediate results and the times in the +# Desc: Runs all snippet benchmarks using GCC, Clang, Polygeist + MLIR, DCIR +# and DaCe. The output contains any intermediate results and the times in the # CSV format as well as all the plots. # Usage: ./run_all.sh +# Be safe +set -e # Fail script when subcommand fails +set -u # Disallow using undefined variables +set -o pipefail # Prevent errors from being masked + # Check args if [ $# -ne 2 ]; then echo "Usage: ./run_all.sh " @@ -16,17 +21,20 @@ output_dir=$1 repetitions=$2 # Create output directory -if [ ! -d $output_dir ]; then - mkdir -p $output_dir; +if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" fi +# Silence Python warnings +export PYTHONWARNINGS="ignore" + # Helpers -runners_dir=$(dirname $0) -scripts_dir=$(dirname $0)/.. -benchmarks_dir=$(dirname $0)/../../benchmarks/snippets +runners_dir=$(dirname "$0") +scripts_dir=$(dirname "$0")/.. +benchmarks_dir=$(dirname "$0")/../../benchmarks/snippets # Run benchmarks -benchmarks=$(find $benchmarks_dir/* -name '*.c' -not -name '*-chrono.c') +benchmarks=$(find "$benchmarks_dir"/* -name '*.c' -not -name '*-chrono.c') total=$(echo "$benchmarks" | wc -l) runners="$runners_dir/gcc.sh $runners_dir/clang.sh $runners_dir/dace.sh \ @@ -37,49 +45,49 @@ for runner in $runners; do echo "Running with: $runner" for benchmark in $benchmarks; do - bname="$(basename $benchmark .c)" - count=$((count+1)) - diff=$(($total - $count)) - percent=$(($count * 100 / $total)) - - prog='' - for i in $(seq 1 $count); do - prog="$prog#" - done - - for i in $(seq 1 $diff); do - prog="$prog-" - done - - echo -ne "\033[2K\r" - echo -ne "$prog ($percent%) ($bname) " - - $runner $benchmark $output_dir $repetitions + bname="$(basename "$benchmark" .c)" + count=$((count + 1)) + diff=$((total - count)) + percent=$((count * 100 / total)) + + prog='' + for _ in $(seq 1 $count); do + prog="$prog#" + done + + for _ in $(seq 1 $diff); do + prog="$prog-" + done + + echo -ne "\033[2K\r" + echo -ne "$prog ($percent%) ($bname) " + + $runner "$benchmark" "$output_dir" "$repetitions" done echo "" done for benchmark in $benchmarks; do - bname="$(basename $benchmark .c)" + bname="$(basename "$benchmark" .c)" - if [[ "$bname" == "demo" ]]; then - fig_num=2 - fi + if [[ "$bname" == "demo" ]]; then + fig_num=2 + fi - if [[ "$bname" == "mem_line" ]]; then - fig_num=8 - fi + if [[ "$bname" == "mem_line" ]]; then + fig_num=8 + fi - if [[ "$bname" == "congrad_multi_field" ]]; then - fig_num=9 - fi + if [[ "$bname" == "congrad_multi_field" ]]; then + fig_num=9 + fi - if [[ "$bname" == "memory" ]]; then - fig_num=10 - fi + if [[ "$bname" == "memory" ]]; then + fig_num=10 + fi - mv "$output_dir/${bname}_timings.csv" "$output_dir/fig${fig_num}.csv" - python3 $scripts_dir/single_plot.py "$output_dir/fig${fig_num}.csv" \ - $output_dir/fig$fig_num.pdf + mv "$output_dir/${bname}_timings.csv" "$output_dir/fig${fig_num}.csv" + python3 "$scripts_dir"/single_plot.py "$output_dir/fig${fig_num}.csv" \ + "$output_dir"/fig"$fig_num".pdf done