llama.cpp에서 NPU 실행하기 (Snapdragon / Hexagon HTP)
llama.cpp에서 NPU 실행하기 (Snapdragon / Hexagon HTP)
NPU 실행은 현재 최신 폰에서만 지원되는 것으로 보인다.
삼성/샤오미/화웨이 등 Snapdragon SoC를 탑재한 기기들 간의 호환성은 아직 확인되지 않았다.
따라서. 구형 휴대폰이나, 삼성 휴대폰의 경우 빌드는 정상적이지만 실행되지 않고 에러가 날 수 있다.
1. 들어가며
모바일 환경에서 LLM을 온디바이스(on-device) 로 실행하려면 CPU/GPU만으로는 한계가 명확하다. Qualcomm Snapdragon SoC에서는 Hexagon NPU (HTP) 를 통해 저전력·고효율 추론이 가능하고, llama.cpp는 이를 실험적으로 지원하고 있다. 이 글에서는 Docker 기반 크로스 빌드 환경에서 llama.cpp를 Android + Snapdragon NPU(HTP) 용으로 빌드하고, 실제 디바이스에서 실행하는 전체 과정을 정리한다.
2. Docker 세팅
Docker 환경은 이미 이전 게시글을 통해 완전히 준비되어 있다고 가정한다. 따라서 이 글에서는 Docker 설치, 이미지 다운로드, 플랫폼 설정 등에 대해서는 다루지 않는다.
최소 요구 RAM 용량은 12GB이다. 최소 RAM 8GB, Swap 4GB를 지정해주는 것을 추천한다.
Docker Desktop의 경우,Settings > Resources에서 설정 가능하다.
3. 빌드 준비
A. Repository clone
먼저 llama.cpp 저장소를 클론한다.
1
2
git clone https://github.com/ggml-org/llama.cpp.git
cd llama.cpp
B. Docker container 실행
Snapdragon Android 크로스 컴파일이 가능한 Docker 컨테이너를 실행한다. (이미 되어 있다면, 스킵하자.)
1
2
3
4
5
6
7
docker run -it --rm \
-u $(id -u):$(id -g) \
-v $(pwd):/workspace \
-w /workspace \
--platform linux/amd64 \
ghcr.io/snapdragon-toolchain/arm64-android:v0.3 \
bash
컨테이너 안에서는 이미 다음이 준비되어 있다.
- Android NDK
- Qualcomm Hexagon SDK
- OpenCL
- 필요한 CMake / Toolchain 설정
4. 빌드
A. CMake 프리셋 준비
Hexagon(NPU) 백엔드는 전용 CMake 프리셋을 사용한다. 먼저 프리셋 파일을 루트 디렉토리로 복사한다.
1
cp docs/backend/hexagon/CMakeUserPresets.json .
이 프리셋에는 다음이 포함되어 있다.
- Android arm64 타겟
- Snapdragon SoC용 컴파일 옵션
- Hexagon HTP 런타임 연동 설정
B. 빌드 환경 세팅
Snapdragon Android용 release 프리셋을 사용해 빌드 디렉토리를 생성한다.
1
cmake --preset arm64-android-snapdragon-release -B build-snapdragon
이 단계에서 수행되는 핵심 작업은 다음과 같다.
- Android NDK toolchain 적용
- Hexagon SDK 경로 연결
- ggml-hexagon 백엔드 활성화
C. 패키지 빌드
1
cmake --build build-snapdragon
이 단계에서 다음 바이너리들이 생성된다.
llama-completionllama-cli- Hexagon 관련 .so 라이브러리
D. 패키지 링킹 및 병합
ADB로 바로 전송 가능한 패키지 형태로 정리한다.
1
cmake --install build-snapdragon --prefix pkg-adb/llama.cpp
결과 디렉토리 구조는 대략 다음과 같다.
1
2
3
4
pkg-adb/llama.cpp/
├── bin/
├── lib/
└── scripts/
5. 실행
A. 모델 다운로드
실행 테스트용 GGUF 모델을 다운로드한다.
1
2
mkdir -p gguf
curl -L https://huggingface.co/bartowski/Llama-3.2-1B-Instruct-GGUF/resolve/main/Llama-3.2-1B-Instruct-Q4_0.gguf -o gguf/Llama-3.2-1B-Instruct-Q4_0.gguf
Q4 양자화 모델은 NPU 실험용으로 크기·성능 균형이 좋다.
B. 패키지 및 모델 전송
ADB를 통해 디바이스로 전송한다.
1
2
3
adb shell "mkdir /data/local/tmp/gguf"
adb push pkg-adb/llama.cpp /data/local/tmp/
adb push Llama-3.2-1B-Instruct-Q4_0.gguf /data/local/tmp/gguf
C. NPU(HTP)로 실행
Hexagon NPU를 명시적으로 지정해 실행한다.
1
2
3
4
M=Llama-3.2-1B-Instruct-Q4_0.gguf \
D=HTP0 \
./scripts/snapdragon/adb/run-completion.sh \
-p "what is the most popular cookie in the world?"
여기서 중요한 환경 변수는 다음과 같다.
D=HTP0→ Hexagon HTP(NPU) 디바이스 사용M=...gguf→ 사용할 GGUF 모델 지정
정상적으로 실행되면 로그에 다음과 같은 문구를 확인할 수 있다.
1
2
ggml_opencl: selected platform: 'QUALCOMM Snapdragon(TM)'
ggml_hexagon: using HTP backend
D. Tip
만약 폰이 루팅되어 있고, 실행이 되지 않는다면, su를 사용해볼 수 있다.
1
vim scripts/snapdragon/adb/run-cli.sh
해당 파일의 제일 아래 부분을 아래의 코드처럼 써주자. 변경된 내용은 su 추가이다.
1
2
3
4
5
6
7
8
9
10
adb $adbserial $adbhost su -c " shell \" \
cd $basedir; ulimit -c unlimited; \
LD_LIBRARY_PATH=$basedir/$branch/lib \
ADSP_LIBRARY_PATH=$basedir/$branch/lib \
$verbose $experimental $sched $opmask $profile $nhvx $ndev $hb \
./$branch/bin/llama-cli --no-mmap -m $basedir/../gguf/$model \
--poll 1000 -t 6 --cpu-mask 0xfc --cpu-strict 1 \
--ctx-size 8192 --batch-size 128 -fa on \
-ngl 99 --device $device $cli_opts $@ \
\""
끝.