Skip to content

Commit 74029f3

Browse files
committed
ggml-qnn: add Qualcomm QNN backend for GGML
1 parent 6dde178 commit 74029f3

File tree

8 files changed

+4250
-0
lines changed

8 files changed

+4250
-0
lines changed

ggml/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ option(GGML_OPENCL "ggml: use OpenCL"
187187
option(GGML_OPENCL_PROFILING "ggml: use OpenCL profiling (increases overhead)" OFF)
188188
option(GGML_OPENCL_EMBED_KERNELS "ggml: embed kernels" ON)
189189
option(GGML_OPENCL_USE_ADRENO_KERNELS "ggml: use optimized kernels for Adreno" ON)
190+
option(GGML_QNN "ggml: use QNN" ON)
190191

191192
# toolchain for vulkan-shaders-gen
192193
set (GGML_VULKAN_SHADERS_GEN_TOOLCHAIN "" CACHE FILEPATH "ggml: toolchain file for vulkan-shaders-gen")
@@ -250,6 +251,7 @@ set(GGML_PUBLIC_HEADERS
250251
include/ggml-rpc.h
251252
include/ggml-sycl.h
252253
include/ggml-vulkan.h
254+
include/ggml-qnn.h
253255
include/gguf.h)
254256

255257
set_target_properties(ggml PROPERTIES PUBLIC_HEADER "${GGML_PUBLIC_HEADERS}")

ggml/include/ggml-qnn.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright (c) 2023-2024 The ggml authors
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to
6+
* deal in the Software without restriction, including without limitation the
7+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8+
* sell copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20+
* IN THE SOFTWARE.
21+
*/
22+
#pragma once
23+
24+
#include "ggml.h"
25+
#include "ggml-backend.h"
26+
27+
#ifdef __cplusplus
28+
extern "C" {
29+
#endif
30+
31+
#define GGML_QNN_MAX_DEVICES 3
32+
#define GGML_QNN_BACKEND_NAME "qnn"
33+
34+
enum QNNBackend {
35+
QNN_BACKEND_CPU,
36+
QNN_BACKEND_GPU,
37+
QNN_BACKEND_NPU,
38+
QNN_BACKEND_GGML, //"fake" QNN backend for compare performance between QNN backend and cpu backend
39+
};
40+
41+
GGML_BACKEND_API ggml_backend_t ggml_backend_qnn_init(size_t dev_num, const char * qnn_lib_path);
42+
43+
GGML_BACKEND_API bool ggml_backend_is_qnn(ggml_backend_t backend);
44+
45+
GGML_BACKEND_API void ggml_backend_qnn_set_n_threads(ggml_backend_t backend, int thread_counts);
46+
47+
GGML_BACKEND_API int ggml_backend_qnn_get_device_count(void);
48+
49+
GGML_BACKEND_API ggml_backend_reg_t ggml_backend_qnn_reg(void);
50+
51+
inline const char * ggml_backend_qnn_get_devname(size_t dev_num) {
52+
switch (dev_num) {
53+
case QNN_BACKEND_CPU:
54+
return "QNN-CPU";
55+
case QNN_BACKEND_GPU:
56+
return "QNN-GPU";
57+
case QNN_BACKEND_NPU:
58+
return "QNN-NPU";
59+
case QNN_BACKEND_GGML:
60+
return "ggml"; //"fake" QNN backend, used for compare performance between QNN backend and original GGML
61+
default:
62+
return "unknown";
63+
}
64+
}
65+
66+
#ifdef __cplusplus
67+
}
68+
#endif

ggml/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ ggml_add_backend(RPC)
329329
ggml_add_backend(SYCL)
330330
ggml_add_backend(Vulkan)
331331
ggml_add_backend(OpenCL)
332+
ggml_add_backend(QNN)
332333

333334
foreach (target ggml-base ggml)
334335
target_include_directories(${target} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include> $<INSTALL_INTERFACE:include>)

ggml/src/ggml-backend-reg.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666
#include "ggml-kompute.h"
6767
#endif
6868

69+
#ifdef GGML_USE_QNN
70+
#include "ggml-qnn.h"
71+
#endif
72+
6973
// disable C++17 deprecation warning for std::codecvt_utf8
7074
#if defined(__clang__)
7175
# pragma clang diagnostic push
@@ -180,6 +184,9 @@ struct ggml_backend_registry {
180184
#ifdef GGML_USE_KOMPUTE
181185
register_backend(ggml_backend_kompute_reg());
182186
#endif
187+
#ifdef GGML_USE_QNN
188+
register_backend(ggml_backend_qnn_reg());
189+
#endif
183190
#ifdef GGML_USE_CPU
184191
register_backend(ggml_backend_cpu_reg());
185192
#endif
@@ -573,6 +580,7 @@ void ggml_backend_load_all_from_path(const char * dir_path) {
573580
ggml_backend_load_best("vulkan", silent, dir_path);
574581
ggml_backend_load_best("opencl", silent, dir_path);
575582
ggml_backend_load_best("musa", silent, dir_path);
583+
ggml_backend_load_best("qnn", silent, dir_path);
576584
ggml_backend_load_best("cpu", silent, dir_path);
577585
// check the environment variable GGML_BACKEND_PATH to load an out-of-tree backend
578586
const char * backend_path = std::getenv("GGML_BACKEND_PATH");

ggml/src/ggml-qnn/CMakeLists.txt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
message(STATUS "Using QNN backend")
2+
3+
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
4+
find_library(LOG_LIB log)
5+
set(QNN_LINK_LIBRARIES ${LOG_LIB})
6+
set(QNN_DEFAULT_LIB_SEARCH_PATH "/data/local/tmp/" CACHE STRING "customized library search path for QNN backend")
7+
else()
8+
message(FATAL_ERROR "QNN now only available on Android")
9+
endif()
10+
11+
if(NOT DEFINED GGML_QNN_SDK_PATH)
12+
# try read from environment variable
13+
if(DEFINED ENV{QNN_SDK_PATH})
14+
set(GGML_QNN_SDK_PATH $ENV{QNN_SDK_PATH})
15+
else()
16+
message(FATAL_ERROR "GGML_QNN_SDK_PATH not defined")
17+
endif()
18+
endif()
19+
20+
message("QNN_SDK_PATH: ${GGML_QNN_SDK_PATH}")
21+
22+
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
23+
24+
file(GLOB QNN_SOURCES "${CMAKE_CURRENT_LIST_DIR}/*.cpp")
25+
ggml_add_backend_library(ggml-qnn
26+
${QNN_SOURCES}
27+
)
28+
29+
target_include_directories(ggml-qnn PRIVATE ${GGML_QNN_SDK_PATH}/include/QNN ${CMAKE_CURRENT_LIST_DIR})
30+
target_link_libraries(ggml-qnn PRIVATE ${QNN_LINK_LIBRARIES})
31+
32+
string(REGEX REPLACE "/$" "" GGML_QNN_DEFAULT_LIB_SEARCH_PATH "${QNN_DEFAULT_LIB_SEARCH_PATH}")
33+
target_compile_definitions(ggml-qnn PRIVATE GGML_QNN_DEFAULT_LIB_SEARCH_PATH="${QNN_DEFAULT_LIB_SEARCH_PATH}/")

0 commit comments

Comments
 (0)