Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion include/transcribe.h
Original file line number Diff line number Diff line change
Expand Up @@ -1085,7 +1085,9 @@ TRANSCRIBE_API void transcribe_model_load_params_init(struct transcribe_model_lo
* Session init params.
*
* n_threads: number of CPU threads for ops that run on CPU. 0 means
* "library picks a sensible default".
* "library picks a sensible default". At most 512 (ggml's
* thread limit); negative or larger values are rejected with
* TRANSCRIBE_ERR_INVALID_ARG.
*
* kv_type: data type for K/V activations in flash attention.
* AUTO (default) uses f16 for quantized models, f32 for f32.
Expand Down
2 changes: 1 addition & 1 deletion include/transcribe/diarize.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct transcribe_diarize_info {

struct transcribe_diarize_session_params {
uint64_t struct_size;
int32_t n_threads; /* 0 = library default */
int32_t n_threads; /* 0 = library default; at most 512 */
};

struct transcribe_diarize_params {
Expand Down
2 changes: 1 addition & 1 deletion include/transcribe/langid.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct transcribe_langid_info {

struct transcribe_langid_session_params {
uint64_t struct_size;
int32_t n_threads; /* 0 = library default */
int32_t n_threads; /* 0 = library default; at most 512 */
};

struct transcribe_langid_params {
Expand Down
2 changes: 1 addition & 1 deletion include/transcribe/vad.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct transcribe_vad_info {

struct transcribe_vad_session_params {
uint64_t struct_size; /* struct size in bytes; set by the init function */
int32_t n_threads; /* number of processing threads; 0 uses the default */
int32_t n_threads; /* number of processing threads; 0 uses the default, at most 512 */
};

/* Settings for transcribe_vad_run. Durations are in milliseconds and
Expand Down
8 changes: 8 additions & 0 deletions src/transcribe-abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#pragma once

#include "ggml.h"
#include "transcribe.h"

#include <cmath>
Expand Down Expand Up @@ -66,6 +67,13 @@ inline transcribe_status check_input_struct_size(uint64_t got, uint64_t want) {
return check_struct_size(got, want);
}

// Session n_threads (ASR, VAD, langid, diarize): 0 selects the library
// default; the maximum is ggml's GGML_MAX_N_THREADS. Larger counts stall the
// CPU backend or fail at thread creation, reported as out-of-memory.
inline bool valid_n_threads(int32_t n_threads) {
return n_threads >= 0 && n_threads <= GGML_MAX_N_THREADS;
}

// Copy min(caller_size, library_size) bytes from a library-staged struct
// into the caller's output buffer. The min() is the overflow guard: the
// library never writes past what the caller declared, and never reads
Expand Down
11 changes: 6 additions & 5 deletions src/transcribe-asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ using transcribe::api_guard_value;
using transcribe::api_guard_void;
using transcribe::enum_field_raw;
using transcribe::pcm_is_finite;
using transcribe::valid_n_threads;

namespace {

Expand Down Expand Up @@ -771,11 +772,11 @@ static transcribe_status transcribe_session_init_impl(struct transcribe_model *
return st;
}
// n_threads contract from include/transcribe.h: 0 means "library
// picks a sensible default", positive means "use this many." A
// negative value is undefined input, not a documented sentinel —
// reject it here so individual family handlers don't have to
// re-check the same condition.
if (params->n_threads < 0) {
// picks a sensible default", positive means "use this many", up to
// ggml's thread limit. Anything else is undefined input, not a
// documented sentinel — reject it here so individual family handlers
// don't have to re-check the same condition.
if (!valid_n_threads(params->n_threads)) {
return TRANSCRIBE_ERR_INVALID_ARG;
}
// Raw-validate kv_type before the families' first enum-typed load of it
Expand Down
3 changes: 2 additions & 1 deletion src/transcribe-diarize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ using transcribe::api_guard_void;
using transcribe::check_input_struct_size;
using transcribe::check_struct_size;
using transcribe::copy_out_prefix;
using transcribe::valid_n_threads;

namespace {

Expand Down Expand Up @@ -106,7 +107,7 @@ static transcribe_status diarize_session_init_impl(transcribe_model *
if (const auto st = check_input_struct_size(params->struct_size, k_min_session_params_size); st != TRANSCRIBE_OK) {
return st;
}
if (params->n_threads < 0) {
if (!valid_n_threads(params->n_threads)) {
return TRANSCRIBE_ERR_INVALID_ARG;
}
*out = ops->new_session();
Expand Down
3 changes: 2 additions & 1 deletion src/transcribe-langid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ using transcribe::check_struct_size;
using transcribe::copy_out_prefix;
using transcribe::LangidCandidateEntry;
using transcribe::LangidLabels;
using transcribe::valid_n_threads;

namespace {

Expand Down Expand Up @@ -223,7 +224,7 @@ static transcribe_status langid_session_init_impl(transcribe_model *
if (const auto st = check_input_struct_size(params->struct_size, k_min_session_params_size); st != TRANSCRIBE_OK) {
return st;
}
if (params->n_threads < 0) {
if (!valid_n_threads(params->n_threads)) {
return TRANSCRIBE_ERR_INVALID_ARG;
}
*out = ops->new_session();
Expand Down
3 changes: 2 additions & 1 deletion src/transcribe-vad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ using transcribe::check_struct_size;
using transcribe::copy_out_prefix;
using transcribe::VadSegmentEntry;
using transcribe::VadSegmentParams;
using transcribe::valid_n_threads;

namespace {

Expand Down Expand Up @@ -349,7 +350,7 @@ static transcribe_status vad_session_init_impl(transcribe_model *
if (const auto st = check_input_struct_size(params->struct_size, k_min_session_params_size); st != TRANSCRIBE_OK) {
return st;
}
if (params->n_threads < 0) {
if (!valid_n_threads(params->n_threads)) {
return TRANSCRIBE_ERR_INVALID_ARG;
}
std::unique_ptr<transcribe_vad_session> s(ops->new_session());
Expand Down
8 changes: 5 additions & 3 deletions tests/diarize_dispatch_unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,11 @@ void test_role_checks() {

transcribe_diarize_session_params sp;
transcribe_diarize_session_params_init(&sp);
sp.n_threads = -1;
CHECK(transcribe_diarize_session_init(&model, &sp, &s) == TRANSCRIBE_ERR_INVALID_ARG);
CHECK(s == nullptr);
for (const int n_threads : { -1, 513 }) {
sp.n_threads = n_threads;
CHECK(transcribe_diarize_session_init(&model, &sp, &s) == TRANSCRIBE_ERR_INVALID_ARG);
CHECK(s == nullptr);
}
sp.n_threads = 2;
CHECK(transcribe_diarize_session_init(&model, &sp, &s) == TRANSCRIBE_OK);
CHECK(s != nullptr);
Expand Down
10 changes: 6 additions & 4 deletions tests/langid_dispatch_unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,14 @@ void test_role_checks_and_labels() {
CHECK(transcribe_langid_label_index(&model, "xx") == 0);
CHECK(transcribe_langid_label_index(&model, "zz") == -1);

// A negative thread count is rejected up front.
// A negative thread count, or one above ggml's limit, is rejected up front.
transcribe_langid_session_params sp;
transcribe_langid_session_params_init(&sp);
sp.n_threads = -1;
CHECK(transcribe_langid_session_init(&model, &sp, &s) == TRANSCRIBE_ERR_INVALID_ARG);
CHECK(s == nullptr);
for (const int n_threads : { -1, 513 }) {
sp.n_threads = n_threads;
CHECK(transcribe_langid_session_init(&model, &sp, &s) == TRANSCRIBE_ERR_INVALID_ARG);
CHECK(s == nullptr);
}
}

void test_ranking() {
Expand Down
9 changes: 8 additions & 1 deletion tests/silero_vad_smoke.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,14 @@ void test_model() {
CHECK(transcribe_vad_get_info(m, &info) == TRANSCRIBE_OK);
CHECK(info.sample_rate == 16000 && info.frame_samples == 512);

transcribe_vad_session * s = nullptr;
transcribe_vad_session * s = nullptr;
transcribe_vad_session_params sp;
transcribe_vad_session_params_init(&sp);
for (const int n_threads : { -1, 513 }) {
sp.n_threads = n_threads;
CHECK(transcribe_vad_session_init(m, &sp, &s) == TRANSCRIBE_ERR_INVALID_ARG);
CHECK(s == nullptr);
}
CHECK(transcribe_vad_session_init(m, nullptr, &s) == TRANSCRIBE_OK);

// Crosses the encoder's 256-frame block boundary with a partial tail.
Expand Down
24 changes: 21 additions & 3 deletions tests/tokenizer_smoke.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,9 @@ void test_v3_fixture() {
// n_threads validation in transcribe_session_init (Finding 3)
// ---------------------------------------------------------------------------
//
// Negative n_threads is undefined input per the public header (0 means
// "library picks", positive means "use this many"). The central
// dispatcher rejects it before the family handler runs.
// Negative n_threads, or more than 512, is undefined input per the public
// header (0 means "library picks", positive means "use this many"). The
// central dispatcher rejects it before the family handler runs.
void test_n_threads_validation() {
struct transcribe_model * model = load_or_fail("tokenizer_minimal.gguf", "tdt-0.6b-v2");
if (model == nullptr) {
Expand All @@ -322,6 +322,24 @@ void test_n_threads_validation() {
++g_failures;
}

// Above ggml's thread limit is rejected the same way; the limit itself is accepted.
cp.n_threads = 513;
ctx = (struct transcribe_session *) 0xdeadbeef;
const transcribe_status st_above = transcribe_session_init(model, &cp, &ctx);
if (st_above != TRANSCRIBE_ERR_INVALID_ARG || ctx != nullptr) {
std::fprintf(stderr, "FAIL n_threads=513: expected INVALID_ARG and cleared out_ctx, got %s\n",
transcribe_status_string(st_above));
++g_failures;
}
cp.n_threads = 512;
ctx = nullptr;
const transcribe_status st_limit = transcribe_session_init(model, &cp, &ctx);
if (st_limit != TRANSCRIBE_OK || ctx == nullptr) {
std::fprintf(stderr, "FAIL n_threads=512: expected OK, got %s\n", transcribe_status_string(st_limit));
++g_failures;
}
transcribe_session_free(ctx);

// Sanity: n_threads == 0 (library default) succeeds.
cp.n_threads = 0;
ctx = nullptr;
Expand Down