Skip to content

Commit 6216749

Browse files
committed
cann: add Ascend NPU support
1 parent 6739eb8 commit 6216749

26 files changed

+11146
-20
lines changed

ggml/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ set(GGML_PUBLIC_HEADERS
200200
include/ggml-backend.h
201201
"${GGML_HEADERS_CUDA}"
202202
"${GGML_HEADERS_METAL}"
203+
"${GGML_HEADERS_CANN}"
203204
"${GGML_HEADERS_EXTRA}")
204205

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

ggml/include/ggml-cann.h

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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+
23+
#pragma once
24+
25+
#include "ggml-backend.h"
26+
#include "ggml.h"
27+
28+
#ifdef __cplusplus
29+
extern "C" {
30+
#endif
31+
32+
/**
33+
* @brief Maximum number of CANN devices supported.
34+
*/
35+
#define GGML_CANN_MAX_DEVICES 16
36+
37+
/**
38+
* @brief Initializes the CANN backend for a specified device.
39+
*
40+
* This function initializes the CANN backend for the given device.
41+
* It verifies the device index, allocates a context, and creates a backend
42+
* instance.
43+
*
44+
* @param device The index of the device to initialize.
45+
* @return A pointer to the initialized backend instance, or nullptr on failure.
46+
*/
47+
GGML_API GGML_CALL ggml_backend_t ggml_backend_cann_init(int32_t device);
48+
49+
/**
50+
* @brief Checks if a given backend is a CANN backend.
51+
*
52+
* This function verifies if the provided backend is a CANN backend by comparing
53+
* its GUID with the CANN backend's GUID.
54+
*
55+
* @param backend The backend instance to check.
56+
* @return True if the backend is a CANN backend, false otherwise.
57+
*/
58+
GGML_API GGML_CALL bool ggml_backend_is_cann(ggml_backend_t backend);
59+
60+
/**
61+
* @brief Retrieves the CANN buffer type for a specified device.
62+
*
63+
* This function initializes and returns the buffer type interface associated
64+
* with the given device. It ensures thread-safe access using a mutex.
65+
*
66+
* @param device The device index for which to retrieve the buffer type.
67+
* @return A pointer to the buffer type interface for the specified device, or
68+
* nullptr if the device index is out of range.
69+
*/
70+
GGML_API GGML_CALL ggml_backend_buffer_type_t
71+
ggml_backend_cann_buffer_type(int32_t device);
72+
73+
/**
74+
* @brief Retrieves the number of CANN devices available.
75+
*
76+
* This function returns the number of CANN devices available based on
77+
* information obtained from `ggml_cann_info()`.
78+
*
79+
* @return The number of CANN devices available.
80+
*/
81+
GGML_API GGML_CALL int32_t ggml_backend_cann_get_device_count(void);
82+
83+
/**
84+
* @brief Retrieves the description of a specific CANN device.
85+
*
86+
* This function sets the specified device, retrieves the SoC name,
87+
* and writes it into the provided description buffer.
88+
*
89+
* @param device The device index to retrieve the description for.
90+
* @param description Pointer to a buffer where the description will be written.
91+
* @param description_size Size of the description buffer.
92+
*/
93+
GGML_API GGML_CALL void ggml_backend_cann_get_device_description(
94+
int32_t device, char* description, size_t description_size);
95+
96+
/**
97+
* @brief Retrieves the memory information of a specific CANN device.
98+
*
99+
* This function sets the specified device, retrieves the free and total
100+
* memory information of the specified type (ACL_HBM_MEM), and stores them
101+
* in the provided pointers.
102+
*
103+
* @param device The device index to retrieve memory information for.
104+
* @param free Pointer to a variable where the free memory size will be stored.
105+
* @param total Pointer to a variable where the total memory size will be
106+
* stored.
107+
*/
108+
GGML_API GGML_CALL void ggml_backend_cann_get_device_memory(int32_t device,
109+
size_t* free,
110+
size_t* total);
111+
112+
/**
113+
* @brief Set the logging callback for GGML.
114+
*
115+
* This function sets the logging callback and user data for logging.
116+
*
117+
* @param log_callback The logging callback to set.
118+
* @param user_data User data to pass to the logging callback.
119+
*/
120+
GGML_API void ggml_backend_cann_log_set_callback(ggml_log_callback log_callback,
121+
void* user_data);
122+
123+
#ifdef __cplusplus
124+
}
125+
#endif

ggml/include/ggml.h

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -254,18 +254,11 @@
254254

255255
#define GGML_PAD(x, n) (((x) + (n) - 1) & ~((n) - 1))
256256

257-
#define GGML_ASSERT(x) \
258-
do { \
259-
if (!(x)) { \
260-
fflush(stdout); \
261-
fprintf(stderr, "GGML_ASSERT: %s:%d: %s\n", __FILE__, __LINE__, #x); \
262-
ggml_print_backtrace(); \
263-
abort(); \
264-
} \
265-
} while (0)
257+
#define GGML_ABORT(...) ggml_abort(__FILE__, __LINE__, __VA_ARGS__)
258+
#define GGML_ASSERT(x) if (!(x)) GGML_ABORT("GGML_ASSERT(%s) failed", #x)
266259

267260
#ifndef NDEBUG
268-
#define GGML_UNREACHABLE() GGML_ASSERT(!"statement should not be reached")
261+
#define GGML_UNREACHABLE() do { fprintf(stderr, "statement should be unreachable\n"); abort(); } while(0)
269262
#elif defined(__GNUC__)
270263
#define GGML_UNREACHABLE() __builtin_unreachable()
271264
#elif defined(_MSC_VER)
@@ -322,6 +315,7 @@
322315
extern "C" {
323316
#endif
324317

318+
GGML_API void ggml_abort(const char * file, int line, const char * fmt, ...);
325319
enum ggml_status {
326320
GGML_STATUS_ALLOC_FAILED = -2,
327321
GGML_STATUS_FAILED = -1,
@@ -746,6 +740,7 @@ extern "C" {
746740

747741
GGML_API bool ggml_are_same_shape (const struct ggml_tensor * t0, const struct ggml_tensor * t1);
748742
GGML_API bool ggml_are_same_stride(const struct ggml_tensor * t0, const struct ggml_tensor * t1);
743+
GGML_API bool ggml_can_repeat(const struct ggml_tensor * t0, const struct ggml_tensor * t1);
749744

750745
// use this to compute the memory overhead of a tensor
751746
GGML_API size_t ggml_tensor_overhead(void);
@@ -2391,6 +2386,7 @@ extern "C" {
23912386
GGML_API int ggml_cpu_has_rpc (void);
23922387
GGML_API int ggml_cpu_has_vsx (void);
23932388
GGML_API int ggml_cpu_has_matmul_int8(void);
2389+
GGML_API int ggml_cpu_has_cann (void);
23942390

23952391
//
23962392
// Internal types and functions exposed for tests and benchmarks

ggml/src/CMakeLists.txt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,70 @@ if (GGML_CPU_HBM)
739739
target_link_libraries(ggml PUBLIC memkind)
740740
endif()
741741
742+
if (GGML_CANN)
743+
if ("cann${CANN_INSTALL_DIR}" STREQUAL "cann" AND DEFINED ENV{ASCEND_TOOLKIT_HOME})
744+
set(CANN_INSTALL_DIR $ENV{ASCEND_TOOLKIT_HOME})
745+
message(STATUS "CANN: updated CANN_INSTALL_DIR from ASCEND_TOOLKIT_HOME=$ENV{ASCEND_TOOLKIT_HOME}")
746+
endif()
747+
748+
if (CANN_INSTALL_DIR)
749+
# Only Support Linux.
750+
if (GGML_CANN)
751+
if (NOT UNIX)
752+
set(GGML_CANN OFF)
753+
message(WARNING "CANN: CANN toolkit supports unix but not ${CMAKE_SYSTEM_NAME}. Turning off GGML_CANN")
754+
endif()
755+
endif()
756+
757+
# Supported platforms: x86-64, arm64
758+
if (GGML_CANN)
759+
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
760+
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
761+
else()
762+
set(GGML_CANN OFF)
763+
message(WARNING "CANN: CANN toolkit supports x86-64 and arm64 but not ${CMAKE_SYSTEM_PROCESSOR}. Turning off GGML_CANN")
764+
endif()
765+
endif()
766+
767+
# Set header and libs
768+
if(GGML_CANN)
769+
set(CANN_INCLUDE_DIRS
770+
${CANN_INSTALL_DIR}/include
771+
${CANN_INSTALL_DIR}/include/aclnn
772+
${CANN_INSTALL_DIR}/acllib/include
773+
)
774+
775+
add_subdirectory(ggml-cann/kernels)
776+
list(APPEND CANN_LIBRARIES
777+
ascendcl
778+
nnopbase
779+
opapi
780+
acl_op_compiler
781+
ascendc_kernels
782+
)
783+
784+
set(GGML_HEADERS_CANN "../include/ggml-cann.h")
785+
file(GLOB GGML_SOURCES_CANN "ggml-cann/*.cpp")
786+
list(APPEND GGML_SOURCES_CANN "ggml-cann.cpp")
787+
788+
message(STATUS "CANN: CANN_INCLUDE_DIRS = ${CANN_INCLUDE_DIRS}")
789+
message(STATUS "CANN: CANN_LIBRARIES = ${CANN_LIBRARIES}")
790+
791+
set(GGML_EXTRA_LIBS ${GGML_EXTRA_LIBS} ${CANN_LIBRARIES} )
792+
set(GGML_EXTRA_INCLUDES ${GGML_EXTRA_INCLUDES} ${CANN_INCLUDE_DIRS})
793+
set(GGML_EXTRA_LIBDIRS ${GGML_EXTRA_LIBDIRS} ${CANN_INSTALL_DIR}/lib64)
794+
list(APPEND GGML_CDEF_PUBLIC GGML_USE_CANN)
795+
endif()
796+
else()
797+
set(GGML_CANN OFF)
798+
message(WARNING "CANN: Can't find CANN_INSTALL_DIR, do you forget to source set_var.sh. Turning off GGML_CANN")
799+
endif()
800+
801+
if(NOT GGML_CANN)
802+
message(WARNING "CANN: GGML_CANN is turned OFF, see above for details.")
803+
endif()
804+
endif()
805+
742806
function(get_flags CCID CCVER)
743807
set(C_FLAGS "")
744808
set(CXX_FLAGS "")
@@ -1153,6 +1217,7 @@ add_library(ggml
11531217
${GGML_SOURCES_ROCM} ${GGML_HEADERS_ROCM}
11541218
${GGML_SOURCES_BLAS} ${GGML_HEADERS_BLAS}
11551219
${GGML_SOURCES_LLAMAFILE} ${GGML_HEADERS_LLAMAFILE}
1220+
${GGML_SOURCES_CANN} ${GGML_HEADERS_CANN}
11561221
)
11571222

11581223
if (EMSCRIPTEN)

ggml/src/ggml-backend.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,11 @@ GGML_CALL static void ggml_backend_registry_init(void) {
445445
extern GGML_CALL void ggml_backend_kompute_reg_devices(void);
446446
ggml_backend_kompute_reg_devices();
447447
#endif
448+
449+
#ifdef GGML_USE_CANN
450+
extern GGML_CALL int ggml_backend_cann_reg_devices(void);
451+
ggml_backend_cann_reg_devices();
452+
#endif
448453
}
449454

450455
GGML_CALL void ggml_backend_register(const char * name, ggml_backend_init_fn init_fn, ggml_backend_buffer_type_t default_buffer_type, void * user_data) {

0 commit comments

Comments
 (0)