Commit 664c62f7 for whisper.cpp
commit 664c62f7a6668b511c280a58d35ccf3d71ebb637
Author: Daniel Müller <d-e-s-o@users.noreply.github.com>
Date: Tue Nov 10 00:39:35 2026 -0800
vitisai : route VitisAI backend logging through whisper's log callback (#4163)
The vitisai backend writes diagnostic messages directly to stderr,
bypassing whisper's logging infrastructure. What that amounts to is a
usability nightmare, because:
- whisper_log_set() may simply not be working depending on which backend
is in use
- verbosity control (log levels) are effectively not present
- client code has to juggle log message management along two axis, the
whisper_log_set() function and the WHISPER_DEBUG define, as well
between runtime and build time
With this change we start sharing the internal logging infrastructure
between backends. The vitisai backend is switched over to using
WHISPER_LOG_* macros, which allows for client-side control of verbosity.
Note that verbose init and timing messages at DEBUG are kept gated by
WHISPER_DEBUG. Other backends can follow the example if accepted.
Signed-off-by: Daniel Müller <deso@posteo.net>
diff --git a/src/vitisai/whisper-vitisai-encoder.cpp b/src/vitisai/whisper-vitisai-encoder.cpp
index 707f876f..a6d8f1b0 100644
--- a/src/vitisai/whisper-vitisai-encoder.cpp
+++ b/src/vitisai/whisper-vitisai-encoder.cpp
@@ -8,8 +8,8 @@
#include "vitisai/whisper-vitisai-helpers.h"
#include "FlexMLClient.h"
#include "ggml.h"
+#include "whisper-logging.h"
-#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <memory>
@@ -65,7 +65,7 @@ static bool whisper_vitisai_get_cached_io_tensors(
struct whisper_vitisai_context * whisper_vitisai_init(const char * path_model) {
if (!path_model) {
- std::fprintf(stderr, "%s: path_model is null\n", __func__);
+ WHISPER_LOG_ERROR("%s: path_model is null\n", __func__);
return nullptr;
}
@@ -95,26 +95,22 @@ struct whisper_vitisai_context * whisper_vitisai_init(const char * path_model) {
options.extOptions["fbs_buffer_size"] = ctx->fbs_buffer_size;
options.extOptions["cache_dir"] = std::string(".");
} else {
- std::fprintf(stderr, "%s: Failed to mmap rai file '%s'\n", __func__, ctx->model_path.c_str());
+ WHISPER_LOG_ERROR("%s: Failed to mmap rai file '%s'\n", __func__, ctx->model_path.c_str());
delete ctx;
return nullptr;
}
} else {
options.deviceName = "stx";
-#if defined(WHISPER_DEBUG)
- std::fprintf(stderr, "%s: Using default device name 'stx'\n", __func__);
-#endif
+ WHISPER_LOG_DEBUG("%s: using default device name 'stx'\n", __func__);
}
if (model_is_rai) {
#if WHISPER_FLEXMLRT_LEGACY_RAI_OVERRIDES
options.deviceName = "stx";
options.subgraphName = "vaiml_par_0";
-#if defined(WHISPER_DEBUG)
- std::fprintf(stderr,
+ WHISPER_LOG_DEBUG(
"%s: legacy FlexMLRT compile configuration detected; applying RAI overrides (device='stx', subgraph='vaiml_par_0')\n",
__func__);
-#endif // defined(WHISPER_DEBUG)
#endif
}
@@ -148,31 +144,29 @@ struct whisper_vitisai_context * whisper_vitisai_init(const char * path_model) {
#if defined(WHISPER_DEBUG)
{
- std::fprintf(stderr, "%s: model has %zu input tensor(s)\n", __func__, input_tensors.size());
+ WHISPER_LOG_DEBUG("%s: model has %zu input tensor(s)\n", __func__, input_tensors.size());
for (int i = 0; i < (int) input_tensors.size(); ++i) {
const auto & meta = input_tensors[i].getMetadata();
- std::fprintf(stderr, "%s: input[%d] name='%s' size=%zu shape=",
- __func__, i, meta.name.c_str(), (size_t) meta.size);
- whisper_vitisai_helpers::whisper_vitisai_print_shape(meta.shape);
- std::fprintf(stderr, "\n");
+ WHISPER_LOG_DEBUG("%s: input[%d] name='%s' size=%zu shape=%s\n",
+ __func__, i, meta.name.c_str(), (size_t) meta.size,
+ whisper_vitisai_helpers::whisper_vitisai_shape_string(meta.shape).c_str());
}
- std::fprintf(stderr, "%s: model has %zu output tensor(s)\n", __func__, output_tensors.size());
+ WHISPER_LOG_DEBUG("%s: model has %zu output tensor(s)\n", __func__, output_tensors.size());
for (int i = 0; i < (int) output_tensors.size(); ++i) {
const auto & meta = output_tensors[i].getMetadata();
- std::fprintf(stderr, "%s: output[%d] name='%s' size=%zu shape=",
- __func__, i, meta.name.c_str(), (size_t) meta.size);
- whisper_vitisai_helpers::whisper_vitisai_print_shape(meta.shape);
- std::fprintf(stderr, "\n");
+ WHISPER_LOG_DEBUG("%s: output[%d] name='%s' size=%zu shape=%s\n",
+ __func__, i, meta.name.c_str(), (size_t) meta.size,
+ whisper_vitisai_helpers::whisper_vitisai_shape_string(meta.shape).c_str());
}
- std::fprintf(stderr, "%s: input index: mel=%d\n", __func__, ctx->mel_in_idx);
- std::fprintf(stderr, "%s: output indices: embd_enc=%d cross_k=%d cross_v=%d\n",
+ WHISPER_LOG_DEBUG("%s: input index: mel=%d\n", __func__, ctx->mel_in_idx);
+ WHISPER_LOG_DEBUG("%s: output indices: embd_enc=%d cross_k=%d cross_v=%d\n",
__func__, ctx->embd_enc_out_idx, ctx->cross_k_out_idx, ctx->cross_v_out_idx);
}
#endif
} catch (const std::exception & e) {
- std::fprintf(stderr, "%s: Exception during Vitis AI runner creation: %s\n", __func__, e.what());
+ WHISPER_LOG_ERROR("%s: Exception during Vitis AI runner creation: %s\n", __func__, e.what());
whisper_vitisai_free(ctx);
return nullptr;
}
@@ -188,9 +182,7 @@ void whisper_vitisai_free(struct whisper_vitisai_context * ctx) {
return;
}
-#if defined(WHISPER_DEBUG)
- std::fprintf(stderr, "%s: releasing Vitis AI context for model '%s'\n", __func__, ctx->model_path.c_str());
-#endif
+ WHISPER_LOG_DEBUG("%s: releasing Vitis AI context for model '%s'\n", __func__, ctx->model_path.c_str());
if (ctx->fbs_buffer) {
whisper_vitisai_helpers::unmap_rai_file(ctx->fbs_buffer, ctx->fbs_buffer_size);
}
@@ -206,34 +198,34 @@ static int whisper_vitisai_forward_impl(
void * cross_k_data,
void * cross_v_data) {
if (!ctx || !mel || !out) {
- std::fprintf(stderr, "%s: ctx/mel/out must not be null\n", __func__);
+ WHISPER_LOG_ERROR("%s: ctx/mel/out must not be null\n", __func__);
return 0;
}
const bool with_cross = (cross_k_data != nullptr || cross_v_data != nullptr);
if (with_cross && (!cross_k_data || !cross_v_data)) {
- std::fprintf(stderr, "%s: cross_k_data/cross_v_data must both be set\n", __func__);
+ WHISPER_LOG_ERROR("%s: cross_k_data/cross_v_data must both be set\n", __func__);
return 0;
}
if (ggml_n_dims(mel) != 2) {
- std::fprintf(stderr, "%s: mel tensor expected to have 2 dims, got %d\n", __func__, ggml_n_dims(mel));
+ WHISPER_LOG_ERROR("%s: mel tensor expected to have 2 dims, got %d\n", __func__, ggml_n_dims(mel));
return 0;
}
if (ggml_n_dims(out) != 2) {
- std::fprintf(stderr, "%s: out tensor expected to have 2 dims, got %d\n", __func__, ggml_n_dims(out));
+ WHISPER_LOG_ERROR("%s: out tensor expected to have 2 dims, got %d\n", __func__, ggml_n_dims(out));
return 0;
}
if (ctx->embd_enc_out_idx < 0 || ctx->embd_enc_out_idx >= (int) output_tensors.size()) {
- std::fprintf(stderr, "%s: invalid embd_enc output index %d for %zu output tensor(s)\n",
+ WHISPER_LOG_ERROR("%s: invalid embd_enc output index %d for %zu output tensor(s)\n",
__func__, ctx->embd_enc_out_idx, output_tensors.size());
return 0;
}
if (ctx->mel_in_idx < 0 || ctx->mel_in_idx >= (int) input_tensors.size()) {
- std::fprintf(stderr, "%s: invalid mel input index %d for %zu input tensor(s)\n",
+ WHISPER_LOG_ERROR("%s: invalid mel input index %d for %zu input tensor(s)\n",
__func__, ctx->mel_in_idx, input_tensors.size());
return 0;
}
@@ -266,7 +258,7 @@ static int whisper_vitisai_forward_impl(
if (with_cross) {
if (ctx->cross_k_out_idx < 0 || ctx->cross_k_out_idx >= (int) output_tensors.size() ||
ctx->cross_v_out_idx < 0 || ctx->cross_v_out_idx >= (int) output_tensors.size()) {
- std::fprintf(stderr, "%s: invalid cross output indices cross_k=%d cross_v=%d for %zu output tensor(s)\n",
+ WHISPER_LOG_ERROR("%s: invalid cross output indices cross_k=%d cross_v=%d for %zu output tensor(s)\n",
__func__, ctx->cross_k_out_idx, ctx->cross_v_out_idx, output_tensors.size());
return 0;
}
@@ -292,13 +284,11 @@ static int whisper_vitisai_forward_impl(
try {
ctx->runner->forward(input_tensors, output_tensors);
clear_bound_data();
-#if defined(WHISPER_DEBUG)
- std::fprintf(stderr, "%s: Vitis AI model inference %scompleted.\n",
+ WHISPER_LOG_DEBUG("%s: Vitis AI model inference %scompleted.\n",
__func__, with_cross ? "(encoder + cross proj) " : "");
-#endif
} catch (const std::exception & e) {
clear_bound_data();
- std::fprintf(stderr, "%s: Exception during model inference: %s\n", __func__, e.what());
+ WHISPER_LOG_ERROR("%s: Exception during model inference: %s\n", __func__, e.what());
return 0;
}
@@ -309,7 +299,7 @@ int whisper_vitisai_encode(struct whisper_vitisai_context * ctx, struct ggml_ten
std::vector<flexmlrt::client::ErtTensorType> * input_tensors_cached = nullptr;
std::vector<flexmlrt::client::ErtTensorType> * output_tensors_cached = nullptr;
if (!whisper_vitisai_get_cached_io_tensors(ctx, input_tensors_cached, output_tensors_cached)) {
- std::fprintf(stderr, "%s: failed to acquire Vitis AI I/O tensors\n", __func__);
+ WHISPER_LOG_ERROR("%s: failed to acquire Vitis AI I/O tensors\n", __func__);
return 0;
}
@@ -352,24 +342,24 @@ int whisper_vitisai_encode_with_cross(
int n_text_head,
bool flash_attn) {
if (!ctx || !mel || !embd_enc || !kv_cross_k || !kv_cross_v) {
- std::fprintf(stderr, "%s: ctx/mel/embd_enc/kv_cross_k/kv_cross_v must not be null\n", __func__);
+ WHISPER_LOG_ERROR("%s: ctx/mel/embd_enc/kv_cross_k/kv_cross_v must not be null\n", __func__);
return 0;
}
if (n_text_layer <= 0 || n_ctx <= 0 || n_text_state <= 0 || n_text_head <= 0) {
- std::fprintf(stderr, "%s: invalid shape parameters layer=%d ctx=%d state=%d head=%d\n",
+ WHISPER_LOG_ERROR("%s: invalid shape parameters layer=%d ctx=%d state=%d head=%d\n",
__func__, n_text_layer, n_ctx, n_text_state, n_text_head);
return 0;
}
if ((n_text_state % n_text_head) != 0) {
- std::fprintf(stderr, "%s: invalid head configuration state=%d head=%d\n",
+ WHISPER_LOG_ERROR("%s: invalid head configuration state=%d head=%d\n",
__func__, n_text_state, n_text_head);
return 0;
}
if (kv_cross_k->type != kv_cross_v->type) {
- std::fprintf(stderr, "%s: kv_cross type mismatch k=%s v=%s\n",
+ WHISPER_LOG_ERROR("%s: kv_cross type mismatch k=%s v=%s\n",
__func__,
whisper_vitisai_helpers::whisper_kv_type_name(kv_cross_k->type),
whisper_vitisai_helpers::whisper_kv_type_name(kv_cross_v->type));
@@ -385,7 +375,7 @@ int whisper_vitisai_encode_with_cross(
const bool kv_is_f32 = kv_type == GGML_TYPE_F32;
const bool kv_is_f16 = kv_type == GGML_TYPE_F16;
if (!kv_is_f32 && !kv_is_f16) {
- std::fprintf(stderr, "%s: unsupported kv_cross tensor type '%s'\n",
+ WHISPER_LOG_ERROR("%s: unsupported kv_cross tensor type '%s'\n",
__func__, whisper_vitisai_helpers::whisper_kv_type_name(kv_type));
return 0;
}
@@ -396,7 +386,7 @@ int whisper_vitisai_encode_with_cross(
std::vector<flexmlrt::client::ErtTensorType> * input_tensors_cached = nullptr;
std::vector<flexmlrt::client::ErtTensorType> * output_tensors_cached = nullptr;
if (!whisper_vitisai_get_cached_io_tensors(ctx, input_tensors_cached, output_tensors_cached)) {
- std::fprintf(stderr, "%s: failed to acquire Vitis AI I/O tensors\n", __func__);
+ WHISPER_LOG_ERROR("%s: failed to acquire Vitis AI I/O tensors\n", __func__);
return 0;
}
std::vector<flexmlrt::client::ErtTensorType> input_tensors = *input_tensors_cached;
@@ -404,7 +394,7 @@ int whisper_vitisai_encode_with_cross(
if (ctx->cross_k_out_idx < 0 || ctx->cross_k_out_idx >= (int) output_tensors.size() ||
ctx->cross_v_out_idx < 0 || ctx->cross_v_out_idx >= (int) output_tensors.size()) {
- std::fprintf(stderr, "%s: invalid cross output indices cross_k=%d cross_v=%d for %zu output tensor(s)\n",
+ WHISPER_LOG_ERROR("%s: invalid cross output indices cross_k=%d cross_v=%d for %zu output tensor(s)\n",
__func__, ctx->cross_k_out_idx, ctx->cross_v_out_idx, output_tensors.size());
return 0;
}
@@ -417,17 +407,17 @@ int whisper_vitisai_encode_with_cross(
}
if (ctx->cross_k_expected_bytes == 0 || ctx->cross_v_expected_bytes == 0) {
- std::fprintf(stderr, "%s: missing cross output metadata sizes\n", __func__);
+ WHISPER_LOG_ERROR("%s: missing cross output metadata sizes\n", __func__);
return 0;
}
if (ctx->cross_k_expected_bytes != ctx->cross_v_expected_bytes) {
- std::fprintf(stderr, "%s: cross output metadata size mismatch k=%zu v=%zu\n",
+ WHISPER_LOG_ERROR("%s: cross output metadata size mismatch k=%zu v=%zu\n",
__func__, ctx->cross_k_expected_bytes, ctx->cross_v_expected_bytes);
return 0;
}
const size_t expected_cross_bytes = (size_t) n_text_layer * req_layer_elems * sizeof(float);
if (ctx->cross_k_expected_bytes != expected_cross_bytes) {
- std::fprintf(stderr,
+ WHISPER_LOG_ERROR(
"%s: cross output size mismatch (model=%zu B, expected=%zu B for layer=%d ctx=%d state=%d)\n",
__func__, ctx->cross_k_expected_bytes, expected_cross_bytes, n_text_layer, n_ctx, n_state);
return 0;
@@ -440,7 +430,7 @@ int whisper_vitisai_encode_with_cross(
? (size_t)n_text_layer * elem_size * (size_t)n_state * (size_t)n_ctx_pad
: (size_t)n_text_layer * elem_size * req_layer_elems;
if (ggml_nbytes(kv_cross_k) < required_kv_bytes || ggml_nbytes(kv_cross_v) < required_kv_bytes) {
- std::fprintf(stderr,
+ WHISPER_LOG_ERROR(
"%s: kv_cross buffers are too small (required=%zu B, k=%zu B, v=%zu B)\n",
__func__, required_kv_bytes, ggml_nbytes(kv_cross_k), ggml_nbytes(kv_cross_v));
return 0;
@@ -518,13 +508,10 @@ int whisper_vitisai_encode_with_cross(
WHISPER_DBG_TIMER(t_post_end);
-#if defined(WHISPER_DEBUG)
- const size_t model_ctx = (size_t) n_ctx;
- std::fprintf(stderr, "%s: vitisai enc+cross forward time = %8.2f ms\n", __func__, (t_fwd_end - t_fwd_start) / 1000.0f);
- std::fprintf(stderr, "%s: kv_cross post-process time = %8.2f ms (flash, req_ctx=%d, model_ctx=%zu, req_ctx_pad=%d, kv_type=%s)\n",
- __func__, (t_post_end - t_post_start) / 1000.0f, n_ctx, model_ctx, n_ctx_pad,
+ WHISPER_LOG_DEBUG("%s: vitisai enc+cross forward time = %8.2f ms\n", __func__, (t_fwd_end - t_fwd_start) / 1000.0f);
+ WHISPER_LOG_DEBUG("%s: kv_cross post-process time = %8.2f ms (flash, req_ctx=%d, model_ctx=%zu, req_ctx_pad=%d, kv_type=%s)\n",
+ __func__, (t_post_end - t_post_start) / 1000.0f, n_ctx, (size_t) n_ctx, n_ctx_pad,
whisper_vitisai_helpers::whisper_kv_type_name(kv_type));
-#endif
} else {
// Non-flash: model outputs contiguous [ctx, state] per layer.
WHISPER_DBG_TIMER(t_fwd_start);
@@ -558,13 +545,10 @@ int whisper_vitisai_encode_with_cross(
WHISPER_DBG_TIMER(t_post_end);
-#if defined(WHISPER_DEBUG)
- const size_t model_ctx = (size_t) n_ctx;
- std::fprintf(stderr, "%s: vitisai enc+cross forward time = %8.2f ms\n", __func__, (t_fwd_end - t_fwd_start) / 1000.0f);
- std::fprintf(stderr, "%s: kv_cross post-process time = %8.2f ms (non-flash, req_ctx=%d, model_ctx=%zu, kv_type=%s)\n",
- __func__, (t_post_end - t_post_start) / 1000.0f, n_ctx, model_ctx,
+ WHISPER_LOG_DEBUG("%s: vitisai enc+cross forward time = %8.2f ms\n", __func__, (t_fwd_end - t_fwd_start) / 1000.0f);
+ WHISPER_LOG_DEBUG("%s: kv_cross post-process time = %8.2f ms (non-flash, req_ctx=%d, model_ctx=%zu, kv_type=%s)\n",
+ __func__, (t_post_end - t_post_start) / 1000.0f, n_ctx, (size_t) n_ctx,
whisper_vitisai_helpers::whisper_kv_type_name(kv_type));
-#endif
}
return 1;
diff --git a/src/vitisai/whisper-vitisai-helpers.cpp b/src/vitisai/whisper-vitisai-helpers.cpp
index 41763461..c622cd52 100644
--- a/src/vitisai/whisper-vitisai-helpers.cpp
+++ b/src/vitisai/whisper-vitisai-helpers.cpp
@@ -5,6 +5,7 @@
#endif
#include "vitisai/whisper-vitisai-helpers.h"
+#include "whisper-logging.h"
#include <algorithm>
#include <cstdio>
@@ -23,21 +24,21 @@ bool map_rai_file(const char * path, uint8_t ** buffer, size_t * size) {
#ifdef _WIN32
HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
- std::fprintf(stderr, "%s: %d: Failed to open rai file '%s'\n", __func__, __LINE__, path);
+ WHISPER_LOG_ERROR("%s: %d: Failed to open rai file '%s'\n", __func__, __LINE__, path);
return false;
}
LARGE_INTEGER fileSize;
if (!GetFileSizeEx(hFile, &fileSize)) {
CloseHandle(hFile);
- std::fprintf(stderr, "%s: %d: Failed to get file size for rai file '%s'\n", __func__, __LINE__, path);
+ WHISPER_LOG_ERROR("%s: %d: Failed to get file size for rai file '%s'\n", __func__, __LINE__, path);
return false;
}
HANDLE hMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, fileSize.QuadPart, NULL);
if (hMapping == NULL) {
CloseHandle(hFile);
- std::fprintf(stderr, "%s: %d: Failed to create file mapping for rai file '%s'\n", __func__, __LINE__, path);
+ WHISPER_LOG_ERROR("%s: %d: Failed to create file mapping for rai file '%s'\n", __func__, __LINE__, path);
return false;
}
@@ -45,7 +46,7 @@ bool map_rai_file(const char * path, uint8_t ** buffer, size_t * size) {
if (*buffer == NULL) {
CloseHandle(hMapping);
CloseHandle(hFile);
- std::fprintf(stderr, "%s: %d: Failed to map rai file '%s'\n", __func__, __LINE__, path);
+ WHISPER_LOG_ERROR("%s: %d: Failed to map rai file '%s'\n", __func__, __LINE__, path);
return false;
}
CloseHandle(hMapping);
@@ -55,21 +56,21 @@ bool map_rai_file(const char * path, uint8_t ** buffer, size_t * size) {
#else
FILE * fd = fopen(path, "rb");
if (!fd) {
- std::fprintf(stderr, "%s: %d: Failed to open rai file '%s'\n", __func__, __LINE__, path);
+ WHISPER_LOG_ERROR("%s: %d: Failed to open rai file '%s'\n", __func__, __LINE__, path);
return false;
}
struct stat st;
if (fstat(fileno(fd), &st) == -1) {
fclose(fd);
- std::fprintf(stderr, "%s: %d: Failed to get file size for rai file '%s'\n", __func__, __LINE__, path);
+ WHISPER_LOG_ERROR("%s: %d: Failed to get file size for rai file '%s'\n", __func__, __LINE__, path);
return false;
}
*buffer = (uint8_t *) mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fileno(fd), 0);
if (*buffer == MAP_FAILED) {
fclose(fd);
- std::fprintf(stderr, "%s: %d: Failed to mmap rai file '%s'\n", __func__, __LINE__, path);
+ WHISPER_LOG_ERROR("%s: %d: Failed to mmap rai file '%s'\n", __func__, __LINE__, path);
return false;
}
fclose(fd);
@@ -140,14 +141,14 @@ static bool whisper_vitisai_validate_tensor_dtype(
ggml_type runtime_dtype) {
ggml_type expected_runtime_dtype = GGML_TYPE_COUNT;
if (!whisper_flexml_dtype_to_ggml_type(model_dtype, &expected_runtime_dtype)) {
- std::fprintf(stderr,
+ WHISPER_LOG_ERROR(
"%s: unsupported model dtype for %s: %s (supported: Float32/Float16/BFloat16)\n",
__func__, tensor_name, whisper_flexml_dtype_name(model_dtype));
return false;
}
if (runtime_dtype != expected_runtime_dtype) {
- std::fprintf(stderr,
+ WHISPER_LOG_ERROR(
"%s: %s dtype mismatch (runtime=%s, model=%s)\n",
__func__, tensor_name, ggml_type_name(runtime_dtype), whisper_flexml_dtype_name(model_dtype));
return false;
@@ -189,7 +190,7 @@ static bool whisper_validate_shape(
const std::vector<size_t> & expected_shape) {
const std::vector<size_t> shape = whisper_canonical_shape(model_shape);
if (shape != expected_shape) {
- std::fprintf(stderr,
+ WHISPER_LOG_ERROR(
"%s: %s shape mismatch (runtime expected=%s, model=%s)\n",
__func__,
tensor_name,
@@ -230,12 +231,12 @@ bool whisper_vitisai_bind_tensor_data(
const size_t model_bytes = meta.size;
const size_t runtime_bytes = ggml_nbytes(runtime_tensor);
if (model_bytes == 0 || runtime_bytes == 0) {
- std::fprintf(stderr, "%s: %s sizes must be non-zero (model=%zu, runtime=%zu)\n",
+ WHISPER_LOG_ERROR("%s: %s sizes must be non-zero (model=%zu, runtime=%zu)\n",
__func__, tensor_name, model_bytes, runtime_bytes);
return false;
}
if (runtime_bytes != model_bytes) {
- std::fprintf(stderr,
+ WHISPER_LOG_ERROR(
"%s: %s tensor size mismatch (runtime=%zu B, model=%zu B). "
"VitisAI .rai requires exact context match; use matching -ac/model artifact.\n",
__func__, tensor_name, runtime_bytes, model_bytes);
@@ -247,7 +248,7 @@ bool whisper_vitisai_bind_tensor_data(
}
bool whisper_vitisai_resolve_io_binding(
- [[maybe_unused]] const char * caller,
+ const char * caller,
const std::vector<flexmlrt::client::ErtTensorType> & input_tensors,
const std::vector<flexmlrt::client::ErtTensorType> & output_tensors,
whisper_vitisai_io_binding * binding,
@@ -274,9 +275,7 @@ bool whisper_vitisai_resolve_io_binding(
}
}
if (!found_named_mel) {
-#if defined(WHISPER_DEBUG)
- std::fprintf(stderr, "%s: WARNING: mel input not found by name; falling back to input[0]\n", caller);
-#endif
+ WHISPER_LOG_WARN("%s: mel input not found by name; falling back to input[0]\n", caller);
}
if (output_tensors.empty()) {
@@ -295,9 +294,7 @@ bool whisper_vitisai_resolve_io_binding(
}
if (binding->embd_enc_out_idx < 0) {
-#if defined(WHISPER_DEBUG)
- std::fprintf(stderr, "%s: WARNING: embd_enc output not found by name; falling back to output[0]\n", caller);
-#endif
+ WHISPER_LOG_WARN("%s: embd_enc output not found by name; falling back to output[0]\n", caller);
binding->embd_enc_out_idx = 0;
}
@@ -356,7 +353,7 @@ bool whisper_vitisai_all_tensors_claimed(
const std::vector<bool> & claimed) {
for (size_t i = 0; i < tensors.size(); ++i) {
if (!claimed[i]) {
- std::fprintf(stderr,
+ WHISPER_LOG_ERROR(
"%s: unsupported extra %s tensor at index %zu (name='%s'); strict contract expects only mapped %ss\n",
caller, tensor_kind, i, tensors[i].getMetadata().name.c_str(), tensor_kind);
return false;
diff --git a/src/vitisai/whisper-vitisai-helpers.h b/src/vitisai/whisper-vitisai-helpers.h
index d50a2f4a..38bc3f04 100644
--- a/src/vitisai/whisper-vitisai-helpers.h
+++ b/src/vitisai/whisper-vitisai-helpers.h
@@ -5,7 +5,6 @@
#include <cstddef>
#include <cstdint>
-#include <cstdio>
#include <string>
#include <vector>
@@ -33,16 +32,19 @@ bool whisper_vitisai_bind_tensor_data(
const std::vector<size_t> & expected_shape,
flexmlrt::client::ErtTensorType & io_tensor);
-#if defined(WHISPER_DEBUG)
+// Formats a tensor shape for logging, e.g. "[1, 80, 3000]".
template <typename T>
-void whisper_vitisai_print_shape(const std::vector<T> & shape) {
- std::fprintf(stderr, "[");
+std::string whisper_vitisai_shape_string(const std::vector<T> & shape) {
+ std::string out = "[";
for (size_t i = 0; i < shape.size(); ++i) {
- std::fprintf(stderr, "%s%lld", i == 0 ? "" : ", ", (long long) shape[i]);
+ if (i > 0) {
+ out += ", ";
+ }
+ out += std::to_string((long long) shape[i]);
}
- std::fprintf(stderr, "]");
+ out += "]";
+ return out;
}
-#endif
// Model IO tensor indices and metadata sizes resolved once at init time.
struct whisper_vitisai_io_binding {
diff --git a/src/whisper-logging.h b/src/whisper-logging.h
new file mode 100644
index 00000000..9a873408
--- /dev/null
+++ b/src/whisper-logging.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "ggml.h"
+
+//
+// logging
+//
+// Internal logging interface shared between whisper.cpp and the optional
+// backends compiled into the library. All WHISPER_LOG_* messages are routed
+// through the callback installed with whisper_log_set().
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GGML_ATTRIBUTE_FORMAT(2, 3)
+void whisper_log_internal(ggml_log_level level, const char * format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define WHISPER_LOG_ERROR(...) whisper_log_internal(GGML_LOG_LEVEL_ERROR, __VA_ARGS__)
+#define WHISPER_LOG_WARN(...) whisper_log_internal(GGML_LOG_LEVEL_WARN , __VA_ARGS__)
+#define WHISPER_LOG_INFO(...) whisper_log_internal(GGML_LOG_LEVEL_INFO , __VA_ARGS__)
+
+// define this to enable verbose trace logging - useful for debugging purposes
+//#define WHISPER_DEBUG
+
+#if defined(WHISPER_DEBUG)
+#define WHISPER_LOG_DEBUG(...) whisper_log_internal(GGML_LOG_LEVEL_DEBUG, __VA_ARGS__)
+#else
+#define WHISPER_LOG_DEBUG(...)
+#endif
diff --git a/src/whisper.cpp b/src/whisper.cpp
index 2fac6479..1c7771fc 100644
--- a/src/whisper.cpp
+++ b/src/whisper.cpp
@@ -1,5 +1,6 @@
#include "whisper.h"
#include "whisper-arch.h"
+#include "whisper-logging.h"
#include "ggml.h"
#include "ggml-cpp.h"
@@ -106,37 +107,12 @@ static void byteswap_tensor(ggml_tensor * tensor) {
#define BYTESWAP_TENSOR(t) do {} while (0)
#endif
-#ifdef __GNUC__
-#ifdef __MINGW32__
-#define WHISPER_ATTRIBUTE_FORMAT(...) __attribute__((format(gnu_printf, __VA_ARGS__)))
-#else
-#define WHISPER_ATTRIBUTE_FORMAT(...) __attribute__((format(printf, __VA_ARGS__)))
-#endif
-#else
-#define WHISPER_ATTRIBUTE_FORMAT(...)
-#endif
-
//
// logging
//
-WHISPER_ATTRIBUTE_FORMAT(2, 3)
-static void whisper_log_internal (ggml_log_level level, const char * format, ...);
static void whisper_log_callback_default(ggml_log_level level, const char * text, void * user_data);
-#define WHISPER_LOG_ERROR(...) whisper_log_internal(GGML_LOG_LEVEL_ERROR, __VA_ARGS__)
-#define WHISPER_LOG_WARN(...) whisper_log_internal(GGML_LOG_LEVEL_WARN , __VA_ARGS__)
-#define WHISPER_LOG_INFO(...) whisper_log_internal(GGML_LOG_LEVEL_INFO , __VA_ARGS__)
-
-// define this to enable verbose trace logging - useful for debugging purposes
-//#define WHISPER_DEBUG
-
-#if defined(WHISPER_DEBUG)
-#define WHISPER_LOG_DEBUG(...) whisper_log_internal(GGML_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#else
-#define WHISPER_LOG_DEBUG(...)
-#endif
-
#define WHISPER_ASSERT(x) \
do { \
if (!(x)) { \
@@ -9386,7 +9362,7 @@ const char * whisper_version(void) {
}
GGML_ATTRIBUTE_FORMAT(2, 3)
-static void whisper_log_internal(ggml_log_level level, const char * format, ...) {
+void whisper_log_internal(ggml_log_level level, const char * format, ...) {
va_list args;
va_start(args, format);
char buffer[1024];