From a7d35d51dcf59d372a07f89a7b7b539902a2732a Mon Sep 17 00:00:00 2001 From: mb8565 Date: Wed, 24 Jun 2026 01:57:19 -0500 Subject: [PATCH] eval-callback : sum over the full tensor, not just the printed slice (#2019) ggml_print_tensor() accumulated `sum` inside the truncated print loop, which skips the middle of each row when ne[0] > 2*n (n = 3). The printed `sum =` therefore only covered the first n and last n elements per row, not the whole tensor. For example a {2688, 5} tensor reported the sum of 30 of its 13440 values. That makes the value useless for numerically comparing two runs, and it disagrees with mainline llama.cpp, whose eval-callback sums every element in a separate pass. This factors the per-element read into a small helper and computes the sum in its own loop over all elements (double accumulator). The truncated print is a separate, unchanged pass, so only the printed `sum =` value changes. The change is confined to examples/eval-callback. Co-authored-by: mb8565 <244351746+mb8565@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 --- examples/eval-callback/eval-callback.cpp | 50 +++++++++++++++--------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/examples/eval-callback/eval-callback.cpp b/examples/eval-callback/eval-callback.cpp index ecdae627..bfdd5713 100644 --- a/examples/eval-callback/eval-callback.cpp +++ b/examples/eval-callback/eval-callback.cpp @@ -27,9 +27,38 @@ static std::string ggml_ne_string(const ggml_tensor * t) { return str; } +static float ggml_get_float_value(const uint8_t * data, ggml_type type, size_t i) { + if (type == GGML_TYPE_F16) { + return ggml_fp16_to_fp32(*(const ggml_fp16_t *) &data[i]); + } else if (type == GGML_TYPE_F32) { + return *(const float *) &data[i]; + } else if (type == GGML_TYPE_I32) { + return (float) *(const int32_t *) &data[i]; + } else if (type == GGML_TYPE_I16) { + return (float) *(const int16_t *) &data[i]; + } else if (type == GGML_TYPE_I8) { + return (float) *(const int8_t *) &data[i]; + } else { + GGML_ABORT("fatal error"); + } +} + static void ggml_print_tensor(uint8_t * data, ggml_type type, const int64_t * ne, const size_t * nb, int64_t n) { GGML_ASSERT(n > 0); - float sum = 0; + // Compute the FULL tensor sum first (debug aid — was previously summing + // only the displayed first/last elements, which made it useless for + // comparing two binaries on the same tensor). + double sum = 0.0; + for (int64_t i3 = 0; i3 < ne[3]; i3++) { + for (int64_t i2 = 0; i2 < ne[2]; i2++) { + for (int64_t i1 = 0; i1 < ne[1]; i1++) { + for (int64_t i0 = 0; i0 < ne[0]; i0++) { + size_t i = i3 * nb[3] + i2 * nb[2] + i1 * nb[1] + i0 * nb[0]; + sum += ggml_get_float_value(data, type, i); + } + } + } + } for (int64_t i3 = 0; i3 < ne[3]; i3++) { printf(" [\n"); for (int64_t i2 = 0; i2 < ne[2]; i2++) { @@ -50,22 +79,7 @@ static void ggml_print_tensor(uint8_t * data, ggml_type type, const int64_t * ne i0 = ne[0] - n; } size_t i = i3 * nb[3] + i2 * nb[2] + i1 * nb[1] + i0 * nb[0]; - float v; - if (type == GGML_TYPE_F16) { - v = ggml_fp16_to_fp32(*(ggml_fp16_t *) &data[i]); - } else if (type == GGML_TYPE_F32) { - v = *(float *) &data[i]; - } else if (type == GGML_TYPE_I32) { - v = (float) *(int32_t *) &data[i]; - } else if (type == GGML_TYPE_I16) { - v = (float) *(int16_t *) &data[i]; - } else if (type == GGML_TYPE_I8) { - v = (float) *(int8_t *) &data[i]; - } else { - GGML_ABORT("fatal error"); - } - printf("%12.4f", v); - sum += v; + printf("%12.4f", ggml_get_float_value(data, type, i)); if (i0 < ne[0] - 1) printf(", "); } printf("],\n"); @@ -73,7 +87,7 @@ static void ggml_print_tensor(uint8_t * data, ggml_type type, const int64_t * ne printf(" ],\n"); } printf(" ]\n"); - printf(" sum = %f\n", sum); + printf(" sum = %f\n", (float) sum); } }