... views
随着大语言模型(LLM)在移动设备上的应用需求日益增长,如何在Android设备上高效运行这些模型成为了开发者关注的焦点。本文将详细介绍如何在搭载高通骁龙芯片的Android设备上,通过OpenCL技术在Adreno GPU上运行llama.cpp,实现高性能的大语言模型推理。
OpenCL(开放计算语言)是由Khronos Group开发的广泛采用的行业标准,它允许开发者编写高效且可移植的并行编程代码,可在CPU、GPU、NPU、FPGA等各种设备上运行,而无需深入了解这些设备的具体实现细节。OpenCL在GPU上的应用特别强大,使开发者能够充分利用现代GPU的并行计算能力,应用于图像/视频/视觉信号处理以及卷积神经网络(CNN)和大语言模型(LLM)等AI工作负载。
作为Khronos Group中OpenCL工作组的重要成员,高通技术公司积极参与OpenCL标准化工作。作为移动GPU上OpenCL标准的早期采用者之一,高通在各种SoC设备上支持OpenCL,包括:
高通还提供了全面的工具集(Snapdragon Profiler)、OpenCL SDK示例和OpenCL编程指南,帮助开发者在Adreno GPU上开始使用OpenCL。
性能提升:新的后端显著提升了llama.cpp在Adreno GPU上的性能,实现更快的计算和更高效的处理。
更广泛的兼容性:该后端针对Adreno GPU进行了高度优化,同时也可在所有支持OpenCL 3.0标准(带子组支持)的GPU上运行,确保更广泛的兼容性和可访问性。
经过严格测试,以下大语言模型已确认在llama.cpp OpenCL后端上表现良好:
该后端已在多款搭载骁龙SoC的高端设备上进行测试:
在开始构建之前,您需要准备以下软件和硬件环境:
软件要求:
硬件要求:
首先,我们需要安装Android NDK。以下是install-ndk.sh
脚本的内容:
cd ~
wget https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip && \
unzip commandlinetools-linux-8512546_latest.zip && \
mkdir -p ~/android-sdk/cmdline-tools && \
mv cmdline-tools latest && \
mv latest ~/android-sdk/cmdline-tools/ && \
rm -rf commandlinetools-linux-8512546_latest.zip
yes | ~/android-sdk/cmdline-tools/latest/bin/sdkmanager "ndk;26.3.11579264"
这个脚本执行以下操作:
由于NDK发行版中没有直接提供运行OpenCL所需的文件,我们需要从官方Khronos OpenCL仓库下载OpenCL头文件和ICD加载器。install-opencl.sh
脚本完成这个任务:
mkdir -p ~/dev/llm
cd ~/dev/llm
# 下载并安装OpenCL头文件
git clone https://github.com/KhronosGroup/OpenCL-Headers
cd OpenCL-Headers
cp -r CL ~/android-sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include
cd ~/dev/llm
# 下载并构建OpenCL ICD加载器
git clone https://github.com/KhronosGroup/OpenCL-ICD-Loader
cd OpenCL-ICD-Loader
# 修复缺失的stdlib.h包含
sed -i '/#include <unistd.h>/a #include <stdlib.h>' loader/linux/icd_linux_envvars.c
mkdir -p build_ndk26
cd build_ndk26
# 设置编译器标志以处理Android NDK问题
export CFLAGS="-D_Nonnull= -D_Nullable= -D__BIONIC_COMPLICATED_NULLNESS= -D__INTRODUCED_IN= -D__BIONIC_AVAILABILITY= -D__BIONIC_FORTIFY_INLINE= -D__BIONIC_FORTIFY_VARIADIC= -Wno-nullability-completeness -Wno-availability -Wno-attributes -Wno-builtin-declaration-mismatch -Wno-implicit-function-declaration -Wno-int-conversion"
export CXXFLAGS="-D_Nonnull= -D_Nullable= -D__BIONIC_COMPLICATED_NULLNESS= -D__INTRODUCED_IN= -D__BIONIC_AVAILABILITY= -D__BIONIC_FORTIFY_INLINE= -D__BIONIC_FORTIFY_VARIADIC= -Wno-nullability-completeness -Wno-availability -Wno-attributes -Wno-builtin-declaration-mismatch -Wno-implicit-function-declaration -Wno-int-conversion"
# 使用CMake配置构建
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=$HOME/android-sdk/ndk/26.3.11579264/build/cmake/android.toolchain.cmake \
-DOPENCL_ICD_LOADER_HEADERS_DIR=$HOME/android-sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=24 \
-DANDROID_STL=c++_shared \
-DCMAKE_C_FLAGS="${CFLAGS}" \
-DCMAKE_CXX_FLAGS="${CXXFLAGS}"
ninja
cp libOpenCL.so ~/android-sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android
这个脚本的关键步骤包括:
最后,使用build-llamacpp.sh
脚本构建带有Adreno OpenCL后端的llama.cpp:
#!/bin/bash
# 设置错误时退出
set -e
# 清理环境变量,避免干扰
unset CC CXX
# 设置 Android NDK 路径
export ANDROID_NDK_ROOT=$HOME/android-sdk/ndk/26.3.11579264
export NDK_ROOT=$ANDROID_NDK_ROOT
# 检查 NDK 是否存在
if [ ! -d "$ANDROID_NDK_ROOT" ]; then
echo "Error: Android NDK not found at $ANDROID_NDK_ROOT"
echo "Please make sure Android NDK is installed correctly"
exit 1
fi
cd ~/dev/llm
# git clone https://github.com/ggerganov/llama.cpp && \
cd llama.cpp
# 完全清理构建目录
rm -rf build-android
mkdir -p build-android && cd build-android
# 配置 CMake,明确指定交叉编译
cmake .. \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake \
-DCMAKE_SYSTEM_NAME=Android \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-28 \
-DANDROID_NDK=$ANDROID_NDK_ROOT \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=OFF \
-DGGML_OPENCL=ON \
-DLLAMA_CURL=OFF \
-DCMAKE_MAKE_PROGRAM=ninja
# 构建
ninja
# 验证编译结果
echo "Build completed. Checking binary architecture..."
if [ -f "bin/llama-cli" ]; then
echo "Architecture check for llama-cli:"
file bin/llama-cli
readelf -h bin/llama-cli | grep Machine
else
echo "Warning: llama-cli binary not found"
fi
构建配置说明:
确认是AArch64平台二进制产物
(base) ➜ do@do ~/dev/llm/llama.cpp/build-android/bin git:(master) readelf -h ./llama-cli
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Position-Independent Executable file)
Machine: AArch64
Version: 0x1
adb logcat
查看Android设备上的运行时日志