From 2d9a69ac8a1d44ed3b77b840aec3b36f067d4c38 Mon Sep 17 00:00:00 2001 From: Antoine Viallon Date: Fri, 13 Dec 2024 23:54:25 +0100 Subject: [PATCH 1/2] whisper-cpp: add ROCm and Vulkan support, rename from openai-whisper-cpp Rewrite to use CMake build Add aviallon to whisper-cpp's maintainers --- .../audio/openai-whisper-cpp/default.nix | 212 ++++++++++++------ pkgs/top-level/aliases.nix | 1 + pkgs/top-level/all-packages.nix | 6 +- 3 files changed, 154 insertions(+), 65 deletions(-) diff --git a/pkgs/tools/audio/openai-whisper-cpp/default.nix b/pkgs/tools/audio/openai-whisper-cpp/default.nix index e65d909b41f8..e8ddeb672a19 100644 --- a/pkgs/tools/audio/openai-whisper-cpp/default.nix +++ b/pkgs/tools/audio/openai-whisper-cpp/default.nix @@ -1,27 +1,75 @@ -{ lib -, stdenv -, fetchFromGitHub -, SDL2 -, makeWrapper -, wget -, which -, Accelerate -, CoreGraphics -, CoreML -, CoreVideo -, MetalKit +{ + lib, + stdenv, + cmake, + apple-sdk_11, + ninja, + fetchFromGitHub, + SDL2, + wget, + which, + autoAddDriverRunpath, + makeWrapper, -, config -, autoAddDriverRunpath -, cudaSupport ? config.cudaSupport -, cudaPackages ? {} + metalSupport ? stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64, + coreMLSupport ? stdenv.hostPlatform.isDarwin && false, # FIXME currently broken + + config, + cudaSupport ? config.cudaSupport, + cudaPackages ? { }, + + rocmSupport ? config.rocmSupport, + rocmPackages ? { }, + rocmGpuTargets ? builtins.concatStringsSep ";" rocmPackages.clr.gpuTargets, + + vulkanSupport ? false, + shaderc, + vulkan-headers, + vulkan-loader, + + withSDL ? true, }: +assert metalSupport -> stdenv.hostPlatform.isDarwin; +assert coreMLSupport -> stdenv.hostPlatform.isDarwin; + let # It's necessary to consistently use backendStdenv when building with CUDA support, # otherwise we get libstdc++ errors downstream. # cuda imposes an upper bound on the gcc version, e.g. the latest gcc compatible with cudaPackages_11 is gcc11 effectiveStdenv = if cudaSupport then cudaPackages.backendStdenv else stdenv; + inherit (lib) + cmakeBool + cmakeFeature + optional + optionals + optionalString + forEach + ; + + darwinBuildInputs = [ apple-sdk_11 ]; + + cudaBuildInputs = with cudaPackages; [ + cuda_cccl # + + # A temporary hack for reducing the closure size, remove once cudaPackages + # have stopped using lndir: https://github.com/NixOS/nixpkgs/issues/271792 + cuda_cudart + libcublas + ]; + + rocmBuildInputs = with rocmPackages; [ + clr + hipblas + rocblas + ]; + + vulkanBuildInputs = [ + shaderc + vulkan-headers + vulkan-loader + ]; + in effectiveStdenv.mkDerivation (finalAttrs: { pname = "whisper-cpp"; @@ -30,7 +78,7 @@ effectiveStdenv.mkDerivation (finalAttrs: { src = fetchFromGitHub { owner = "ggerganov"; repo = "whisper.cpp"; - rev = "refs/tags/v${finalAttrs.version}" ; + rev = "refs/tags/v${finalAttrs.version}"; hash = "sha256-y30ZccpF3SCdRGa+P3ddF1tT1KnvlI4Fexx81wZxfTk="; }; @@ -40,74 +88,112 @@ effectiveStdenv.mkDerivation (finalAttrs: { # the models to the current directory of where it is being run from. patches = [ ./download-models.patch ]; - nativeBuildInputs = [ + postPatch = '' + for target in examples/{bench,command,main,quantize,server,stream,talk}/CMakeLists.txt; do + if ! grep -q -F 'install('; then + echo 'install(TARGETS ''${TARGET} RUNTIME)' >> $target + fi + done + ''; + + nativeBuildInputs = + [ + cmake + ninja which makeWrapper - ] ++ lib.optionals cudaSupport [ + ] + ++ lib.optionals cudaSupport [ cudaPackages.cuda_nvcc autoAddDriverRunpath ]; - buildInputs = [ - SDL2 - ] ++ lib.optionals stdenv.hostPlatform.isDarwin [ - Accelerate - CoreGraphics - CoreML - CoreVideo - MetalKit - ] ++ lib.optionals cudaSupport ( with cudaPackages; [ - cuda_cccl # provides nv/target - cuda_cudart - libcublas - ]); + buildInputs = + optional withSDL SDL2 + ++ optionals effectiveStdenv.hostPlatform.isDarwin darwinBuildInputs + ++ optionals cudaSupport cudaBuildInputs + ++ optionals rocmSupport rocmBuildInputs + ++ optionals vulkanSupport vulkanBuildInputs; - postPatch = let - cudaOldStr = "-lcuda "; - cudaNewStr = "-lcuda -L${cudaPackages.cuda_cudart}/lib/stubs "; - in lib.optionalString cudaSupport '' - substituteInPlace Makefile \ - --replace-fail '${cudaOldStr}' '${cudaNewStr}' - ''; + cmakeFlags = + [ + (cmakeBool "WHISPER_BUILD_EXAMPLES" true) + (cmakeBool "GGML_CUDA" cudaSupport) + (cmakeBool "GGML_HIPBLAS" rocmSupport) + (cmakeBool "GGML_VULKAN" vulkanSupport) + (cmakeBool "WHISPER_SDL2" withSDL) + (cmakeBool "GGML_LTO" true) + (cmakeBool "GGML_NATIVE" false) + (cmakeBool "BUILD_SHARED_LIBS" (!effectiveStdenv.hostPlatform.isStatic)) + ] + ++ optionals (effectiveStdenv.hostPlatform.isx86 && !effectiveStdenv.hostPlatform.isStatic) [ + (cmakeBool "GGML_BACKEND_DL" true) + (cmakeBool "GGML_CPU_ALL_VARIANTS" true) + ] + ++ optionals cudaSupport [ + (cmakeFeature "CMAKE_CUDA_ARCHITECTURES" cudaPackages.flags.cmakeCudaArchitecturesString) + ] + ++ optionals rocmSupport [ + (cmakeFeature "CMAKE_C_COMPILER" "hipcc") + (cmakeFeature "CMAKE_CXX_COMPILER" "hipcc") - env = lib.optionalAttrs stdenv.hostPlatform.isDarwin { - WHISPER_COREML = "1"; - WHISPER_COREML_ALLOW_FALLBACK = "1"; - WHISPER_METAL_EMBED_LIBRARY = "1"; - } // lib.optionalAttrs cudaSupport { - GGML_CUDA = "1"; - }; + # Build all targets supported by rocBLAS. When updating search for TARGET_LIST_ROCM + # in https://github.com/ROCmSoftwarePlatform/rocBLAS/blob/develop/CMakeLists.txt + # and select the line that matches the current nixpkgs version of rocBLAS. + "-DAMDGPU_TARGETS=${rocmGpuTargets}" + ] + ++ optionals coreMLSupport [ + (cmakeBool "WHISPER_COREML" true) + (cmakeBool "WHISPER_COREML_ALLOW_FALLBACK" true) + ] + ++ optionals metalSupport [ + (cmakeFeature "CMAKE_C_FLAGS" "-D__ARM_FEATURE_DOTPROD=1") + (cmakeBool "GGML_METAL" true) + (cmakeBool "GGML_METAL_EMBED_LIBRARY" true) + ]; - installPhase = '' - runHook preInstall + postInstall = '' + # Add "whisper-cpp" prefix before every command + mv -v $out/bin/{main,whisper-cpp} - mkdir -p $out/bin - - cp ./main $out/bin/whisper-cpp - - for file in *; do - if [[ -x "$file" && -f "$file" && "$file" != "main" ]]; then - cp "$file" "$out/bin/whisper-cpp-$file" + for file in $out/bin/*; do + if [[ -x "$file" && -f "$file" && "$(basename $file)" != "whisper-cpp" ]]; then + mv -v "$file" "$out/bin/whisper-cpp-$(basename $file)" fi done - cp models/download-ggml-model.sh $out/bin/whisper-cpp-download-ggml-model + install -v -D -m755 $src/models/download-ggml-model.sh $out/bin/whisper-cpp-download-ggml-model wrapProgram $out/bin/whisper-cpp-download-ggml-model \ - --prefix PATH : ${lib.makeBinPath [wget]} - - runHook postInstall + --prefix PATH : ${lib.makeBinPath [ wget ]} ''; - meta = with lib; { + requiredSystemFeatures = optionals rocmSupport [ "big-parallel" ]; # rocmSupport multiplies build time by the number of GPU targets, which takes arround 30 minutes on a 16-cores system to build + + doInstallCheck = true; + + installCheckPhase = '' + runHook preInstallCheck + $out/bin/whisper-cpp --help >/dev/null + runHook postInstallCheck + ''; + + meta = { description = "Port of OpenAI's Whisper model in C/C++"; longDescription = '' To download the models as described in the project's readme, you may use the `whisper-cpp-download-ggml-model` binary from this package. ''; homepage = "https://github.com/ggerganov/whisper.cpp"; - license = licenses.mit; - platforms = platforms.all; - maintainers = with maintainers; [ dit7ya hughobrien ]; + license = lib.licenses.mit; + mainProgram = "whisper-cpp"; + platforms = lib.platforms.all; + broken = coreMLSupport; + badPlatforms = optionals cudaSupport lib.platforms.darwin; + maintainers = with lib.maintainers; [ + dit7ya + hughobrien + aviallon + ]; }; }) diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix index e62c6d5d80db..818620b0fb17 100644 --- a/pkgs/top-level/aliases.nix +++ b/pkgs/top-level/aliases.nix @@ -986,6 +986,7 @@ mapAliases { oauth2_proxy = throw "'oauth2_proxy' has been renamed to/replaced by 'oauth2-proxy'"; # Converted to throw 2024-10-17 oil = lib.warnOnInstantiate "Oil has been replaced with the faster native C++ version and renamed to 'oils-for-unix'. See also https://github.com/oils-for-unix/oils/wiki/Oils-Deployments" oils-for-unix; # Added 2024-10-22 onevpl-intel-gpu = lib.warnOnInstantiate "onevpl-intel-gpu has been renamed to vpl-gpu-rt" vpl-gpu-rt; # Added 2024-06-04 + openai-whisper-cpp = whisper-cpp; # Added 2024-12-13 opencv2 = throw "opencv2 has been removed as it is obsolete and was not used by any other package; please migrate to OpenCV 4"; # Added 2024-08-20 opencv3 = throw "opencv3 has been removed as it is obsolete and was not used by any other package; please migrate to OpenCV 4"; # Added 2024-08-20 openafs_1_8 = openafs; # Added 2022-08-22 diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 7411f98dc38b..e0caa29545e4 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -8143,8 +8143,10 @@ with pkgs; openai-whisper = with python3.pkgs; toPythonApplication openai-whisper; - openai-whisper-cpp = darwin.apple_sdk_11_0.callPackage ../tools/audio/openai-whisper-cpp { - inherit (darwin.apple_sdk_11_0.frameworks) Accelerate CoreGraphics CoreML CoreVideo MetalKit; + whisper-cpp = callPackage ../tools/audio/openai-whisper-cpp { }; + + whisper-cpp-vulkan = whisper-cpp.override { + vulkanSupport = true; }; openocd-rp2040 = openocd.overrideAttrs (old: { From 89de5a96e49a85938c504b39ac756df207a287d2 Mon Sep 17 00:00:00 2001 From: Antoine Viallon Date: Fri, 13 Dec 2024 23:47:16 +0100 Subject: [PATCH 2/2] whisper-cpp: convert to by-name --- .../wh/whisper-cpp}/download-models.patch | 0 .../default.nix => by-name/wh/whisper-cpp/package.nix} | 0 pkgs/top-level/all-packages.nix | 10 ++++------ 3 files changed, 4 insertions(+), 6 deletions(-) rename pkgs/{tools/audio/openai-whisper-cpp => by-name/wh/whisper-cpp}/download-models.patch (100%) rename pkgs/{tools/audio/openai-whisper-cpp/default.nix => by-name/wh/whisper-cpp/package.nix} (100%) diff --git a/pkgs/tools/audio/openai-whisper-cpp/download-models.patch b/pkgs/by-name/wh/whisper-cpp/download-models.patch similarity index 100% rename from pkgs/tools/audio/openai-whisper-cpp/download-models.patch rename to pkgs/by-name/wh/whisper-cpp/download-models.patch diff --git a/pkgs/tools/audio/openai-whisper-cpp/default.nix b/pkgs/by-name/wh/whisper-cpp/package.nix similarity index 100% rename from pkgs/tools/audio/openai-whisper-cpp/default.nix rename to pkgs/by-name/wh/whisper-cpp/package.nix diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index e0caa29545e4..473eeeeff9da 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -8143,12 +8143,6 @@ with pkgs; openai-whisper = with python3.pkgs; toPythonApplication openai-whisper; - whisper-cpp = callPackage ../tools/audio/openai-whisper-cpp { }; - - whisper-cpp-vulkan = whisper-cpp.override { - vulkanSupport = true; - }; - openocd-rp2040 = openocd.overrideAttrs (old: { pname = "openocd-rp2040"; src = fetchFromGitHub { @@ -8420,6 +8414,10 @@ with pkgs; inherit (llvmPackages) clang-unwrapped; }; + whisper-cpp-vulkan = whisper-cpp.override { + vulkanSupport = true; + }; + watson-ruby = callPackage ../development/tools/misc/watson-ruby { }; xmake = darwin.apple_sdk_11_0.callPackage ../development/tools/build-managers/xmake {