Both inference call sites previously called `num_cpus::get()` (logical
thread count). Established whisper.cpp / llama.cpp guidance is that
SMT siblings contend for shared FPU resources during heavy F16/F32
matmul, so going past physical core count anti-scales. Empirical
sweep on Whisper Tiny / 11s JFK clip / Ryzen 5 4650U (6c12t):
n_threads | xc_time | RTF | speedup_vs_1
----------|---------|--------|-------------
1 | 0.33s | 0.030 | 1.00x
2 | 0.33s | 0.030 | 1.00x
4 | 0.30s | 0.028 | 1.09x
6 | 0.32s | 0.029 | 1.04x
8 | 0.31s | 0.028 | 1.06x
12 | 0.32s | 0.029 | 1.03x
Tiny doesn't scale (work dominated by overhead) but the larger
Whisper variants and Qwen LLMs do. Sources: whisper.cpp #200, #1033,
#1252, #403; llama.cpp #3167, #572.
Changes:
- crates/core/src/constants.rs:
* MIN_INFERENCE_THREADS lowered 4 → 2 (research-derived floor)
* MAX_INFERENCE_THREADS = 8 added (research-derived ceiling)
* inference_thread_count() rewritten:
- reads MAGNOTIA_INFERENCE_THREADS env var (override)
- num_cpus::get_physical() with available_parallelism fallback
- clamped to [MIN_INFERENCE_THREADS, MAX_INFERENCE_THREADS]
- crates/core/Cargo.toml: + num_cpus = "1"
- crates/transcription/src/whisper_rs_backend.rs: call site uses helper.
- crates/llm/src/lib.rs: call site uses helper.
- crates/transcription/Cargo.toml: drop num_cpus from [features] +
[dependencies] (production no longer needs it). Move to
[dev-dependencies] for tests/thread_sweep.rs only.
- crates/llm/Cargo.toml: drop num_cpus = "1" (no longer used directly).
Per-machine maps (after this patch):
Ryzen 5 4650U 6c12t → 6
big-iron 12c24t → 8 (clamp; users can override)
cheap 2c2t laptop → 2
1c container/VM → 2
Adds crates/transcription/tests/thread_sweep.rs — env-gated like
jfk_bench, prints the table above against any model + WAV. Useful for
re-baselining on new hardware or when tuning the clamp values.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
33 lines
1.2 KiB
TOML
33 lines
1.2 KiB
TOML
[package]
|
|
name = "magnotia-llm"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
description = "Local LLM engine for Magnotia (Qwen3.5 / Qwen3.6 via llama-cpp-2): transcript cleanup, task extraction, micro-step decomposition"
|
|
|
|
[features]
|
|
# Default desktop build keeps the existing openmp + vulkan acceleration.
|
|
# Mobile / CPU-only targets can drop one or both via:
|
|
# cargo build -p magnotia-llm --no-default-features
|
|
# These are independent so an Android Vulkan build can opt into vulkan
|
|
# without openmp (the NDK ships OpenMP libs but the toolchain configuration
|
|
# is fragile across NDK versions).
|
|
default = ["gpu-vulkan", "openmp"]
|
|
gpu-vulkan = ["llama-cpp-2/vulkan"]
|
|
openmp = ["llama-cpp-2/openmp"]
|
|
|
|
[dependencies]
|
|
magnotia-core = { path = "../core" }
|
|
encoding_rs = "0.8"
|
|
futures-util = "0.3"
|
|
llama-cpp-2 = { version = "0.1.144", default-features = false }
|
|
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "stream"] }
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
sha2 = "0.10"
|
|
thiserror = "2"
|
|
tokio = { version = "1", features = ["fs", "io-util", "macros", "net", "rt-multi-thread", "sync", "time"] }
|
|
tracing = "0.1"
|
|
|
|
[dev-dependencies]
|
|
tempfile = "3"
|