]> git.djapps.eu Git - pkg/ggml/sources/whisper.cpp/commitdiff
whisper.android : how to build with CLBlast (#1809)
authorNeuman Vong <redacted>
Fri, 9 Feb 2024 15:39:05 +0000 (02:39 +1100)
committerGitHub <redacted>
Fri, 9 Feb 2024 15:39:05 +0000 (17:39 +0200)
* FetchContent

* OpenCL

* Documentation and make optional

* Specify GGML build options in build.gradle

* Use gradle properties

* @ggerganov

Co-authored-by: Georgi Gerganov <redacted>
* @gpokat

---------

Co-authored-by: Georgi Gerganov <redacted>
.github/workflows/build.yml
examples/whisper.android/README.md
examples/whisper.android/lib/build.gradle
examples/whisper.android/lib/src/main/jni/whisper/CMakeLists.txt

index ae6c4ce9b450998d2b0eb7896402558c6e53174e..41cb691ca383d6bf5da62b9961527e393631c15e 100644 (file)
@@ -416,6 +416,14 @@ jobs:
     steps:
       - name: Clone
         uses: actions/checkout@v3
+        with:
+          path: whisper
+
+      - name: Clone
+        uses: actions/checkout@v3
+        with:
+          repository: ggerganov/ggml
+          path: ggml
 
       - name: Install Java
         uses: actions/setup-java@v3
@@ -428,9 +436,15 @@ jobs:
 
       - name: Build
         run: |
-          cd examples/whisper.android
+          cd whisper/examples/whisper.android
           ./gradlew assembleRelease --no-daemon
 
+      - name: Build with external ggml
+        run: |
+          export PATH_TO_GGML=$PWD/ggml
+          cd whisper/examples/whisper.android
+          ./gradlew assembleRelease --no-daemon -PGGML_HOME=$PATH_TO_GGML
+
   android_java:
     runs-on: ubuntu-latest
 
index cf8a328c0e42e18bb43c623fb4d4942ede640d06..a661b3238426ae9290cf5afd89cdd7d34be6e6b5 100644 (file)
@@ -12,3 +12,47 @@ To use:
 (PS: Do not move this android project folder individually to other folders, because this android project folder depends on the files of the whole project.)
 
 <img width="300" alt="image" src="https://user-images.githubusercontent.com/1670775/221613663-a17bf770-27ef-45ab-9a46-a5f99ba65d2a.jpg">
+
+## CLBlast
+
+> [!NOTE]
+> - OpenCL does not have the same level of support as CUDA or Metal.
+> - Turning on CLBlast may degrade OpenCL performance if your device isn't already tuned. See [tuning.md](https://github.com/CNugteren/CLBlast/blob/162783a414969464ce3aa5adf5c2554afa5ee93e/doc/tuning.md#already-tuned-for-devices) for a list of devices that are already tuned and what to do if yours is missing.
+
+Build CLBlast.
+
+```
+# In path/to/CLBlast (we assume OpenCL-Headers relative location)
+$ANDROID_SDK_PATH/cmake/3.22.1/bin/cmake .. \
+    -DCMAKE_SYSTEM_NAME=Android \
+    -DCMAKE_SYSTEM_VERSION=33 \
+    -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
+    -DCMAKE_ANDROID_NDK=$ANDROID_NDK_PATH \
+    -DCMAKE_ANDROID_STL_TYPE=c++_static \
+    -DOPENCL_ROOT=$(readlink -f ../../OpenCL-Headers) \
+    -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH \
+    -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH
+
+# Build libclblast.so
+make -j4
+```
+
+Pull `libGLES_mali.so` to `libOpenCL.so`.
+
+```bash
+# In path/to/whisper.android
+mkdir lib/src/main/jniLibs/arm64-v8a
+adb pull /system/vendor/lib64/egl/libGLES_mali.so lib/src/main/jniLibs/arm64-v8a/libOpenCL.so
+```
+
+In gradle.properties, set `GGML_HOME` to the location of GGML, as well as
+required options for turning on CLBlast.
+
+```
+GGML_HOME=/path/to/ggml
+GGML_CLBLAST=ON
+CLBLAST_HOME=/path/to/CLBlast
+OPENCL_LIB=/path/to/libOpenCL.so
+OPENCL_ROOT=/path/to/OpenCL-Headers
+```
+
index c32a6899bed75106cf0ca89df5402db1d462b94c..e4779e2652753442ab4b2292936a4b5f0accf48c 100644 (file)
@@ -16,6 +16,28 @@ android {
         ndk {
             abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
         }
+        externalNativeBuild {
+            cmake {
+                // When set, builds whisper.android against the version located
+                // at GGML_HOME instead of the copy bundled with whisper.cpp.
+                if (
+                    project.hasProperty('GGML_HOME') &&
+                    project.findProperty('GGML_CLBLAST') == 'ON'
+                ) {
+                    // Turning on CLBlast requires GGML_HOME
+                    arguments "-DGGML_HOME=${project.property('GGML_HOME')}",
+                         "-DGGML_CLBLAST=ON",
+                         "-DOPENCL_LIB=${project.property('OPENCL_LIB')}",
+                         "-DCLBLAST_HOME=${project.property('CLBLAST_HOME')}",
+                         "-DOPENCL_ROOT=${project.property('OPENCL_ROOT')}",
+                         "-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH",
+                         "-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH"
+                } else if (project.hasProperty('GGML_HOME')) {
+                    arguments "-DGGML_HOME=${project.property('GGML_HOME')}"
+                }
+
+            }
+        }
     }
 
     buildTypes {
index 390fd196c0a0f95f845d6349583d9c8fbbfae241..49f34479a40fdeeafebcb17e1edb9a5a4c63416c 100644 (file)
@@ -3,17 +3,28 @@ cmake_minimum_required(VERSION 3.10)
 project(whisper.cpp)
 
 set(CMAKE_CXX_STANDARD 11)
-set(WHISPER_LIB_DIR ${CMAKE_SOURCE_DIR}/../../../../../../../)
+set(WHISPER_LIB_DIR ${CMAKE_SOURCE_DIR}/../../../../../../..)
+
+# Path to external GGML, otherwise uses the copy in whisper.cpp.
+option(GGML_HOME       "whisper: Path to external GGML source" OFF)
 
 set(
         SOURCE_FILES
+        ${WHISPER_LIB_DIR}/whisper.cpp
+        ${CMAKE_SOURCE_DIR}/jni.c
+)
+
+if (NOT GGML_HOME)
+    set(
+        SOURCE_FILES
+        ${SOURCE_FILES}
         ${WHISPER_LIB_DIR}/ggml.c
         ${WHISPER_LIB_DIR}/ggml-alloc.c
         ${WHISPER_LIB_DIR}/ggml-backend.c
         ${WHISPER_LIB_DIR}/ggml-quants.c
-        ${WHISPER_LIB_DIR}/whisper.cpp
-        ${CMAKE_SOURCE_DIR}/jni.c
-)
+
+    )
+endif()
 
 find_library(LOG_LIB log)
 
@@ -24,12 +35,12 @@ function(build_library target_name)
         ${SOURCE_FILES}
     )
 
-    target_link_libraries(${target_name} ${LOG_LIB} android)
-
     if (${target_name} STREQUAL "whisper_v8fp16_va")
         target_compile_options(${target_name} PRIVATE -march=armv8.2-a+fp16)
+        set(GGML_COMPILE_OPTIONS                      -march=armv8.2-a+fp16)
     elseif (${target_name} STREQUAL "whisper_vfpv4")
         target_compile_options(${target_name} PRIVATE -mfpu=neon-vfpv4)
+        set(GGML_COMPILE_OPTIONS                      -mfpu=neon-vfpv4)
     endif ()
 
     if (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
@@ -43,9 +54,20 @@ function(build_library target_name)
         target_link_options(${target_name} PRIVATE -flto)
 
     endif ()
-endfunction()
 
-build_library("whisper") # Default target
+    if (GGML_HOME)
+        include(FetchContent)
+        FetchContent_Declare(ggml SOURCE_DIR ${GGML_HOME})
+        FetchContent_MakeAvailable(ggml)
+
+        target_compile_options(ggml PRIVATE ${GGML_COMPILE_OPTIONS})
+        target_link_libraries(${target_name} ${LOG_LIB} android ggml)
+    else()
+        target_link_libraries(${target_name} ${LOG_LIB} android)
+    endif()
+
+
+endfunction()
 
 if (${ANDROID_ABI} STREQUAL "arm64-v8a")
     build_library("whisper_v8fp16_va")
@@ -53,4 +75,6 @@ elseif (${ANDROID_ABI} STREQUAL "armeabi-v7a")
     build_library("whisper_vfpv4")
 endif ()
 
+build_library("whisper") # Default target
+
 include_directories(${WHISPER_LIB_DIR})