bark.cpp icon indicating copy to clipboard operation
bark.cpp copied to clipboard

DivideByZeroException in bark_load_model when calling ggml_time_us()

Open LSXAxeller opened this issue 5 months ago • 0 comments

When calling bark_load_model from the C# BarkSharp wrapper, a System.DivideByZeroException is thrown at the line int64_t t_load_start_us = ggml_time_us();. This seems to indicate that the ggml_time_us() function is attempting to divide by zero, likely because the timer_freq variable has not been properly initialized.

Inserting a call to ggml_time_init() at the beginning of bark_load_model to initialize the timer leads to a StackOverflowException during the allocation of memory with ggml_allocr_new_from_buffer. This suggests a potential issue with memory management or initialization within the GGML library.

Reproduction Steps:

  1. Build the Bark library: Ensure that the Bark library (including GGML) is built successfully.
  2. Create a C# project: Create a C# project that uses the BarkSharp wrapper to interact with the Bark library.
  3. Load the Bark model: Attempt to load the Bark model using the BarkContext class constructor, providing the path to the model file.

Example Code (Relevant C# snippets):

// BarkContext.cs
public BarkContext(string modelPath, BarkContextParams parameters, uint seed)
{
    var modelPathPtr = Marshal.StringToHGlobalAnsi(modelPath);
    _context = LoadModel(modelPathPtr , parameters, seed); // This call eventually leads to the exception
    // ...
}

// NativeMethods.cs
[DllImport(NativeLibraryManager.LibraryName, EntryPoint = "bark_load_model", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern IntPtr LoadModel(IntPtr modelPath, BarkContextParams parameters, uint seed);

Relevant C++ Code (bark.cpp):

struct bark_context* bark_load_model(const char* model_path, struct bark_context_params params, uint32_t seed) {
    int64_t t_load_start_us = ggml_time_us(); // Exception occurs here

    struct bark_context* bctx = new bark_context();

    bctx->text_model = bark_model();
    std::string model_path_str(model_path);
    if (!bark_load_model_from_file(model_path_str, bctx, params.verbosity)) {
        fprintf(stderr, "%s: failed to load model weights from '%s'\n", __func__, model_path);
        return nullptr;
    }

    bctx->rng = std::mt19937(seed);
    bctx->params = params;
    bctx->stats.t_load_us = ggml_time_us() - t_load_start_us;

    return bctx;
}

Relevant C++ Code (ggml.c):

int64_t ggml_time_us(void) {
    LARGE_INTEGER t;
    QueryPerformanceCounter(&t);
    return ((t.QuadPart - timer_start) * 1000000) / timer_freq; // Potential division by zero
}

void ggml_time_init(void) {
    LARGE_INTEGER frequency;
    QueryPerformanceFrequency(&frequency);
    timer_freq = frequency.QuadPart;
    QueryPerformanceCounter(&timer_start);
}

Expected Behavior:

The bark_load_model function should load the model successfully without throwing any exceptions. The ggml_time_us() function should return a valid timestamp.

Actual Behavior:

A System.DivideByZeroException is thrown when calling ggml_time_us(). Attempting to fix this by calling ggml_time_init() at the beginning of bark_load_model results in a StackOverflowException during memory allocation.

Possible Causes:

  • Missing timer initialization: The timer_freq variable in ggml_time_us() might not be initialized properly before it is used, leading to the division by zero error.
  • Circular dependency or recursive call: The StackOverflowException when calling ggml_time_init() might indicate a circular dependency or a recursive function call that exceeds the stack limit.
  • Memory allocation issues: There might be problems with memory allocation or initialization within GGML, leading to the stack overflow during the creation of the allocator.

LSXAxeller avatar Sep 13 '24 09:09 LSXAxeller