diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ebd829a..17870058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1848,6 +1848,20 @@ endif() if (ENGINE_BUILD_TESTS) enable_testing() + add_test( + NAME audiocpp_cli_list_devices + COMMAND audiocpp_cli --list-devices + ) + add_test( + NAME audiocpp_server_list_devices + COMMAND audiocpp_server --list-devices + ) + set_tests_properties( + audiocpp_cli_list_devices + audiocpp_server_list_devices + PROPERTIES PASS_REGULAR_EXPRESSION "available_devices=[0-9]+" + ) + set(ENGINE_UNITTEST_ASSET_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/tests/unittests/assets") function(add_engine_unittest target source) diff --git a/app/cli/main.cpp b/app/cli/main.cpp index 37b2a3e5..affe12bd 100644 --- a/app/cli/main.cpp +++ b/app/cli/main.cpp @@ -648,16 +648,7 @@ int audiocpp_cli_main(int argc, char ** argv) { return 0; } if (has_arg(argc, argv, "--list-devices")) { - const auto devices = engine::core::list_backend_devices(); - std::cout << "available_devices=" << devices.size() << "\n"; - for (const auto & device : devices) { - std::cout << device.backend << ":" << device.index; - if (!device.name.empty()) { - std::cout << " \"" << device.name << "\""; - } - std::cout << " [" << device.type << "]\n"; - } - std::cout << "select with: --backend --device \n"; + engine::core::print_backend_devices(std::cout); return 0; } if (has_arg(argc, argv, "--list-loaders")) { diff --git a/app/server/main.cpp b/app/server/main.cpp index 348988d6..d3e6fdd9 100644 --- a/app/server/main.cpp +++ b/app/server/main.cpp @@ -2,6 +2,7 @@ #include "http.h" #include "runtime.h" +#include "engine/framework/core/backend.h" #include "engine/framework/debug/trace.h" #include @@ -60,7 +61,8 @@ std::filesystem::path executable_directory(const char * argv0) { void print_help() { std::cout << "audiocpp_server [--config ] [--ui] [--host ] [--port ] [--backend ]\n" - << " [--device ] [--threads ] [--busy-timeout-ms ] [--max-loaded-models ]\n" + << " [--device ] [--list-devices] [--threads ] [--busy-timeout-ms ]\n" + << " [--max-loaded-models ]\n" << " [--model-spec-override ] [--voice-dir ]\n" << " [--log] [--log-file ]\n" << " [--cors-origins ]\n" @@ -69,6 +71,7 @@ void print_help() { << " --ui-management allow WebUI model management and downloads; requires\n" << " AUDIOCPP_BUILD_NATIVE_MODEL_MANAGER=ON at build time\n" << " --backend cpu|cuda|hip|rocm|vulkan|metal default cuda (rocm is an alias for hip)\n" + << " --list-devices list available backend devices and exit\n" << " --busy-timeout-ms fail a request with 503 when the model has been\n" << " busy this long; default 300000, 0 disables\n" << " --max-loaded-models keep at most n models resident in memory, unloading\n" @@ -110,6 +113,10 @@ void print_help() { int main(int argc, char ** argv) { try { + if (has_arg(argc, argv, "--list-devices")) { + engine::core::print_backend_devices(std::cout); + return 0; + } if (has_arg(argc, argv, "--help") || has_arg(argc, argv, "-h")) { print_help(); return 0; diff --git a/include/engine/framework/core/backend.h b/include/engine/framework/core/backend.h index 782667e8..d56637e8 100644 --- a/include/engine/framework/core/backend.h +++ b/include/engine/framework/core/backend.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -29,6 +30,7 @@ struct BackendDeviceInfo { // Enumerates every device of every loaded ggml backend registry, in registry order. std::vector list_backend_devices(); +void print_backend_devices(std::ostream & out); struct BackendMemorySnapshot { bool available = false; diff --git a/src/framework/core/backend.cpp b/src/framework/core/backend.cpp index 0297b51c..afb5489e 100644 --- a/src/framework/core/backend.cpp +++ b/src/framework/core/backend.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -209,6 +210,19 @@ std::vector list_backend_devices() { return devices; } +void print_backend_devices(std::ostream & out) { + const auto devices = list_backend_devices(); + out << "available_devices=" << devices.size() << "\n"; + for (const auto & device : devices) { + out << device.backend << ":" << device.index; + if (!device.name.empty()) { + out << " \"" << device.name << "\""; + } + out << " [" << device.type << "]\n"; + } + out << "select with: --backend --device \n"; +} + ggml_backend_t init_backend(const BackendConfig & config) { ensure_backends_loaded(); switch (config.type) {