Skip to content

Commit caedb5c

Browse files
committed
perf(embeddings): optimize thread budget for ORT sessions
- Introduce max thread budget based on CPU count - Derive session count from thread budget and intra-op threads - Add EMBEDDINGS_MAX_THREADS environment variable support - Prevent thread oversubscription by capping session count
1 parent 7a7f229 commit caedb5c

1 file changed

Lines changed: 23 additions & 8 deletions

File tree

embeddings/src/model/local.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ use tokenizers::Tokenizer;
3232
/// Default batch size per ONNX forward pass.
3333
const DEFAULT_BATCH_SIZE: usize = 8;
3434

35+
/// Default intra-op threads per session.
36+
const DEFAULT_INTRA_THREADS: usize = 4;
37+
3538
fn batch_size() -> usize {
3639
std::env::var("EMBEDDINGS_BATCH_SIZE")
3740
.ok()
@@ -45,22 +48,34 @@ fn available_cpus() -> usize {
4548
.unwrap_or(2)
4649
}
4750

48-
/// Number of parallel ORT sessions. Default: num_cpus / 2 (min 1).
49-
/// Moderate oversubscription (total_threads ≈ 2×cores) fills idle gaps between ORT ops.
50-
fn num_sessions() -> usize {
51-
std::env::var("EMBEDDINGS_NUM_SESSIONS")
51+
/// Max total ORT threads budget. Default: 2 × num_cpus (optimal oversubscription).
52+
/// Controls how many threads all sessions combined can use.
53+
fn max_threads() -> usize {
54+
std::env::var("EMBEDDINGS_MAX_THREADS")
5255
.ok()
5356
.and_then(|v| v.parse().ok())
54-
.unwrap_or_else(|| (available_cpus() / 2).max(1))
57+
.unwrap_or_else(|| available_cpus() * 2)
5558
}
5659

57-
/// Intra-op threads per session. Default: 4.
58-
/// With num_sessions = cpus/2, total threads = cpus/2 * 4 = 2×cpus — optimal oversubscription.
60+
/// Intra-op threads per session.
5961
fn intra_threads() -> usize {
6062
std::env::var("EMBEDDINGS_INTRA_THREADS")
6163
.ok()
6264
.and_then(|v| v.parse().ok())
63-
.unwrap_or(4)
65+
.unwrap_or(DEFAULT_INTRA_THREADS)
66+
}
67+
68+
/// Number of parallel ORT sessions, derived from thread budget.
69+
/// total_threads = num_sessions × intra_threads ≤ max_threads
70+
fn num_sessions() -> usize {
71+
let ns = std::env::var("EMBEDDINGS_NUM_SESSIONS")
72+
.ok()
73+
.and_then(|v| v.parse().ok())
74+
.unwrap_or_else(|| (max_threads() / intra_threads()).max(1));
75+
// Cap so total threads don't exceed budget
76+
let it = intra_threads();
77+
let mt = max_threads();
78+
(mt / it).max(1).min(ns)
6479
}
6580

6681
/// Model architecture type - determines pooling strategy

0 commit comments

Comments
 (0)