Skip to content

Commit dee799e

Browse files
committed
Allow server backend selection
1 parent acde132 commit dee799e

7 files changed

Lines changed: 66 additions & 4 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ cat > server.json <<'JSON'
505505
{
506506
"host": "127.0.0.1",
507507
"port": 8080,
508+
"backend": "cuda",
508509
"device": 0,
509510
"threads": 1,
510511
"lazy_load": true,
@@ -536,6 +537,8 @@ JSON
536537

537538
Set `"lazy_load": true` to register configured model ids at startup while loading each model only on first use. Use per-model `"lazy": true` or `"lazy": false` to override that default.
538539

540+
Set top-level `"backend"` to `"cuda"`, `"cpu"`, `"vulkan"`, or `"metal"`. CUDA is the optimized path for audio.cpp; CPU, Vulkan, and Metal are intended for portability and testing when the binary is built with that backend, but performance and model coverage may be lower.
541+
539542
> [!WARNING]
540543
> Lazy loading does not unload models after a request. Once a model is first used, the server keeps that model and session in memory for reuse until the server exits.
541544

app/server/README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# audio.cpp Server
22

3-
`audiocpp_server` is a CUDA-only HTTP adapter over the framework runtime registry. It keeps one loaded model and one offline task session per active model id, so repeated HTTP requests reuse the same framework session and model-owned graph/cache state.
3+
`audiocpp_server` is an HTTP adapter over the framework runtime registry. It keeps one loaded model and one offline task session per active model id, so repeated HTTP requests reuse the same framework session and model-owned graph/cache state.
44

55
## Build
66

@@ -9,13 +9,16 @@ cmake -S . -B build -DENGINE_ENABLE_CUDA=ON
99
cmake --build build --parallel --target audiocpp_server
1010
```
1111

12+
Enable the backend you plan to run: `ENGINE_ENABLE_CUDA=ON` for CUDA, `ENGINE_ENABLE_VULKAN=ON` for Vulkan, or `ENGINE_ENABLE_METAL=ON` for Metal. CPU support is always available.
13+
1214
## Config
1315

1416
```bash
1517
cat > server.json <<'JSON'
1618
{
1719
"host": "127.0.0.1",
1820
"port": 8080,
21+
"backend": "cuda",
1922
"device": 0,
2023
"threads": 1,
2124
"lazy_load": true,
@@ -47,6 +50,8 @@ JSON
4750

4851
The server resolves model paths from this JSON exactly as written, so use paths that match your machine. Request-time audio paths are also user-provided paths.
4952

53+
Set top-level `"backend"` to `"cuda"`, `"cpu"`, `"vulkan"`, or `"metal"`. CUDA is the optimized path for audio.cpp; CPU, Vulkan, and Metal are intended for portability and testing when the binary is built with that backend, but performance and model coverage may be lower. The server prints this expectation-setting message when a non-CUDA backend is selected.
54+
5055
Set top-level `"lazy_load": true` to register all configured model ids at startup but defer each model's framework load and session creation until its first request. A model can override the default with `"lazy": true` or `"lazy": false`.
5156

5257
> [!WARNING]
@@ -58,6 +63,12 @@ Set top-level `"lazy_load": true` to register all configured model ids at startu
5863
build/bin/audiocpp_server --config server.json
5964
```
6065

66+
You can override the configured backend at startup:
67+
68+
```bash
69+
build/bin/audiocpp_server --config server.json --backend vulkan
70+
```
71+
6172
## Endpoints
6273

6374
### `GET /health`

app/server/config.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "config.h"
22

3+
#include "../cli/args.h"
34
#include "../cli/request.h"
45

56
#include "engine/framework/io/json.h"
@@ -20,12 +21,21 @@ std::unordered_map<std::string, std::string> options_from_object(const engine::i
2021

2122
} // namespace
2223

24+
engine::core::BackendType parse_server_backend(const std::string & value) {
25+
auto backend = minitts::cli::parse_backend(value);
26+
if (backend == engine::core::BackendType::BestAvailable) {
27+
throw std::runtime_error("unsupported server backend: " + value);
28+
}
29+
return backend;
30+
}
31+
2332
ServerConfig load_server_config(const std::filesystem::path & path) {
2433
const auto root = engine::io::json::parse_file(path);
2534
const auto base = path.parent_path();
2635
ServerConfig config;
2736
config.host = engine::io::json::optional_string(root, "host", config.host);
2837
config.port = engine::io::json::optional_i32(root, "port", config.port);
38+
config.backend = parse_server_backend(engine::io::json::optional_string(root, "backend", "cuda"));
2939
config.device = engine::io::json::optional_i32(root, "device", config.device);
3040
config.threads = engine::io::json::optional_i32(root, "threads", config.threads);
3141
config.lazy_load = engine::io::json::optional_bool(root, "lazy_load", config.lazy_load);

app/server/config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <unordered_map>
77
#include <vector>
88

9+
#include "engine/framework/core/backend.h"
10+
911
namespace minitts::server {
1012

1113
struct ServerModelConfig {
@@ -24,12 +26,14 @@ struct ServerModelConfig {
2426
struct ServerConfig {
2527
std::string host = "127.0.0.1";
2628
int port = 8080;
29+
engine::core::BackendType backend = engine::core::BackendType::Cuda;
2730
int device = 0;
2831
int threads = 1;
2932
bool lazy_load = false;
3033
std::vector<ServerModelConfig> models;
3134
};
3235

36+
engine::core::BackendType parse_server_backend(const std::string & value);
3337
ServerConfig load_server_config(const std::filesystem::path & path);
3438

3539
} // namespace minitts::server

app/server/example.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"host": "127.0.0.1",
33
"port": 8080,
4+
"backend": "cuda",
45
"device": 0,
56
"threads": 1,
67
"lazy_load": true,

app/server/main.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ bool has_arg(int argc, char ** argv, const std::string & name) {
3232

3333
void print_help() {
3434
std::cout
35-
<< "audiocpp_server --config <server.json> [--host <ip>] [--port <port>] [--device <id>] [--threads <n>]\n"
35+
<< "audiocpp_server --config <server.json> [--host <ip>] [--port <port>] [--backend <backend>]\n"
36+
<< " [--device <id>] [--threads <n>]\n"
3637
<< " [--log] [--log-file <path>]\n"
38+
<< " --backend cpu|cuda|vulkan|metal default cuda\n"
3739
<< "\n"
3840
<< "Endpoints:\n"
3941
<< " GET /health\n"
@@ -68,6 +70,9 @@ int main(int argc, char ** argv) {
6870
if (const auto port = arg_value(argc, argv, "--port")) {
6971
config.port = std::stoi(*port);
7072
}
73+
if (const auto backend = arg_value(argc, argv, "--backend")) {
74+
config.backend = minitts::server::parse_server_backend(*backend);
75+
}
7176
if (const auto device = arg_value(argc, argv, "--device")) {
7277
config.device = std::stoi(*device);
7378
}

app/server/runtime.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <chrono>
1010
#include <cmath>
1111
#include <cstdint>
12+
#include <iostream>
1213
#include <sstream>
1314
#include <stdexcept>
1415
#include <unordered_map>
@@ -29,6 +30,22 @@ std::filesystem::path resolve_path(const std::filesystem::path & base, const std
2930
return path.is_absolute() ? path : base / path;
3031
}
3132

33+
const char * backend_name(engine::core::BackendType type) {
34+
switch (type) {
35+
case engine::core::BackendType::Cpu:
36+
return "cpu";
37+
case engine::core::BackendType::Cuda:
38+
return "cuda";
39+
case engine::core::BackendType::Vulkan:
40+
return "vulkan";
41+
case engine::core::BackendType::Metal:
42+
return "metal";
43+
case engine::core::BackendType::BestAvailable:
44+
return "best";
45+
}
46+
return "unknown";
47+
}
48+
3249
std::unordered_map<std::string, std::string> options_from_object(const Value * value) {
3350
return minitts::cli::json_options_map(value);
3451
}
@@ -336,12 +353,23 @@ engine::runtime::TaskRequest build_openai_transcription_request(const Value & bo
336353
ServerState::ServerState(ServerConfig config, std::filesystem::path request_base)
337354
: config_(std::move(config)),
338355
request_base_(std::move(request_base)) {
356+
if (config_.backend != engine::core::BackendType::Cuda) {
357+
std::cerr
358+
<< "audio.cpp is optimized for CUDA. The "
359+
<< backend_name(config_.backend)
360+
<< " server backend is intended for portability and testing, but performance and model coverage may be lower than CUDA.\n";
361+
}
339362
load_models();
340363
}
341364

342365
HttpResponse ServerState::handle(const HttpRequest & request) {
343366
if (request.method == "GET" && request.path == "/health") {
344-
return json_response("{\"status\":\"ok\",\"backend\":\"cuda\",\"models\":" + std::to_string(models_.size()) + "}");
367+
return json_response(
368+
"{\"status\":\"ok\",\"backend\":\"" +
369+
std::string(backend_name(config_.backend)) +
370+
"\",\"models\":" +
371+
std::to_string(models_.size()) +
372+
"}");
345373
}
346374
if (request.method == "GET" && request.path == "/v1/models") {
347375
return json_response(models_json());
@@ -393,7 +421,7 @@ void ServerState::ensure_model_loaded_locked(LoadedModel & model) {
393421
load_request.options = model.config.load_options;
394422

395423
engine::runtime::SessionOptions session_options;
396-
session_options.backend.type = engine::core::BackendType::Cuda;
424+
session_options.backend.type = config_.backend;
397425
session_options.backend.device = config_.device;
398426
session_options.backend.threads = config_.threads;
399427
session_options.options = model.config.session_options;

0 commit comments

Comments
 (0)