Spaces:
Sleeping
Sleeping
whisper.android : how to build with CLBlast (#1809)
Browse files* FetchContent
* OpenCL
* Documentation and make optional
* Specify GGML build options in build.gradle
* Use gradle properties
*
@ggerganov
Co-authored-by: Georgi Gerganov <[email protected]>
* @gpokat
---------
Co-authored-by: Georgi Gerganov <[email protected]>
.github/workflows/build.yml
CHANGED
|
@@ -416,6 +416,14 @@ jobs:
|
|
| 416 |
steps:
|
| 417 |
- name: Clone
|
| 418 |
uses: actions/checkout@v3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 419 |
|
| 420 |
- name: Install Java
|
| 421 |
uses: actions/setup-java@v3
|
|
@@ -428,9 +436,15 @@ jobs:
|
|
| 428 |
|
| 429 |
- name: Build
|
| 430 |
run: |
|
| 431 |
-
cd examples/whisper.android
|
| 432 |
./gradlew assembleRelease --no-daemon
|
| 433 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 434 |
android_java:
|
| 435 |
runs-on: ubuntu-latest
|
| 436 |
|
|
|
|
| 416 |
steps:
|
| 417 |
- name: Clone
|
| 418 |
uses: actions/checkout@v3
|
| 419 |
+
with:
|
| 420 |
+
path: whisper
|
| 421 |
+
|
| 422 |
+
- name: Clone
|
| 423 |
+
uses: actions/checkout@v3
|
| 424 |
+
with:
|
| 425 |
+
repository: ggerganov/ggml
|
| 426 |
+
path: ggml
|
| 427 |
|
| 428 |
- name: Install Java
|
| 429 |
uses: actions/setup-java@v3
|
|
|
|
| 436 |
|
| 437 |
- name: Build
|
| 438 |
run: |
|
| 439 |
+
cd whisper/examples/whisper.android
|
| 440 |
./gradlew assembleRelease --no-daemon
|
| 441 |
|
| 442 |
+
- name: Build with external ggml
|
| 443 |
+
run: |
|
| 444 |
+
export PATH_TO_GGML=$PWD/ggml
|
| 445 |
+
cd whisper/examples/whisper.android
|
| 446 |
+
./gradlew assembleRelease --no-daemon -PGGML_HOME=$PATH_TO_GGML
|
| 447 |
+
|
| 448 |
android_java:
|
| 449 |
runs-on: ubuntu-latest
|
| 450 |
|
examples/whisper.android/README.md
CHANGED
|
@@ -12,3 +12,47 @@ To use:
|
|
| 12 |
(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.)
|
| 13 |
|
| 14 |
<img width="300" alt="image" src="https://user-images.githubusercontent.com/1670775/221613663-a17bf770-27ef-45ab-9a46-a5f99ba65d2a.jpg">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
(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.)
|
| 13 |
|
| 14 |
<img width="300" alt="image" src="https://user-images.githubusercontent.com/1670775/221613663-a17bf770-27ef-45ab-9a46-a5f99ba65d2a.jpg">
|
| 15 |
+
|
| 16 |
+
## CLBlast
|
| 17 |
+
|
| 18 |
+
> [!NOTE]
|
| 19 |
+
> - OpenCL does not have the same level of support as CUDA or Metal.
|
| 20 |
+
> - 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.
|
| 21 |
+
|
| 22 |
+
Build CLBlast.
|
| 23 |
+
|
| 24 |
+
```
|
| 25 |
+
# In path/to/CLBlast (we assume OpenCL-Headers relative location)
|
| 26 |
+
$ANDROID_SDK_PATH/cmake/3.22.1/bin/cmake .. \
|
| 27 |
+
-DCMAKE_SYSTEM_NAME=Android \
|
| 28 |
+
-DCMAKE_SYSTEM_VERSION=33 \
|
| 29 |
+
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
|
| 30 |
+
-DCMAKE_ANDROID_NDK=$ANDROID_NDK_PATH \
|
| 31 |
+
-DCMAKE_ANDROID_STL_TYPE=c++_static \
|
| 32 |
+
-DOPENCL_ROOT=$(readlink -f ../../OpenCL-Headers) \
|
| 33 |
+
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH \
|
| 34 |
+
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH
|
| 35 |
+
|
| 36 |
+
# Build libclblast.so
|
| 37 |
+
make -j4
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
Pull `libGLES_mali.so` to `libOpenCL.so`.
|
| 41 |
+
|
| 42 |
+
```bash
|
| 43 |
+
# In path/to/whisper.android
|
| 44 |
+
mkdir lib/src/main/jniLibs/arm64-v8a
|
| 45 |
+
adb pull /system/vendor/lib64/egl/libGLES_mali.so lib/src/main/jniLibs/arm64-v8a/libOpenCL.so
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
In gradle.properties, set `GGML_HOME` to the location of GGML, as well as
|
| 49 |
+
required options for turning on CLBlast.
|
| 50 |
+
|
| 51 |
+
```
|
| 52 |
+
GGML_HOME=/path/to/ggml
|
| 53 |
+
GGML_CLBLAST=ON
|
| 54 |
+
CLBLAST_HOME=/path/to/CLBlast
|
| 55 |
+
OPENCL_LIB=/path/to/libOpenCL.so
|
| 56 |
+
OPENCL_ROOT=/path/to/OpenCL-Headers
|
| 57 |
+
```
|
| 58 |
+
|
examples/whisper.android/lib/build.gradle
CHANGED
|
@@ -16,6 +16,28 @@ android {
|
|
| 16 |
ndk {
|
| 17 |
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
|
| 18 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
}
|
| 20 |
|
| 21 |
buildTypes {
|
|
|
|
| 16 |
ndk {
|
| 17 |
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
|
| 18 |
}
|
| 19 |
+
externalNativeBuild {
|
| 20 |
+
cmake {
|
| 21 |
+
// When set, builds whisper.android against the version located
|
| 22 |
+
// at GGML_HOME instead of the copy bundled with whisper.cpp.
|
| 23 |
+
if (
|
| 24 |
+
project.hasProperty('GGML_HOME') &&
|
| 25 |
+
project.findProperty('GGML_CLBLAST') == 'ON'
|
| 26 |
+
) {
|
| 27 |
+
// Turning on CLBlast requires GGML_HOME
|
| 28 |
+
arguments "-DGGML_HOME=${project.property('GGML_HOME')}",
|
| 29 |
+
"-DGGML_CLBLAST=ON",
|
| 30 |
+
"-DOPENCL_LIB=${project.property('OPENCL_LIB')}",
|
| 31 |
+
"-DCLBLAST_HOME=${project.property('CLBLAST_HOME')}",
|
| 32 |
+
"-DOPENCL_ROOT=${project.property('OPENCL_ROOT')}",
|
| 33 |
+
"-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH",
|
| 34 |
+
"-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH"
|
| 35 |
+
} else if (project.hasProperty('GGML_HOME')) {
|
| 36 |
+
arguments "-DGGML_HOME=${project.property('GGML_HOME')}"
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
}
|
| 42 |
|
| 43 |
buildTypes {
|
examples/whisper.android/lib/src/main/jni/whisper/CMakeLists.txt
CHANGED
|
@@ -3,17 +3,28 @@ cmake_minimum_required(VERSION 3.10)
|
|
| 3 |
project(whisper.cpp)
|
| 4 |
|
| 5 |
set(CMAKE_CXX_STANDARD 11)
|
| 6 |
-
set(WHISPER_LIB_DIR ${CMAKE_SOURCE_DIR}
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
set(
|
| 9 |
SOURCE_FILES
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
${WHISPER_LIB_DIR}/ggml.c
|
| 11 |
${WHISPER_LIB_DIR}/ggml-alloc.c
|
| 12 |
${WHISPER_LIB_DIR}/ggml-backend.c
|
| 13 |
${WHISPER_LIB_DIR}/ggml-quants.c
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
)
|
| 17 |
|
| 18 |
find_library(LOG_LIB log)
|
| 19 |
|
|
@@ -24,12 +35,12 @@ function(build_library target_name)
|
|
| 24 |
${SOURCE_FILES}
|
| 25 |
)
|
| 26 |
|
| 27 |
-
target_link_libraries(${target_name} ${LOG_LIB} android)
|
| 28 |
-
|
| 29 |
if (${target_name} STREQUAL "whisper_v8fp16_va")
|
| 30 |
target_compile_options(${target_name} PRIVATE -march=armv8.2-a+fp16)
|
|
|
|
| 31 |
elseif (${target_name} STREQUAL "whisper_vfpv4")
|
| 32 |
target_compile_options(${target_name} PRIVATE -mfpu=neon-vfpv4)
|
|
|
|
| 33 |
endif ()
|
| 34 |
|
| 35 |
if (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
|
@@ -43,9 +54,20 @@ function(build_library target_name)
|
|
| 43 |
target_link_options(${target_name} PRIVATE -flto)
|
| 44 |
|
| 45 |
endif ()
|
| 46 |
-
endfunction()
|
| 47 |
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
if (${ANDROID_ABI} STREQUAL "arm64-v8a")
|
| 51 |
build_library("whisper_v8fp16_va")
|
|
@@ -53,4 +75,6 @@ elseif (${ANDROID_ABI} STREQUAL "armeabi-v7a")
|
|
| 53 |
build_library("whisper_vfpv4")
|
| 54 |
endif ()
|
| 55 |
|
|
|
|
|
|
|
| 56 |
include_directories(${WHISPER_LIB_DIR})
|
|
|
|
| 3 |
project(whisper.cpp)
|
| 4 |
|
| 5 |
set(CMAKE_CXX_STANDARD 11)
|
| 6 |
+
set(WHISPER_LIB_DIR ${CMAKE_SOURCE_DIR}/../../../../../../..)
|
| 7 |
+
|
| 8 |
+
# Path to external GGML, otherwise uses the copy in whisper.cpp.
|
| 9 |
+
option(GGML_HOME "whisper: Path to external GGML source" OFF)
|
| 10 |
|
| 11 |
set(
|
| 12 |
SOURCE_FILES
|
| 13 |
+
${WHISPER_LIB_DIR}/whisper.cpp
|
| 14 |
+
${CMAKE_SOURCE_DIR}/jni.c
|
| 15 |
+
)
|
| 16 |
+
|
| 17 |
+
if (NOT GGML_HOME)
|
| 18 |
+
set(
|
| 19 |
+
SOURCE_FILES
|
| 20 |
+
${SOURCE_FILES}
|
| 21 |
${WHISPER_LIB_DIR}/ggml.c
|
| 22 |
${WHISPER_LIB_DIR}/ggml-alloc.c
|
| 23 |
${WHISPER_LIB_DIR}/ggml-backend.c
|
| 24 |
${WHISPER_LIB_DIR}/ggml-quants.c
|
| 25 |
+
|
| 26 |
+
)
|
| 27 |
+
endif()
|
| 28 |
|
| 29 |
find_library(LOG_LIB log)
|
| 30 |
|
|
|
|
| 35 |
${SOURCE_FILES}
|
| 36 |
)
|
| 37 |
|
|
|
|
|
|
|
| 38 |
if (${target_name} STREQUAL "whisper_v8fp16_va")
|
| 39 |
target_compile_options(${target_name} PRIVATE -march=armv8.2-a+fp16)
|
| 40 |
+
set(GGML_COMPILE_OPTIONS -march=armv8.2-a+fp16)
|
| 41 |
elseif (${target_name} STREQUAL "whisper_vfpv4")
|
| 42 |
target_compile_options(${target_name} PRIVATE -mfpu=neon-vfpv4)
|
| 43 |
+
set(GGML_COMPILE_OPTIONS -mfpu=neon-vfpv4)
|
| 44 |
endif ()
|
| 45 |
|
| 46 |
if (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
|
|
|
| 54 |
target_link_options(${target_name} PRIVATE -flto)
|
| 55 |
|
| 56 |
endif ()
|
|
|
|
| 57 |
|
| 58 |
+
if (GGML_HOME)
|
| 59 |
+
include(FetchContent)
|
| 60 |
+
FetchContent_Declare(ggml SOURCE_DIR ${GGML_HOME})
|
| 61 |
+
FetchContent_MakeAvailable(ggml)
|
| 62 |
+
|
| 63 |
+
target_compile_options(ggml PRIVATE ${GGML_COMPILE_OPTIONS})
|
| 64 |
+
target_link_libraries(${target_name} ${LOG_LIB} android ggml)
|
| 65 |
+
else()
|
| 66 |
+
target_link_libraries(${target_name} ${LOG_LIB} android)
|
| 67 |
+
endif()
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
endfunction()
|
| 71 |
|
| 72 |
if (${ANDROID_ABI} STREQUAL "arm64-v8a")
|
| 73 |
build_library("whisper_v8fp16_va")
|
|
|
|
| 75 |
build_library("whisper_vfpv4")
|
| 76 |
endif ()
|
| 77 |
|
| 78 |
+
build_library("whisper") # Default target
|
| 79 |
+
|
| 80 |
include_directories(${WHISPER_LIB_DIR})
|