Skip to content

Commit

Permalink
whisper.android : how to build with CLBlast (ggerganov#1809)
Browse files Browse the repository at this point in the history
* FetchContent

* OpenCL

* Documentation and make optional

* Specify GGML build options in build.gradle

* Use gradle properties

* @ggerganov

Co-authored-by: Georgi Gerganov <ggerganov@gmail.com>

* @gpokat

---------

Co-authored-by: Georgi Gerganov <ggerganov@gmail.com>
  • Loading branch information
2 people authored and iThalay committed Sep 23, 2024
1 parent c404b85 commit 697d3ba
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 8 deletions.
44 changes: 44 additions & 0 deletions examples/whisper.android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

22 changes: 22 additions & 0 deletions examples/whisper.android/lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
40 changes: 32 additions & 8 deletions examples/whisper.android/lib/src/main/jni/whisper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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")
Expand All @@ -43,14 +54,27 @@ 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")
elseif (${ANDROID_ABI} STREQUAL "armeabi-v7a")
build_library("whisper_vfpv4")
endif ()

build_library("whisper") # Default target

include_directories(${WHISPER_LIB_DIR})

0 comments on commit 697d3ba

Please sign in to comment.