From 4dd34ff83165a483ebff7bd43621b28490fa1fd6 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Sat, 18 Jan 2025 16:18:15 +0200 Subject: [PATCH] cmake : add sanitizer flags for llama.cpp (#11279) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * cmake : add sanitizer flags for llama.cpp ggml-ci * tests : fix compile warnings ggml-ci * cmake : move sanitizer flags to llama_add_compile_flags ggml-ci * cmake : move llama.cpp compile flags to top level lists ggml-ci * cmake : apply only sanitizer flags at top level ggml-ci * tests : fix gguf context use in same_tensor_data * gguf-test: tensor data comparison * dummy : trigger ggml-ci * unicode : silence gcc warnings ggml-ci * ci : use sanitizer builds only in Debug mode ggml-ci * cmake : add status messages [no ci] --------- Co-authored-by: Johannes Gäßler --- .github/workflows/build.yml | 2 +- CMakeLists.txt | 73 +++++++++++++++++++++++++------------ ggml/src/gguf.cpp | 4 ++ src/unicode.cpp | 5 +-- tests/CMakeLists.txt | 2 + tests/test-gguf.cpp | 28 ++++++++------ tests/test-sampling.cpp | 1 - 7 files changed, 74 insertions(+), 41 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c85999b89..9e0c4a675 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -234,7 +234,7 @@ jobs: strategy: matrix: sanitizer: [ADDRESS, THREAD, UNDEFINED] - build_type: [Debug, Release] + build_type: [Debug] steps: - name: Clone diff --git a/CMakeLists.txt b/CMakeLists.txt index a717a508f..42caed486 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,11 +83,8 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/build-info.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/common.cmake) # override ggml options -set(GGML_SANITIZE_THREAD ${LLAMA_SANITIZE_THREAD}) -set(GGML_SANITIZE_ADDRESS ${LLAMA_SANITIZE_ADDRESS}) -set(GGML_SANITIZE_UNDEFINED ${LLAMA_SANITIZE_UNDEFINED}) -set(GGML_ALL_WARNINGS ${LLAMA_ALL_WARNINGS}) -set(GGML_FATAL_WARNINGS ${LLAMA_FATAL_WARNINGS}) +set(GGML_ALL_WARNINGS ${LLAMA_ALL_WARNINGS}) +set(GGML_FATAL_WARNINGS ${LLAMA_FATAL_WARNINGS}) # change the default for these ggml options if (NOT DEFINED GGML_LLAMAFILE) @@ -117,16 +114,62 @@ llama_option_depr(WARNING LLAMA_SYCL GGML_SYCL) llama_option_depr(WARNING LLAMA_SYCL_F16 GGML_SYCL_F16) llama_option_depr(WARNING LLAMA_CANN GGML_CANN) +if (NOT MSVC) + if (LLAMA_SANITIZE_THREAD) + message(STATUS "Using -fsanitize=thread") + + add_compile_options(-fsanitize=thread) + link_libraries (-fsanitize=thread) + endif() + + if (LLAMA_SANITIZE_ADDRESS) + message(STATUS "Using -fsanitize=address") + + add_compile_options(-fsanitize=address -fno-omit-frame-pointer) + link_libraries (-fsanitize=address) + endif() + + if (LLAMA_SANITIZE_UNDEFINED) + message(STATUS "Using -fsanitize=undefined") + + add_compile_options(-fsanitize=undefined) + link_libraries (-fsanitize=undefined) + endif() +endif() + # -# build the library +# 3rd-party # if (NOT TARGET ggml) add_subdirectory(ggml) # ... otherwise assume ggml is added by a parent CMakeLists.txt endif() + +# +# build the library +# + add_subdirectory(src) +# +# utils, programs, examples and tests +# + +if (LLAMA_BUILD_COMMON) + add_subdirectory(common) +endif() + +if (LLAMA_BUILD_COMMON AND LLAMA_BUILD_TESTS AND NOT CMAKE_JS_VERSION) + include(CTest) + add_subdirectory(tests) +endif() + +if (LLAMA_BUILD_COMMON AND LLAMA_BUILD_EXAMPLES) + add_subdirectory(examples) + add_subdirectory(pocs) +endif() + # # install # @@ -200,21 +243,3 @@ configure_file(cmake/llama.pc.in install(FILES "${CMAKE_CURRENT_BINARY_DIR}/llama.pc" DESTINATION lib/pkgconfig) - -# -# utils, programs, examples and tests -# - -if (LLAMA_BUILD_COMMON) - add_subdirectory(common) -endif() - -if (LLAMA_BUILD_COMMON AND LLAMA_BUILD_TESTS AND NOT CMAKE_JS_VERSION) - include(CTest) - add_subdirectory(tests) -endif() - -if (LLAMA_BUILD_COMMON AND LLAMA_BUILD_EXAMPLES) - add_subdirectory(examples) - add_subdirectory(pocs) -endif() diff --git a/ggml/src/gguf.cpp b/ggml/src/gguf.cpp index 655ed600a..ab13669c5 100644 --- a/ggml/src/gguf.cpp +++ b/ggml/src/gguf.cpp @@ -648,6 +648,10 @@ struct gguf_context * gguf_init_from_file_impl(FILE * file, struct gguf_init_par ok = ok && data != nullptr; + if (ok) { + ggml_set_name(data, "GGUF tensor data binary blob"); + } + // read the binary blob with the tensor data ok = ok && gr.read(data->data, ctx->size); diff --git a/src/unicode.cpp b/src/unicode.cpp index 7aca6544b..89180da41 100644 --- a/src/unicode.cpp +++ b/src/unicode.cpp @@ -7,18 +7,17 @@ #include #include +#include #include #include +#include #include #include #include #include #include -#include #include #include -#include -#include size_t unicode_len_utf8(char src) { const size_t lookup[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4 }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2b5e5fd4a..3fa43c295 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,3 +1,5 @@ +llama_add_compile_flags() + function(llama_test target) include(CMakeParseArguments) set(options) diff --git a/tests/test-gguf.cpp b/tests/test-gguf.cpp index 611957ac0..6ed696328 100644 --- a/tests/test-gguf.cpp +++ b/tests/test-gguf.cpp @@ -48,7 +48,7 @@ enum handcrafted_file_type { HANDCRAFTED_DATA_CUSTOM_ALIGN = 810 + offset_has_data, }; -std::string handcrafted_file_type_name(const enum handcrafted_file_type hft) { +static std::string handcrafted_file_type_name(const enum handcrafted_file_type hft) { switch (hft) { case HANDCRAFTED_HEADER_BAD_MAGIC: return "HEADER_BAD_MAGIC"; case HANDCRAFTED_HEADER_BAD_VERSION_1: return "HEADER_BAD_VERSION_1"; @@ -99,7 +99,7 @@ static bool expect_context_not_null(const enum handcrafted_file_type hft) { typedef std::pair> tensor_config_t; -std::vector get_tensor_configs(std::mt19937 & rng) { +static std::vector get_tensor_configs(std::mt19937 & rng) { std::vector tensor_configs; tensor_configs.reserve(100); @@ -122,7 +122,7 @@ std::vector get_tensor_configs(std::mt19937 & rng) { return tensor_configs; } -std::vector> get_kv_types(std::mt19937 rng) { +static std::vector> get_kv_types(std::mt19937 rng) { std::vector> kv_types; kv_types.reserve(100); @@ -626,8 +626,6 @@ static bool handcrafted_check_tensor_data(const gguf_context * gguf_ctx, const u bool ok = true; - const uint32_t alignment = GGUF_DEFAULT_ALIGNMENT; - for (int i = 0; i < int(tensor_configs.size()); ++i) { const ggml_type type = tensor_configs[i].first; const std::array shape = tensor_configs[i].second; @@ -866,13 +864,13 @@ static struct random_gguf_context_result get_random_gguf_context(ggml_backend_t case GGUF_TYPE_COUNT: default: { GGML_ABORT("fatal error"); - } break; + } } } break; case GGUF_TYPE_COUNT: default: { GGML_ABORT("fatal error"); - } break; + } } } @@ -938,7 +936,7 @@ static bool all_kv_in_other(const gguf_context * ctx, const gguf_context * other } if (type == GGUF_TYPE_ARRAY) { - const int arr_n = gguf_get_arr_n(ctx, id); + const size_t arr_n = gguf_get_arr_n(ctx, id); if (arr_n != gguf_get_arr_n(other, idx_other)) { ok = false; continue; @@ -953,7 +951,7 @@ static bool all_kv_in_other(const gguf_context * ctx, const gguf_context * other if (type_arr == GGUF_TYPE_BOOL) { const int8_t * data = reinterpret_cast(gguf_get_arr_data(ctx, id)); const int8_t * data_other = reinterpret_cast(gguf_get_arr_data(other, idx_other)); - for (int arr_i = 0; arr_i < arr_n; ++arr_i) { + for (size_t arr_i = 0; arr_i < arr_n; ++arr_i) { if (bool(data[arr_i]) != bool(data_other[arr_i])) { ok = false; } @@ -962,7 +960,7 @@ static bool all_kv_in_other(const gguf_context * ctx, const gguf_context * other } if (type_arr == GGUF_TYPE_STRING) { - for (int arr_i = 0; arr_i < arr_n; ++arr_i) { + for (size_t arr_i = 0; arr_i < arr_n; ++arr_i) { const std::string str = gguf_get_arr_str(ctx, id, arr_i); const std::string str_other = gguf_get_arr_str(other, idx_other, arr_i); if (str != str_other) { @@ -1033,6 +1031,12 @@ static bool same_tensor_data(const struct ggml_context * orig, const struct ggml struct ggml_tensor * t_orig = ggml_get_first_tensor(orig); struct ggml_tensor * t_read = ggml_get_first_tensor(read); + + if (std::string(t_read->name) != "GGUF tensor data binary blob") { + return false; + } + t_read = ggml_get_next_tensor(read, t_read); + while (t_orig) { if (!t_read) { ok = false; @@ -1051,13 +1055,13 @@ static bool same_tensor_data(const struct ggml_context * orig, const struct ggml } t_orig = ggml_get_next_tensor(orig, t_orig); - t_read = ggml_get_next_tensor(orig, t_read); + t_read = ggml_get_next_tensor(read, t_read); } if (t_read) { ok = false; } - return true; + return ok; } static std::pair test_roundtrip(ggml_backend_dev_t dev, const unsigned int seed, const bool only_meta) { diff --git a/tests/test-sampling.cpp b/tests/test-sampling.cpp index c0dcb4848..61bd67850 100644 --- a/tests/test-sampling.cpp +++ b/tests/test-sampling.cpp @@ -144,7 +144,6 @@ static void test_penalties( sampler_tester tester(probs, probs_expected); - const size_t n_vocab = probs.size(); auto * sampler = llama_sampler_init_penalties(last_tokens.size(), repeat_penalty, alpha_frequency, alpha_presence); for (size_t i = 0; i < last_tokens.size(); i++) {