mirror of
https://github.com/ggml-org/whisper.cpp.git
synced 2026-07-23 11:10:57 -05:00
* ci : add ccache clear action * ci : split self-hosted GPU jobs into build-self-hosted.yml Extract self-hosted runner jobs from build.yml into a dedicated build-self-hosted.yml following the llama.cpp pattern: - gpu-cuda (NVIDIA Linux) - gpu-vulkan-nvidia-cm (NVIDIA Linux) - gpu-vulkan-nvidia-cm2 (NVIDIA Linux + COOPMAT2) - gpu-metal (macOS ARM64) - gpu-vulkan (macOS ARM64) GitHub-hosted CPU jobs remain in build.yml. Assisted-by: llama.cpp:local pi * ci : split release jobs into release.yml Extract release-related jobs from build.yml into a dedicated release.yml following the llama.cpp pattern: - determine-tag - windows (Win32/x64, SDL2) - windows-blas (Win32/x64, OpenBLAS) - windows-cublas (x64, CUDA 11.8/12.4) - ios-xcode-build - bindings-java (depends on windows) - release (artifact aggregation + GitHub release) CoreML job stays in build.yml with its own local tag calculation. Assisted-by: llama.cpp:local pi * ci : remove bindings-java job from release.yml Assisted-by: llama.cpp:local pi * cont : add manual trigger for build.yml * cont : remove obsolete ifs * ci : extract sanitizer job to bild-sanitize.yml * ci : extract linux jobs into build-linux.yml * ci : extract macos jobs to build-macos.yml * ci : extract gcc jobs to build-gcc.yml * ci : extract clang jobs to build-clang.yml * ci : extract sycl jobs to build-sycl.yml * ci : extract windows jobs to build-windows.yml * ci : extract emscripten job to build-wasm.yml * ci : extract android jobs into build-android.yml * ci : extract quantize job to quantize.yml * ci : extract coreml job into coreml.yml * ci : extract vad job to vad.yml * ci : extract cpu jobs to build-cpu.yml * ci : make naming of yml files consistent * ci : add --fail to curl download and propagate This commit adds the --fail option to the model download scripts so that if the model download returns a server error this is picked up. This is then detected in run.sh and a error message is displayed and the script stops and returns an error. The motivation for this is that currently it is possible for the model download to fail but this script proceeds and instead of a model file the contents will be an html page probably with the error. This will then cause the model to not be able to load due to a missing magic number. I'm not sure we can do much about the downloading failing, perhaps a retry but at least this will give a clearer error message. Refs: https://github.com/danbev/whisper.cpp/actions/runs/26866349389/job/79230794512 * ci : enable command traces to see download command in use * ci : add retry functionality to download model script This commit adds curl retry options to the model download script. The motivation is that currently when CI jobs run huggingface rate limit the requests and return: ```console curl: (22) The requested URL returned error: 429 ``` This is an attempt to work around this and if it does not work then we can an authorization token. * ci : extract freebsd job to build-freebsd.yml This job has been commented out as it has been flaky in the past. I'll monitor this and if it continues to be unreliable we can disable it in the github actions GUI instead of commenting it out like we did before. * ci : add ccache to jobs (non-docker builds) The ccache will only be saved on pushed to master. * ci : bump ccache-action version to v1.2.21 The motivation for this is that the save parameter does not seem to work with the current version. * ci : add ccache to docker jobs in build-linux.yml * ci : add debug statements to linux docker build * ci : set CCACHE_DIR for build-linux.yml * ci : add ccache to the remaining docker jobs * ci : remove build-linux.yml This commit remove build-linux.yml as the same jobs are also run by build-gcc.yml, with the exception that build-gcc.yml also run ctest). So keeping build-gcc.yml and removing the redundant build-linux.yml. * ci : add linux build artifacts to release * ci : revert to hendrikmuhs/ccache-action for win job This is currently causing the following failure: ```console sccache C:\PROGRA~1\NVIDIA~1\CUDA\v\bin\nvcc.exe -forward-unknown-to-host-compiler -DGGML_BACKEND_BUILD -DGGML_BACKEND_SHARED -DGGML_CUDA_PEER_MAX_BATCH_SIZE=128 -DGGML_SCHED_MAX_COPIES=4 -DGGML_SHARED -D_CRT_SECURE_NO_WARNINGS -D_XOPEN_SOURCE=600 -Dggml_cuda_EXPORTS -DCMAKE_INTDIR=\"Release\" -ID:\a\whisper.cpp\whisper.cpp\ggml\src\ggml-cuda\.. -ID:\a\whisper.cpp\whisper.cpp\ggml\src\..\include -isystem "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v\include" -Xcompiler="-MD -O2 -Ob2" -DNDEBUG -std=c++17 -arch=native -use_fast_math -extended-lambda -Xcompiler /Zc:preprocessor -MD -MT ggml\src\ggml-cuda\CMakeFiles\ggml-cuda.dir\Release\allreduce.cu.obj -MF ggml\src\ggml-cuda\CMakeFiles\ggml-cuda.dir\Release\allreduce.cu.obj.d -x cu -c D:\a\whisper.cpp\whisper.cpp\ggml\src\ggml-cuda\allreduce.cu -o ggml\src\ggml-cuda\CMakeFiles\ggml-cuda.dir\Release\allreduce.cu.obj -Xcompiler=-Fdggml\src\ggml-cuda\CMakeFiles\ggml-cuda.dir\Release\,-FS sccache: encountered fatal error sccache: error: Could not parse shell line sccache: caused by: Could not parse shell line ``` Refs: https://github.com/danbev/whisper.cpp/actions/runs/26883673904/job/79290017353 * ci : make static linux artifacts * ci : make linux release artifact names consistent This commit removes the tag form the linux release artifacts to be consistent with the existing artifacts. If we want to include the tag then we can do that in a follow-up PR. * ci : fix linux zip files to have a directory * ci : add HF_TOKEN secret for HF download authorization This is to avoid the HR rate limiting when downloading model. --------- Co-authored-by: Daniel Bevenius <daniel.bevenius@gmail.com>
391 lines
11 KiB
Bash
391 lines
11 KiB
Bash
#!/bin/bash
|
|
#
|
|
# sample usage:
|
|
#
|
|
# mkdir tmp
|
|
#
|
|
# # CPU-only build
|
|
# bash ./ci/run.sh ./tmp/results ./tmp/mnt
|
|
#
|
|
# # with CUDA support
|
|
# GG_BUILD_CUDA=1 bash ./ci/run.sh ./tmp/results ./tmp/mnt
|
|
#
|
|
# # with SYCL support
|
|
# GG_BUILD_SYCL=1 bash ./ci/run.sh ./tmp/results ./tmp/mnt
|
|
|
|
if [ -z "$2" ]; then
|
|
echo "usage: $0 <output-dir> <mnt-dir>"
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p "$1"
|
|
mkdir -p "$2"
|
|
|
|
OUT=$(realpath "$1")
|
|
MNT=$(realpath "$2")
|
|
|
|
rm -vf $OUT/*.log
|
|
rm -vf $OUT/*.exit
|
|
rm -vf $OUT/*.md
|
|
|
|
sd=`dirname $0`
|
|
cd $sd/../
|
|
SRC=`pwd`
|
|
|
|
ALL_MODELS=( "tiny.en" "tiny" "base.en" "base" "small.en" "small" "medium.en" "medium" "large-v1" "large-v2" "large-v3" "large-v3-turbo" )
|
|
BENCH_N_THREADS=4
|
|
BENCH_ENCODER_ONLY=0
|
|
BENCH_FLASH_ATTN=0
|
|
|
|
# check for user-specified models first. if not specified, use fast models
|
|
if [ ! -z ${GG_BUILD_TEST_MODELS} ]; then
|
|
IFS=',' read -r -a MODELS <<< "${GG_BUILD_TEST_MODELS}"
|
|
else
|
|
if [ ! -z ${GG_BUILD_LOW_PERF} ]; then
|
|
MODELS=( "tiny" "base" "small" )
|
|
else
|
|
MODELS=("${ALL_MODELS[@]}")
|
|
fi
|
|
fi
|
|
|
|
CMAKE_EXTRA="-DWHISPER_FATAL_WARNINGS=ON"
|
|
|
|
if [[ "$(uname -m)" == "x86_64" ]]; then
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_NATIVE=OFF"
|
|
fi
|
|
|
|
if [ ! -z ${GG_BUILD_METAL} ]; then
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_METAL=ON"
|
|
fi
|
|
|
|
if [ ! -z ${GG_BUILD_CUDA} ]; then
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_CUDA=ON"
|
|
|
|
if command -v nvidia-smi >/dev/null 2>&1; then
|
|
CUDA_ARCH=$(nvidia-smi --query-gpu=compute_cap --format=csv,noheader,nounits 2>/dev/null | head -1 | tr -d '.')
|
|
if [[ -n "$CUDA_ARCH" && "$CUDA_ARCH" =~ ^[0-9]+$ ]]; then
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DCMAKE_CUDA_ARCHITECTURES=${CUDA_ARCH}"
|
|
else
|
|
echo "Warning: Using fallback CUDA architectures"
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DCMAKE_CUDA_ARCHITECTURES=61;70;75;80;86;89"
|
|
fi
|
|
else
|
|
echo "Error: nvidia-smi not found, cannot build with CUDA"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ ! -z ${GG_BUILD_ROCM} ]; then
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_HIP=ON"
|
|
if [ -z ${GG_BUILD_AMDGPU_TARGETS} ]; then
|
|
echo "Missing GG_BUILD_AMDGPU_TARGETS, please set it to your GPU architecture (e.g. gfx90a, gfx1100, etc.)"
|
|
exit 1
|
|
fi
|
|
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DAMDGPU_TARGETS=${GG_BUILD_AMDGPU_TARGETS}"
|
|
fi
|
|
|
|
if [ ! -z ${GG_BUILD_SYCL} ]; then
|
|
if [ -z ${ONEAPI_ROOT} ]; then
|
|
echo "Not detected ONEAPI_ROOT, please install oneAPI base toolkit and enable it by:"
|
|
echo "source /opt/intel/oneapi/setvars.sh"
|
|
exit 1
|
|
fi
|
|
# Use only main GPU
|
|
export ONEAPI_DEVICE_SELECTOR="level_zero:0"
|
|
# Enable sysman for correct memory reporting
|
|
export ZES_ENABLE_SYSMAN=1
|
|
# to circumvent precision issues on CPY operations
|
|
export SYCL_PROGRAM_COMPILE_OPTIONS="-cl-fp32-correctly-rounded-divide-sqrt"
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_SYCL=1 -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -DGGML_SYCL_F16=ON"
|
|
fi
|
|
|
|
if [ ! -z ${GG_BUILD_VULKAN} ]; then
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_VULKAN=1"
|
|
|
|
# if on Mac, disable METAL
|
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_METAL=OFF -DGGML_BLAS=OFF"
|
|
fi
|
|
|
|
fi
|
|
|
|
if [ ! -z ${GG_BUILD_WEBGPU} ]; then
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_WEBGPU=1"
|
|
fi
|
|
|
|
if [ ! -z ${GG_BUILD_MUSA} ]; then
|
|
# Use qy1 by default (MTT S80)
|
|
MUSA_ARCH=${MUSA_ARCH:-21}
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_MUSA=ON -DMUSA_ARCHITECTURES=${MUSA_ARCH}"
|
|
fi
|
|
|
|
if [ ! -z ${GG_BUILD_NO_SVE} ]; then
|
|
# arm 9 and newer enables sve by default, adjust these flags depending on the cpu used
|
|
CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_NATIVE=OFF -DGGML_CPU_ARM_ARCH=armv8.5-a+fp16+i8mm"
|
|
fi
|
|
|
|
## helpers
|
|
|
|
# download a file if it does not exist or if it is outdated
|
|
function gg_wget {
|
|
local out=$1
|
|
local url=$2
|
|
|
|
local cwd=`pwd`
|
|
|
|
mkdir -p $out
|
|
cd $out
|
|
|
|
# should not re-download if file is the same
|
|
wget -nv -N $url
|
|
|
|
cd $cwd
|
|
}
|
|
|
|
function gg_download_model {
|
|
local model_name=$1
|
|
local model_file="$MNT/models/ggml-${model_name}.bin"
|
|
|
|
if [ ! -f ${model_file} ]; then
|
|
local cwd=`pwd`
|
|
mkdir -p "$MNT/models"
|
|
cd "$MNT/models"
|
|
set -x
|
|
bash "$cwd/models/download-ggml-model.sh" ${model_name} .
|
|
local download_status=$?
|
|
set +x
|
|
cd "$cwd"
|
|
if [ $download_status -ne 0 ]; then
|
|
echo "Error: failed to download model ${model_name}"
|
|
ret=1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function gg_printf {
|
|
printf -- "$@" >> $OUT/README.md
|
|
}
|
|
|
|
# Helper function to check command exit status
|
|
function gg_check_last_command_status {
|
|
local exit_file=$1
|
|
local command_name=$2
|
|
|
|
local exit_status=$?
|
|
echo "$exit_status" > "$exit_file"
|
|
|
|
if [ $exit_status -ne 0 ]; then
|
|
echo "Error: Command $command_name failed with exit status $exit_status"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Usage: gg_run <test_name> [additional_args...]
|
|
#
|
|
# Parameters:
|
|
# test_name - Name of the test to run (calls gg_run_<test_name>)
|
|
# additional_args - Any additional arguments to pass to the test function (first argument is appended to the log filename)
|
|
function gg_run {
|
|
ci=$1
|
|
|
|
if [ $# -gt 1 ]; then
|
|
ci="${ci}_${2}"
|
|
fi
|
|
|
|
set -o pipefail
|
|
set -x
|
|
|
|
gg_run_$1 "$@" | tee $OUT/$ci.log
|
|
cur=$?
|
|
echo "$cur" > $OUT/$ci.exit
|
|
|
|
set +x
|
|
set +o pipefail
|
|
|
|
gg_sum_$1 "$@"
|
|
|
|
ret=$((ret | cur))
|
|
}
|
|
|
|
function gg_check_build_requirements {
|
|
if ! command -v cmake &> /dev/null; then
|
|
gg_printf 'cmake not found, please install'
|
|
fi
|
|
|
|
if ! command -v make &> /dev/null; then
|
|
gg_printf 'make not found, please install'
|
|
fi
|
|
}
|
|
|
|
## ci
|
|
|
|
function gg_run_ctest {
|
|
mode=$2
|
|
|
|
cd ${SRC}
|
|
|
|
rm -rf build-ci-${mode} && mkdir build-ci-${mode} && cd build-ci-${mode}
|
|
|
|
set -e
|
|
|
|
gg_check_build_requirements
|
|
|
|
(time cmake -DCMAKE_BUILD_TYPE=${mode} ${CMAKE_EXTRA} .. ) 2>&1 | tee -a $OUT/${ci}-cmake.log
|
|
(time make -j$(nproc) ) 2>&1 | tee -a $OUT/${ci}-make.log
|
|
|
|
(time ctest --output-on-failure -L main -E test-opt ) 2>&1 | tee -a $OUT/${ci}-ctest.log
|
|
|
|
set +e
|
|
}
|
|
|
|
function gg_sum_ctest {
|
|
mode=$2
|
|
|
|
gg_printf '### %s\n\n' "${ci}"
|
|
|
|
gg_printf 'Runs ctest in '${mode}' mode\n'
|
|
gg_printf '- status: %s\n' "$(cat $OUT/${ci}.exit)"
|
|
gg_printf '```\n'
|
|
gg_printf '%s\n' "$(cat $OUT/${ci}-ctest.log)"
|
|
gg_printf '```\n'
|
|
}
|
|
|
|
function gg_run_bench {
|
|
cd ${SRC}
|
|
|
|
# set flash attention flag if enabled
|
|
fattn="-nfa"
|
|
if [ "$BENCH_FLASH_ATTN" -eq 1 ]; then
|
|
fattn="-fa"
|
|
fi
|
|
|
|
# run memcpy benchmark if not encoder-only mode
|
|
if [ "$BENCH_ENCODER_ONLY" -eq 0 ]; then
|
|
echo "Running memcpy benchmark"
|
|
(time ./build-ci-release/bin/whisper-bench -w 1 -t $BENCH_N_THREADS 2>&1) | tee -a $OUT/${ci}-memcpy.log
|
|
gg_check_last_command_status "$OUT/${ci}-memcpy.exit" "memcpy benchmark"
|
|
|
|
echo "Running ggml_mul_mat benchmark with $BENCH_N_THREADS threads"
|
|
(time ./build-ci-release/bin/whisper-bench -w 2 -t $BENCH_N_THREADS 2>&1) | tee -a $OUT/${ci}-mul_mat.log
|
|
gg_check_last_command_status "$OUT/${ci}-mul_mat.exit" "ggml_mul_mat benchmark"
|
|
fi
|
|
|
|
echo "Running benchmark for all models"
|
|
|
|
# generate header for the benchmark table
|
|
{
|
|
printf "| %16s | %13s | %3s | %3s | %7s | %7s | %7s | %7s | %7s |\n" "Config" "Model" "Th" "FA" "Enc." "Dec." "Bch5" "PP" "Commit"
|
|
printf "| %16s | %13s | %3s | %3s | %7s | %7s | %7s | %7s | %7s |\n" "---" "---" "---" "---" "---" "---" "---" "---" "---"
|
|
} | tee -a $OUT/${ci}-models-table.log
|
|
|
|
res=0
|
|
|
|
# run benchmark for each model
|
|
for model in "${MODELS[@]}"; do
|
|
echo "Benchmarking model: $model"
|
|
|
|
# run the benchmark and capture output
|
|
output=$(./build-ci-release/bin/whisper-bench -m $MNT/models/ggml-$model.bin -t $BENCH_N_THREADS $fattn 2>&1)
|
|
ret=$?
|
|
|
|
# save the raw output
|
|
echo "$output" > $OUT/${ci}-bench-$model.log
|
|
|
|
if [ $ret -eq 0 ]; then
|
|
# parse the benchmark results
|
|
encode_time=$(echo "$output" | grep "encode time" | awk '{print $11}')
|
|
decode_time=$(echo "$output" | grep "decode time" | awk '{print $11}')
|
|
batchd_time=$(echo "$output" | grep "batchd time" | awk '{print $11}')
|
|
prompt_time=$(echo "$output" | grep "prompt time" | awk '{print $11}')
|
|
system_info=$(echo "$output" | grep "system_info")
|
|
actual_threads=$(echo "$output" | grep "system_info" | awk '{print $4}')
|
|
|
|
# determine configuration
|
|
config=""
|
|
if [[ $system_info == *"AVX2 = 1"* ]]; then
|
|
config="$config AVX2"
|
|
fi
|
|
if [[ $system_info == *"NEON = 1"* ]]; then
|
|
config="$config NEON"
|
|
fi
|
|
if [[ $system_info == *"BLAS = 1"* ]]; then
|
|
config="$config BLAS"
|
|
fi
|
|
if [[ $system_info == *"COREML = 1"* ]]; then
|
|
config="$config COREML"
|
|
fi
|
|
if [[ $system_info == *"CUDA = 1"* ]]; then
|
|
config="$config CUDA"
|
|
fi
|
|
if [[ $system_info == *"METAL = 1"* ]]; then
|
|
config="$config METAL"
|
|
fi
|
|
|
|
# get commit hash
|
|
commit=$(git rev-parse --short HEAD)
|
|
|
|
# add row to benchmark table
|
|
printf "| %16s | %13s | %3s | %3s | %7s | %7s | %7s | %7s | %7s |\n" \
|
|
"$config" "$model" "$actual_threads" "$BENCH_FLASH_ATTN" "$encode_time" "$decode_time" "$batchd_time" "$prompt_time" "$commit" \
|
|
| tee -a $OUT/${ci}-models-table.log
|
|
else
|
|
echo "Benchmark failed for model: $model" | tee -a $OUT/${ci}-bench-errors.log
|
|
res=1
|
|
fi
|
|
done
|
|
|
|
return $res
|
|
}
|
|
|
|
function gg_sum_bench {
|
|
gg_printf '### %s\n\n' "${ci}"
|
|
|
|
gg_printf 'Whisper Benchmark Results\n'
|
|
gg_printf '- status: %s\n' "$(cat $OUT/${ci}.exit)"
|
|
|
|
# show memcpy and ggml_mul_mat benchmark results if available
|
|
if [ "$BENCH_ENCODER_ONLY" -eq 0 ]; then
|
|
if [ -f "$OUT/${ci}-memcpy.log" ]; then
|
|
gg_printf '#### memcpy Benchmark\n\n'
|
|
gg_printf '```\n%s\n```\n\n' "$(cat $OUT/${ci}-memcpy.log)"
|
|
fi
|
|
|
|
if [ -f "$OUT/${ci}-mul_mat.log" ]; then
|
|
gg_printf '#### ggml_mul_mat Benchmark\n\n'
|
|
gg_printf '```\n%s\n```\n\n' "$(cat $OUT/${ci}-mul_mat.log)"
|
|
fi
|
|
fi
|
|
|
|
# show model benchmark results
|
|
gg_printf '#### Model Benchmarks\n\n'
|
|
if [ -f "$OUT/${ci}-models-table.log" ]; then
|
|
gg_printf '%s\n\n' "$(cat $OUT/${ci}-models-table.log)"
|
|
else
|
|
gg_printf 'No model benchmark results available.\n\n'
|
|
fi
|
|
|
|
# show any errors that occurred
|
|
if [ -f "$OUT/${ci}-bench-errors.log" ]; then
|
|
gg_printf '#### Benchmark Errors\n\n'
|
|
gg_printf '```\n%s\n```\n\n' "$(cat $OUT/${ci}-bench-errors.log)"
|
|
fi
|
|
}
|
|
|
|
ret=0
|
|
|
|
for model in "${MODELS[@]}"; do
|
|
test $ret -eq 0 && gg_download_model ${model}
|
|
done
|
|
|
|
test $ret -eq 0 && gg_run ctest debug
|
|
test $ret -eq 0 && gg_run ctest release
|
|
|
|
test $ret -eq 0 && gg_run bench
|
|
|
|
cat $OUT/README.md
|
|
|
|
exit $ret
|