From 4bde2578b5bbc98d599c58c0a3d04f6c180708d2 Mon Sep 17 00:00:00 2001 From: Gabriel Reus Rodriguez Date: Sun, 14 Jun 2026 01:26:22 +0200 Subject: [PATCH 1/8] ROCm: Selector by lemonade cli of the rocm architecture to use --- CMakeLists.txt | 1 + src/cpp/cli/CMakeLists.txt | 1 + src/cpp/cli/lemonade_client.cpp | 161 ++++++++++++++++++ src/cpp/cli/main.cpp | 22 +++ src/cpp/include/lemon/runtime_config.h | 3 + src/cpp/include/lemon/utils/rocm_arch_utils.h | 11 ++ src/cpp/include/lemon_cli/lemonade_client.h | 12 ++ src/cpp/server/runtime_config.cpp | 52 ++++++ src/cpp/server/system_info.cpp | 8 + src/cpp/server/utils/rocm_arch_utils.cpp | 37 ++++ 10 files changed, 308 insertions(+) create mode 100644 src/cpp/include/lemon/utils/rocm_arch_utils.h create mode 100644 src/cpp/server/utils/rocm_arch_utils.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c1844707a5..6d23224d30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -597,6 +597,7 @@ set(SOURCES_CORE src/cpp/server/utils/version_utils.cpp src/cpp/server/utils/wmi_helper.cpp src/cpp/server/utils/network_beacon.cpp + src/cpp/server/utils/rocm_arch_utils.cpp src/cpp/server/backends/llamacpp_server.cpp src/cpp/server/backends/fastflowlm_server.cpp src/cpp/server/backends/ryzenaiserver.cpp diff --git a/src/cpp/cli/CMakeLists.txt b/src/cpp/cli/CMakeLists.txt index 04e32e874e..4782111029 100644 --- a/src/cpp/cli/CMakeLists.txt +++ b/src/cpp/cli/CMakeLists.txt @@ -92,6 +92,7 @@ set(COMMON_SOURCES ../server/utils/path_utils.cpp ../server/utils/json_utils.cpp ../server/utils/http_client.cpp + ../server/utils/rocm_arch_utils.cpp agent_launcher.cpp agent_config_file.cpp opencode_profile.cpp diff --git a/src/cpp/cli/lemonade_client.cpp b/src/cpp/cli/lemonade_client.cpp index af8446552f..b586a90801 100644 --- a/src/cpp/cli/lemonade_client.cpp +++ b/src/cpp/cli/lemonade_client.cpp @@ -7,6 +7,9 @@ #include #include +#include "lemon/utils/json_utils.h" +#include "lemon/utils/rocm_arch_utils.h" + namespace lemonade { using json = nlohmann::json; @@ -454,6 +457,164 @@ int LemonadeClient::list_models(bool show_all, const std::string& name_filter) c } } +int LemonadeClient::set_rocm_arch(const std::string& rocm_arch) const{ + + if (rocm_arch.empty()) { + std::cerr << "Error Rocm arch value is empty" << std::endl; + return 1; + } + + // Check if the rocm_arch var exists at server config.json + try { + std::string config_response = make_request("/internal/config"); + auto json_config_response = json::parse(config_response); + if (!json_config_response.contains("rocm_arch")) { + std::cout << "You do NOT have the rocm_arch config var in your config.json" << std::endl; + return 0; + } + } catch (const HttpError& e) { + std::cerr << "Error checking rocm_arch config var: " << extract_server_error_message(e) << std::endl; + return 1; + } catch (const std::exception& e) { + std::cerr << "Error checking rocm_arch config var: " << e.what() << std::endl; + return 1; + } + + // Check if an active gpu with Rocm arch exists at server. We only check if it is NOT auto. + if (rocm_arch != "auto") { + bool rocm_arch_found = false; + try { + std::string response = make_request("/api/v1/system-info"); + auto json_response = json::parse(response); + if (json_response.contains("devices")) { + const auto& device = json_response["devices"]; + // AMD + if (device.contains("amd_gpu")) { + if (device["amd_gpu"].is_array()) { + for (const auto& amd_gpu : device["amd_gpu"]) { + if (amd_gpu.contains("available") && amd_gpu["available"].is_boolean() && amd_gpu["available"]) { + if (rocm_arch == lemon::rocm_arch_numeric_to_gfx(amd_gpu["name"])) { + rocm_arch_found = true; + break; + } + } + } + } + } + } + if (!rocm_arch_found) { + std::cerr << "Error there is not any active gpu with that ROCm arch " << std::endl; + return 1; + } + } catch (const HttpError& e) { + std::cerr << "Error setting ROCm arch: " << extract_server_error_message(e) << std::endl; + return 1; + } catch (const json::exception& e) { + std::cerr << "Error parsing system-info JSON: " << e.what() << std::endl; + return 1; + } catch (const std::exception& e) { + std::cerr << "Error setting ROCm arch: " << e.what() << std::endl; + return 1; + } + } + + //Set the config var. + try { + json request_body = {{"rocm_arch", rocm_arch}}; + std::string response = make_request("/internal/set", "POST", request_body.dump(), "application/json"); + + auto response_json = json::parse(response); + if (response_json.contains("status") && response_json["status"] == "success") { + std::cout << "ROCm arch setted successfully: " << rocm_arch << std::endl; + return 0; + } else { + std::cerr << "Failed to set rocm_arch config var" << std::endl; + return 1; + } + } catch (const HttpError& e) { + std::cerr << "Error setting ROCm architecture: " << extract_server_error_message(e) << std::endl; + return 1; + } catch (const json::exception& e) { + std::cerr << "Error parsing rocm_arch set response JSON: " << e.what() << std::endl; + return 1; + } catch (const std::exception& e) { + std::cerr << "Error setting ROCm architecture: " << e.what() << std::endl; + return 1; + } +} + +int LemonadeClient::list_rocm_archs() const { + + // Check if rocm_archs config var exists at server. + try { + std::string config_response = make_request("/internal/config"); + auto json_config_response = json::parse(config_response); + if (!json_config_response.contains("rocm_arch")) { + std::cout << "You do NOT have the rocm_arch config var in your config.json" << std::endl; + return 0; + } + + } catch (const HttpError& e) { + std::cerr << "Error listing ROCm architectures: " << extract_server_error_message(e) << std::endl; + return 1; + } catch (const std::exception& e) { + std::cerr << "Error listing ROCm architectures: " << e.what() << std::endl; + return 1; + } + + std::cout << "List of avaible ROCm architectures." << std::endl; + std::cout << "---------------------" << std::endl; + std::vector gpus_amd; + std::vector gpus_nvidia; + + try { + std::string response = make_request("/api/v1/system-info"); + auto json_response = json::parse(response); + if (json_response.contains("devices")) { + GpuInfo gpu; + const auto& device = json_response["devices"]; + + // AMD + if (device.contains("amd_gpu")) { + if (device["amd_gpu"].is_array()) { + for (const auto& amd_gpu : device["amd_gpu"]) { + if (amd_gpu.contains("available") && amd_gpu["available"].is_boolean() && amd_gpu["available"]) { + gpu.manufacturer = "AMD"; + gpu.family = amd_gpu["family"]; + gpu.name = lemon::rocm_arch_numeric_to_gfx(amd_gpu["name"]); + gpu.vram_gb = amd_gpu["vram_gb"]; + gpus_amd.push_back(gpu); + } + } + } + + } + } + + std::cout << "Active AMD GPUs detected" << std::endl; + std::cout << "----------------------------------------------" << std::endl; + std::cout << "architecture\t| vram (GB)\t|" << std::endl; + for (const auto& gpu : gpus_amd) { + + std::cout << " " << gpu.name << "\t" << " " << gpu.vram_gb << std::endl; + } + std::cout << "----------------------------------------------" << std::endl << std::endl; + return 0; + + } catch (const HttpError& e) { + std::cerr << "Error listing gpus: " << extract_server_error_message(e) << std::endl; + //return {}; + return 1; + } catch (const json::exception& e) { + std::cerr << "Error parsing gpus JSON: " << e.what() << std::endl; + return 1; + } catch (const std::exception& e) { + std::cerr << "Error listing gpus: " << e.what() << std::endl; + return 1; + } + +} + // Helper function to parse SSE progress events static std::string format_speed(double bytes_per_sec) { if (bytes_per_sec < 1024.0) { diff --git a/src/cpp/cli/main.cpp b/src/cpp/cli/main.cpp index 3c92c9ea3c..05e928bf79 100644 --- a/src/cpp/cli/main.cpp +++ b/src/cpp/cli/main.cpp @@ -163,6 +163,7 @@ struct CliConfig { bool codex_use_user_config = false; std::string codex_model_provider = "lemonade"; std::string agent_args; + std::string rocm_arch = ""; // Bench command options lemon_cli::BenchCliOptions bench; @@ -1024,6 +1025,16 @@ static int handle_scan_command(const CliConfig& config) { return 0; } +static int handle_rocm_arch_command(lemonade::LemonadeClient& client, + const CliConfig& config, + bool set_requested) { + if (set_requested) { + return client.set_rocm_arch(config.rocm_arch); + } else { + return client.list_rocm_archs(); + } +} + int main(int argc, char* argv[]) { // CLI11 configuration CLI::App app{"Lemonade CLI - HTTP client for Lemonade Server"}; @@ -1060,6 +1071,14 @@ int main(int argc, char* argv[]) { CLI::App* logs_cmd = app.add_subcommand("logs", "Open server logs in the web UI")->group("Server"); CLI::App* scan_cmd = app.add_subcommand("scan", "Scan for network beacons")->group("Server"); + // List rocm arch + CLI::App* rocm_arch_cmd = app.add_subcommand("rocm-arch", "View or modify ROCm architectures")->group("Server"); + // We add the subcommand set + CLI::App* rocm_arch_set_cmd = rocm_arch_cmd->add_subcommand("set", "Set ROCm architecture to use (e.g. gfx1200, gfx1150, ...)")->group("Subcommands"); + rocm_arch_set_cmd->add_option("rocm_arch", config.rocm_arch, "ROCm architecture to use")->required(); + rocm_arch_set_cmd->allow_extras(true); + rocm_arch_set_cmd->fallthrough(false); + // Config commands CLI::App* config_cmd = app.add_subcommand("config", "View or modify server configuration")->group("Server"); CLI::App* config_set_cmd = config_cmd->add_subcommand("set", "Set configuration values (e.g., llamacpp.backend=rocm port=8123)")->group("Subcommands"); @@ -1291,6 +1310,9 @@ int main(int argc, char* argv[]) { return handle_config_view(client); } else if (cleanup_cmd->count() > 0) { return client.cleanup_cache(config.dry_run); + } else if (rocm_arch_cmd->count() > 0) { + return handle_rocm_arch_command(client, config, + rocm_arch_set_cmd->count() > 0); } else if (bench_cmd->count() > 0) { auto bench_config = lemon_cli::build_bench_config(config.output_file, config.bench); return lemon_cli::handle_bench_command(client, bench_config); diff --git a/src/cpp/include/lemon/runtime_config.h b/src/cpp/include/lemon/runtime_config.h index 6baaef5d67..8549049c45 100644 --- a/src/cpp/include/lemon/runtime_config.h +++ b/src/cpp/include/lemon/runtime_config.h @@ -39,6 +39,7 @@ class RuntimeConfig { bool enable_dgpu_gtt() const; std::string rocm_channel() const; std::string rocm_channel_for_recipe(const std::string& recipe) const; + std::string rocm_arch() const; // Backend settings (nested) json backend_config(const std::string& backend_name) const; @@ -97,6 +98,8 @@ class RuntimeConfig { const std::string& key, const std::string& value); + static void validate_rocm_arch(const std::string& rocm_arch); + private: // Validate a single key/value pair. Throws std::invalid_argument on failure. void validate(const std::string& key, const json& value) const; diff --git a/src/cpp/include/lemon/utils/rocm_arch_utils.h b/src/cpp/include/lemon/utils/rocm_arch_utils.h new file mode 100644 index 0000000000..3b76a30b6f --- /dev/null +++ b/src/cpp/include/lemon/utils/rocm_arch_utils.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace lemon { + +std::string rocm_arch_numeric_to_gfx(const std::string& numeric_version); +bool rocm_arch_is_valid_gfx(const std::string& gfx_arch); + + +} // namespace lemon \ No newline at end of file diff --git a/src/cpp/include/lemon_cli/lemonade_client.h b/src/cpp/include/lemon_cli/lemonade_client.h index 16df8ae96e..88fbe90f09 100644 --- a/src/cpp/include/lemon_cli/lemonade_client.h +++ b/src/cpp/include/lemon_cli/lemonade_client.h @@ -54,6 +54,14 @@ struct ModelInfo { std::string description; }; +//GPU information structure +struct GpuInfo { + std::string manufacturer; + std::string family; + std::string name; + float vram_gb; +}; + // Recipe backend status structure struct BackendStatus { std::string name; @@ -97,6 +105,10 @@ class LemonadeClient { int install_backend(const std::string& recipe, const std::string& backend, bool force = false); int uninstall_backend(const std::string& recipe, const std::string& backend); + // Gpu selector commands + int list_rocm_archs() const; + int set_rocm_arch(const std::string& rocm_arch) const; + // Cache management int cleanup_cache(bool dry_run) const; diff --git a/src/cpp/server/runtime_config.cpp b/src/cpp/server/runtime_config.cpp index e1410f3c30..e405270746 100644 --- a/src/cpp/server/runtime_config.cpp +++ b/src/cpp/server/runtime_config.cpp @@ -2,6 +2,7 @@ #include "lemon/system_info.h" #include "lemon/utils/aixlog.hpp" #include "lemon/utils/path_utils.h" +#include "lemon/utils/rocm_arch_utils.h" #include #include #include @@ -131,6 +132,38 @@ void RuntimeConfig::validate_bin_path(const std::string& config_section, // error if the tag does not exist on GitHub. } +void RuntimeConfig::validate_rocm_arch(const std::string& rocm_arch) { + + // We check if rocm_arch has the correct format and if we have an active gpu with that architecture. + + if (rocm_arch != "auto" && !rocm_arch_is_valid_gfx(rocm_arch)) { + throw std::invalid_argument("'rocm_arch' has NOT valid format"); + } + if (rocm_arch != "auto") { + bool rocm_arch_found = false; + json system_info = SystemInfoCache::get_system_info_with_cache(); + if (system_info.contains("devices")) { + const auto& device = system_info["devices"]; + // AMD + if (device.contains("amd_gpu")) { + if (device["amd_gpu"].is_array()) { + for (const auto& amd_gpu : device["amd_gpu"]) { + if (amd_gpu.contains("available") && amd_gpu["available"].is_boolean() && amd_gpu["available"]) { + if (rocm_arch == rocm_arch_numeric_to_gfx(amd_gpu["name"])) { + rocm_arch_found = true; + break; + } + } + } + } + } + } + if (!rocm_arch_found) { + throw std::invalid_argument("There is NOT active GPU with selected 'rocm_arch'"); + } + } +} + RuntimeConfig::RuntimeConfig(const json& config) : config_(config) { // Config is expected to already have defaults merged in (by ConfigFile::load). @@ -231,6 +264,14 @@ std::string RuntimeConfig::rocm_channel_for_recipe(const std::string& recipe) co return channel; } +std::string RuntimeConfig::rocm_arch() const{ + std::shared_lock lock(mutex_); + if (config_.contains("rocm_arch")){ + return config_["rocm_arch"].get(); + } + return ""; +} + json RuntimeConfig::backend_config(const std::string& backend_name) const { std::shared_lock lock(mutex_); if (config_.contains(backend_name) && config_[backend_name].is_object()) { @@ -426,6 +467,17 @@ void RuntimeConfig::validate(const std::string& key, const json& value) const { if (channel != "stable" && channel != "nightly") { throw std::invalid_argument("'rocm_channel' must be either 'stable', or 'nightly'"); } + } else if (key == "rocm_arch") { + if (!value.is_string()) { + throw std::invalid_argument("'rocm_arch' must be a string"); + } + if (value != "auto" && !rocm_arch_is_valid_gfx(value)) { + throw std::invalid_argument("'rocm_arch' has NOT valid format"); + } + if (value != "auto") { + + } + //Opcional check si el sistema tiene activa esa arquitectura. } else if (is_backend_name(key)) { if (!value.is_object()) { throw std::invalid_argument("'" + key + "' must be an object"); diff --git a/src/cpp/server/system_info.cpp b/src/cpp/server/system_info.cpp index 6f74713499..d4f8e809fc 100644 --- a/src/cpp/server/system_info.cpp +++ b/src/cpp/server/system_info.cpp @@ -2085,6 +2085,13 @@ std::string identify_npu_arch() { std::string SystemInfo::get_rocm_arch() { // Returns the ROCm architecture for the best available AMD GPU on this system + // Check if user has defined gpu config var. + if (auto* cfg = RuntimeConfig::global()) { + std::string rocm_arch = cfg->rocm_arch(); + if (!rocm_arch.empty() && rocm_arch != "auto") { + return cfg->rocm_arch(); + } + } // Checks iGPU first, then dGPUs. Returns empty string if no compatible GPU found. try { // Use cached system info to avoid re-detecting GPUs @@ -2115,6 +2122,7 @@ std::string SystemInfo::get_rocm_arch() { } return ""; // No supported architecture found + } static int cuda_sm_value(const std::string& arch) { diff --git a/src/cpp/server/utils/rocm_arch_utils.cpp b/src/cpp/server/utils/rocm_arch_utils.cpp new file mode 100644 index 0000000000..2b2754e25f --- /dev/null +++ b/src/cpp/server/utils/rocm_arch_utils.cpp @@ -0,0 +1,37 @@ +#include +#include +#include + +namespace lemon{ + + +bool rocm_arch_is_valid_gfx(const std::string& gfx_arch) { + std::smatch gfx_match; + return std::regex_search(gfx_arch, gfx_match, std::regex(R"((gfx\d{4}))")); +} + +// In this function we tranform the rocm archictecture from numeric format to gfx format. +std::string rocm_arch_numeric_to_gfx(const std::string& numeric_arch) { + try { + // We convert the string with numeric version to long long number + long long num = std::stoll(numeric_arch); + + // We get the differents components of version. + long long major = num / 10000; + long long minor = (num / 100) % 100; + long long stepping = num % 100; + + // We build the gfx version with the previous components. + return "gfx" + std::to_string(major) + std::to_string(minor) + std::to_string(stepping); + } + catch (const std::invalid_argument& e) { + // The case that the conversion of stoll cannot be done. + throw std::invalid_argument("The numeric version is not a valid number"); + } + catch (const std::out_of_range& e) { + // The case that the conversion is bigger than long long limits. + throw std::invalid_argument("The numeric version is not a valid number"); + } +} + +} // namespace lemon \ No newline at end of file From b46f455d7e779e764e449ec48a9aed5bf16b9869 Mon Sep 17 00:00:00 2001 From: Gabriel Reus Rodriguez Date: Sun, 14 Jun 2026 14:21:05 +0200 Subject: [PATCH 2/8] Refactoring ROCm Arch Utils --- src/cpp/cli/lemonade_client.cpp | 63 +++++-------------- src/cpp/include/lemon/utils/rocm_arch_utils.h | 15 ++++- src/cpp/include/lemon_cli/lemonade_client.h | 8 --- src/cpp/server/runtime_config.cpp | 46 +++++--------- src/cpp/server/utils/rocm_arch_utils.cpp | 31 +++++++-- 5 files changed, 71 insertions(+), 92 deletions(-) diff --git a/src/cpp/cli/lemonade_client.cpp b/src/cpp/cli/lemonade_client.cpp index b586a90801..da47538df4 100644 --- a/src/cpp/cli/lemonade_client.cpp +++ b/src/cpp/cli/lemonade_client.cpp @@ -458,11 +458,7 @@ int LemonadeClient::list_models(bool show_all, const std::string& name_filter) c } int LemonadeClient::set_rocm_arch(const std::string& rocm_arch) const{ - - if (rocm_arch.empty()) { - std::cerr << "Error Rocm arch value is empty" << std::endl; - return 1; - } + std::vector rocm_devs; // Check if the rocm_arch var exists at server config.json try { @@ -481,24 +477,18 @@ int LemonadeClient::set_rocm_arch(const std::string& rocm_arch) const{ } // Check if an active gpu with Rocm arch exists at server. We only check if it is NOT auto. - if (rocm_arch != "auto") { + if (!rocm_arch.empty() && rocm_arch != "auto") { bool rocm_arch_found = false; try { std::string response = make_request("/api/v1/system-info"); auto json_response = json::parse(response); + if (json_response.contains("devices")) { - const auto& device = json_response["devices"]; - // AMD - if (device.contains("amd_gpu")) { - if (device["amd_gpu"].is_array()) { - for (const auto& amd_gpu : device["amd_gpu"]) { - if (amd_gpu.contains("available") && amd_gpu["available"].is_boolean() && amd_gpu["available"]) { - if (rocm_arch == lemon::rocm_arch_numeric_to_gfx(amd_gpu["name"])) { - rocm_arch_found = true; - break; - } - } - } + rocm_devs = lemon::ROCmArchUtils::rocm_arch_get_active_devices(json_response["devices"]); + for (const auto& rocm_dev : rocm_devs) { + if (rocm_arch == rocm_dev.name) { + rocm_arch_found = true; + break; } } } @@ -545,6 +535,8 @@ int LemonadeClient::set_rocm_arch(const std::string& rocm_arch) const{ int LemonadeClient::list_rocm_archs() const { + std::vector rocm_devs; + // Check if rocm_archs config var exists at server. try { std::string config_response = make_request("/internal/config"); @@ -562,41 +554,18 @@ int LemonadeClient::list_rocm_archs() const { return 1; } - std::cout << "List of avaible ROCm architectures." << std::endl; - std::cout << "---------------------" << std::endl; - std::vector gpus_amd; - std::vector gpus_nvidia; - try { + std::cout << "List of avaible ROCm architectures." << std::endl; + std::cout << "----------------------------------------------" << std::endl; std::string response = make_request("/api/v1/system-info"); auto json_response = json::parse(response); if (json_response.contains("devices")) { - GpuInfo gpu; - const auto& device = json_response["devices"]; - - // AMD - if (device.contains("amd_gpu")) { - if (device["amd_gpu"].is_array()) { - for (const auto& amd_gpu : device["amd_gpu"]) { - if (amd_gpu.contains("available") && amd_gpu["available"].is_boolean() && amd_gpu["available"]) { - gpu.manufacturer = "AMD"; - gpu.family = amd_gpu["family"]; - gpu.name = lemon::rocm_arch_numeric_to_gfx(amd_gpu["name"]); - gpu.vram_gb = amd_gpu["vram_gb"]; - gpus_amd.push_back(gpu); - } - } - } - - } - } - - std::cout << "Active AMD GPUs detected" << std::endl; - std::cout << "----------------------------------------------" << std::endl; + rocm_devs = lemon::ROCmArchUtils::rocm_arch_get_active_devices(json_response["devices"]); + } std::cout << "architecture\t| vram (GB)\t|" << std::endl; - for (const auto& gpu : gpus_amd) { + for (const auto& rocm_dev : rocm_devs) { - std::cout << " " << gpu.name << "\t" << " " << gpu.vram_gb << std::endl; + std::cout << " " << rocm_dev.name << "\t" << " " << rocm_dev.vram_gb << std::endl; } std::cout << "----------------------------------------------" << std::endl << std::endl; return 0; diff --git a/src/cpp/include/lemon/utils/rocm_arch_utils.h b/src/cpp/include/lemon/utils/rocm_arch_utils.h index 3b76a30b6f..049a62ba95 100644 --- a/src/cpp/include/lemon/utils/rocm_arch_utils.h +++ b/src/cpp/include/lemon/utils/rocm_arch_utils.h @@ -4,8 +4,19 @@ namespace lemon { -std::string rocm_arch_numeric_to_gfx(const std::string& numeric_version); -bool rocm_arch_is_valid_gfx(const std::string& gfx_arch); +//ROCm Device information structure +struct ROCmDeviceInfo { + std::string family; + std::string name; + std::string + float vram_gb; +}; +class ROCmArchUtils { + + static std::string rocm_arch_numeric_to_gfx(const std::string& numeric_version); + static bool rocm_arch_is_valid_gfx(const std::string& gfx_arch); + static std::vector rocm_arch_get_active_devices(const json& json_devices); +}; } // namespace lemon \ No newline at end of file diff --git a/src/cpp/include/lemon_cli/lemonade_client.h b/src/cpp/include/lemon_cli/lemonade_client.h index 88fbe90f09..51d965b13d 100644 --- a/src/cpp/include/lemon_cli/lemonade_client.h +++ b/src/cpp/include/lemon_cli/lemonade_client.h @@ -54,14 +54,6 @@ struct ModelInfo { std::string description; }; -//GPU information structure -struct GpuInfo { - std::string manufacturer; - std::string family; - std::string name; - float vram_gb; -}; - // Recipe backend status structure struct BackendStatus { std::string name; diff --git a/src/cpp/server/runtime_config.cpp b/src/cpp/server/runtime_config.cpp index e405270746..2ea0169582 100644 --- a/src/cpp/server/runtime_config.cpp +++ b/src/cpp/server/runtime_config.cpp @@ -133,34 +133,28 @@ void RuntimeConfig::validate_bin_path(const std::string& config_section, } void RuntimeConfig::validate_rocm_arch(const std::string& rocm_arch) { + std::vector rocm_devs; + bool rocm_arch_found = false; // We check if rocm_arch has the correct format and if we have an active gpu with that architecture. - - if (rocm_arch != "auto" && !rocm_arch_is_valid_gfx(rocm_arch)) { + if (!rocm_arch.empty() && rocm_arch != "auto" ) { + return ; + } + if (!rocm_arch_is_valid_gfx(rocm_arch)) { throw std::invalid_argument("'rocm_arch' has NOT valid format"); } - if (rocm_arch != "auto") { - bool rocm_arch_found = false; - json system_info = SystemInfoCache::get_system_info_with_cache(); - if (system_info.contains("devices")) { - const auto& device = system_info["devices"]; - // AMD - if (device.contains("amd_gpu")) { - if (device["amd_gpu"].is_array()) { - for (const auto& amd_gpu : device["amd_gpu"]) { - if (amd_gpu.contains("available") && amd_gpu["available"].is_boolean() && amd_gpu["available"]) { - if (rocm_arch == rocm_arch_numeric_to_gfx(amd_gpu["name"])) { - rocm_arch_found = true; - break; - } - } - } + json system_info = SystemInfoCache::get_system_info_with_cache(); + if (system_info.contains("devices")) { + rocm_devs = lemon::ROCmArchUtils::rocm_arch_get_active_devices(system_info["devices"]); + for (const auto& rocm_dev : rocm_devs) { + if (rocm_arch == rocm_dev.name) { + rocm_arch_found = true; + break; } } - } - if (!rocm_arch_found) { - throw std::invalid_argument("There is NOT active GPU with selected 'rocm_arch'"); - } + } + if (!rocm_arch_found) { + throw std::invalid_argument("There is NOT active GPU with selected 'rocm_arch'"); } } @@ -471,13 +465,7 @@ void RuntimeConfig::validate(const std::string& key, const json& value) const { if (!value.is_string()) { throw std::invalid_argument("'rocm_arch' must be a string"); } - if (value != "auto" && !rocm_arch_is_valid_gfx(value)) { - throw std::invalid_argument("'rocm_arch' has NOT valid format"); - } - if (value != "auto") { - - } - //Opcional check si el sistema tiene activa esa arquitectura. + validate_rocm_arch(value); } else if (is_backend_name(key)) { if (!value.is_object()) { throw std::invalid_argument("'" + key + "' must be an object"); diff --git a/src/cpp/server/utils/rocm_arch_utils.cpp b/src/cpp/server/utils/rocm_arch_utils.cpp index 2b2754e25f..496efb5651 100644 --- a/src/cpp/server/utils/rocm_arch_utils.cpp +++ b/src/cpp/server/utils/rocm_arch_utils.cpp @@ -4,15 +4,15 @@ namespace lemon{ - -bool rocm_arch_is_valid_gfx(const std::string& gfx_arch) { - std::smatch gfx_match; - return std::regex_search(gfx_arch, gfx_match, std::regex(R"((gfx\d{4}))")); +bool ROCmArchUtils::rocm_arch_is_valid_gfx(const std::string& gfx_arch) { + std::smatch gfx_match; + return std::regex_search(gfx_arch, gfx_match, std::regex(R"((gfx\d{4}))")); } // In this function we tranform the rocm archictecture from numeric format to gfx format. -std::string rocm_arch_numeric_to_gfx(const std::string& numeric_arch) { - try { +std::string ROCmArchUtils::rocm_arch_numeric_to_gfx(const std::string& numeric_arch) { + if rocm_arch_is_valid_gfx(const std::string& gfx_arch) + try { // We convert the string with numeric version to long long number long long num = std::stoll(numeric_arch); @@ -34,4 +34,23 @@ std::string rocm_arch_numeric_to_gfx(const std::string& numeric_arch) { } } +std::vector ROCmArchUtils::rocm_arch_get_active_devices(const json& devices) { + std::vector active_devs; + + if (device.contains("amd_gpu")) { + if (device["amd_gpu"].is_array()) { + for (const auto& amd_gpu : device["amd_gpu"]) { + ROCmDeviceInfo dev; + if (amd_gpu.contains("available") && amd_gpu["available"].is_boolean() && amd_gpu["available"]) { + dev.name = lemon::ROCmArchUtils::rocm_arch_numeric_to_gfx(amd_gpu["name"]); + dev.vram_gb = amd_gpu["vram_gb"]; + active_devs.push_back(dev); + } + } + } + } + return active_devs; +} + + } // namespace lemon \ No newline at end of file From f5bd908f7554b3e720836c226fc0f7cd21aecde2 Mon Sep 17 00:00:00 2001 From: Gabriel Reus Rodriguez Date: Sun, 14 Jun 2026 14:26:22 +0200 Subject: [PATCH 3/8] Refactoring comments : removing gpu references on comments and changing with the new var rocm-arch --- src/cpp/include/lemon_cli/lemonade_client.h | 2 +- src/cpp/server/system_info.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/include/lemon_cli/lemonade_client.h b/src/cpp/include/lemon_cli/lemonade_client.h index 51d965b13d..034a9c5267 100644 --- a/src/cpp/include/lemon_cli/lemonade_client.h +++ b/src/cpp/include/lemon_cli/lemonade_client.h @@ -97,7 +97,7 @@ class LemonadeClient { int install_backend(const std::string& recipe, const std::string& backend, bool force = false); int uninstall_backend(const std::string& recipe, const std::string& backend); - // Gpu selector commands + // Rocm-arch selector commands int list_rocm_archs() const; int set_rocm_arch(const std::string& rocm_arch) const; diff --git a/src/cpp/server/system_info.cpp b/src/cpp/server/system_info.cpp index d4f8e809fc..3e6b009c03 100644 --- a/src/cpp/server/system_info.cpp +++ b/src/cpp/server/system_info.cpp @@ -2085,7 +2085,7 @@ std::string identify_npu_arch() { std::string SystemInfo::get_rocm_arch() { // Returns the ROCm architecture for the best available AMD GPU on this system - // Check if user has defined gpu config var. + // Check if user has defined rocm_arch config var. if (auto* cfg = RuntimeConfig::global()) { std::string rocm_arch = cfg->rocm_arch(); if (!rocm_arch.empty() && rocm_arch != "auto") { From e6aa26fdf1f726efbca7dccffe7382bfe361cf9b Mon Sep 17 00:00:00 2001 From: Gabriel Reus Date: Sun, 14 Jun 2026 14:47:15 +0200 Subject: [PATCH 4/8] Added validation in rocm-arch set , now you cannot send empty arch --- src/cpp/cli/lemonade_client.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cpp/cli/lemonade_client.cpp b/src/cpp/cli/lemonade_client.cpp index da47538df4..7877bf907a 100644 --- a/src/cpp/cli/lemonade_client.cpp +++ b/src/cpp/cli/lemonade_client.cpp @@ -460,6 +460,11 @@ int LemonadeClient::list_models(bool show_all, const std::string& name_filter) c int LemonadeClient::set_rocm_arch(const std::string& rocm_arch) const{ std::vector rocm_devs; + if (rocm_arch.empty()) { + std::cerr << "Error Rocm arch value is empty" << std::endl; + return 1; + } + // Check if the rocm_arch var exists at server config.json try { std::string config_response = make_request("/internal/config"); From 21f5179bc425912dbc71d012ac982393b57274d2 Mon Sep 17 00:00:00 2001 From: Gabriel Reus Date: Sun, 14 Jun 2026 16:24:59 +0200 Subject: [PATCH 5/8] Solving compilation problems --- src/cpp/cli/lemonade_client.cpp | 4 ++-- src/cpp/include/lemon/utils/rocm_arch_utils.h | 5 ++++- src/cpp/server/runtime_config.cpp | 6 +++--- src/cpp/server/utils/rocm_arch_utils.cpp | 10 +++++----- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/cpp/cli/lemonade_client.cpp b/src/cpp/cli/lemonade_client.cpp index 7877bf907a..16ff0ba0aa 100644 --- a/src/cpp/cli/lemonade_client.cpp +++ b/src/cpp/cli/lemonade_client.cpp @@ -458,7 +458,7 @@ int LemonadeClient::list_models(bool show_all, const std::string& name_filter) c } int LemonadeClient::set_rocm_arch(const std::string& rocm_arch) const{ - std::vector rocm_devs; + std::vector rocm_devs; if (rocm_arch.empty()) { std::cerr << "Error Rocm arch value is empty" << std::endl; @@ -540,7 +540,7 @@ int LemonadeClient::set_rocm_arch(const std::string& rocm_arch) const{ int LemonadeClient::list_rocm_archs() const { - std::vector rocm_devs; + std::vector rocm_devs; // Check if rocm_archs config var exists at server. try { diff --git a/src/cpp/include/lemon/utils/rocm_arch_utils.h b/src/cpp/include/lemon/utils/rocm_arch_utils.h index 049a62ba95..5621eaeaff 100644 --- a/src/cpp/include/lemon/utils/rocm_arch_utils.h +++ b/src/cpp/include/lemon/utils/rocm_arch_utils.h @@ -1,19 +1,22 @@ #pragma once #include +#include namespace lemon { +using json = nlohmann::json; + //ROCm Device information structure struct ROCmDeviceInfo { std::string family; std::string name; - std::string float vram_gb; }; class ROCmArchUtils { +public: static std::string rocm_arch_numeric_to_gfx(const std::string& numeric_version); static bool rocm_arch_is_valid_gfx(const std::string& gfx_arch); static std::vector rocm_arch_get_active_devices(const json& json_devices); diff --git a/src/cpp/server/runtime_config.cpp b/src/cpp/server/runtime_config.cpp index 2ea0169582..0693ad5ff0 100644 --- a/src/cpp/server/runtime_config.cpp +++ b/src/cpp/server/runtime_config.cpp @@ -133,14 +133,14 @@ void RuntimeConfig::validate_bin_path(const std::string& config_section, } void RuntimeConfig::validate_rocm_arch(const std::string& rocm_arch) { - std::vector rocm_devs; + std::vector rocm_devs; bool rocm_arch_found = false; // We check if rocm_arch has the correct format and if we have an active gpu with that architecture. - if (!rocm_arch.empty() && rocm_arch != "auto" ) { + if (rocm_arch.empty() || rocm_arch == "auto" ) { return ; } - if (!rocm_arch_is_valid_gfx(rocm_arch)) { + if (!lemon::ROCmArchUtils::rocm_arch_is_valid_gfx(rocm_arch)) { throw std::invalid_argument("'rocm_arch' has NOT valid format"); } json system_info = SystemInfoCache::get_system_info_with_cache(); diff --git a/src/cpp/server/utils/rocm_arch_utils.cpp b/src/cpp/server/utils/rocm_arch_utils.cpp index 496efb5651..c18b1d952c 100644 --- a/src/cpp/server/utils/rocm_arch_utils.cpp +++ b/src/cpp/server/utils/rocm_arch_utils.cpp @@ -1,6 +1,7 @@ #include #include #include +#include "lemon/utils/rocm_arch_utils.h" namespace lemon{ @@ -11,8 +12,7 @@ bool ROCmArchUtils::rocm_arch_is_valid_gfx(const std::string& gfx_arch) { // In this function we tranform the rocm archictecture from numeric format to gfx format. std::string ROCmArchUtils::rocm_arch_numeric_to_gfx(const std::string& numeric_arch) { - if rocm_arch_is_valid_gfx(const std::string& gfx_arch) - try { + try { // We convert the string with numeric version to long long number long long num = std::stoll(numeric_arch); @@ -37,9 +37,9 @@ std::string ROCmArchUtils::rocm_arch_numeric_to_gfx(const std::string& numeric_a std::vector ROCmArchUtils::rocm_arch_get_active_devices(const json& devices) { std::vector active_devs; - if (device.contains("amd_gpu")) { - if (device["amd_gpu"].is_array()) { - for (const auto& amd_gpu : device["amd_gpu"]) { + if (devices.contains("amd_gpu")) { + if (devices["amd_gpu"].is_array()) { + for (const auto& amd_gpu : devices["amd_gpu"]) { ROCmDeviceInfo dev; if (amd_gpu.contains("available") && amd_gpu["available"].is_boolean() && amd_gpu["available"]) { dev.name = lemon::ROCmArchUtils::rocm_arch_numeric_to_gfx(amd_gpu["name"]); From 7453a656c1974b7cf10307f64fc86d53f26fcf47 Mon Sep 17 00:00:00 2001 From: Gabriel Reus Date: Sun, 14 Jun 2026 22:51:47 +0200 Subject: [PATCH 6/8] Refactoring rocm_translate --- src/cpp/include/lemon/utils/rocm_arch_utils.h | 2 +- src/cpp/server/system_info.cpp | 54 +++++++++++++------ src/cpp/server/utils/rocm_arch_utils.cpp | 2 +- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/cpp/include/lemon/utils/rocm_arch_utils.h b/src/cpp/include/lemon/utils/rocm_arch_utils.h index 5621eaeaff..d5a4d7b434 100644 --- a/src/cpp/include/lemon/utils/rocm_arch_utils.h +++ b/src/cpp/include/lemon/utils/rocm_arch_utils.h @@ -22,4 +22,4 @@ class ROCmArchUtils { static std::vector rocm_arch_get_active_devices(const json& json_devices); }; -} // namespace lemon \ No newline at end of file +} // namespace lemon diff --git a/src/cpp/server/system_info.cpp b/src/cpp/server/system_info.cpp index 10f1229954..11ed4abb4d 100644 --- a/src/cpp/server/system_info.cpp +++ b/src/cpp/server/system_info.cpp @@ -1833,26 +1833,15 @@ std::string identify_cuda_arch_from_name(const std::string& device_name) { return ""; } -// Helper to identify ROCm architecture from GPU name. -std::string identify_rocm_arch_from_name(const std::string& device_name) { - std::string device_lower = device_name; - std::transform(device_lower.begin(), device_lower.end(), device_lower.begin(), ::tolower); - - std::smatch gfx_match; - // Match 3- or 4-digit gfx tokens; the trailing nibble can be hex (e.g. gfx90a). - if (std::regex_search(device_lower, gfx_match, std::regex(R"((gfx[0-9a-f]{3,4}))"))) { - return gfx_match[1].str(); - } - - // Linux will pass the ISA from KFD, transform it to what the rest of lemonade expects - if (!device_lower.empty() && - std::all_of(device_lower.begin(), device_lower.end(), ::isdigit)) { +std::string transform_isakfd_to_gfx(const std::string& isa) { + if (!isa.empty() && + std::all_of(isa.begin(), isa.end(), ::isdigit)) { int v; try { - v = std::stoi(device_lower); + v = std::stoi(isa); } catch (const std::exception& e) { throw std::runtime_error( - "Failed to parse gfx_target_version '" + device_lower + "': " + e.what()); + "Failed to parse gfx_target_version '" + isa + "': " + e.what()); } int major = v / 10000; int minor = (v / 100) % 100; @@ -1861,8 +1850,41 @@ std::string identify_rocm_arch_from_name(const std::string& device_name) { char buf[16]; std::snprintf(buf, sizeof(buf), "gfx%d%x%x", major, minor, step); return std::string(buf); + } else { + return ""; } +} + +std::string get_gfx_from_device_name(const std::string device_name) { + std::string device_lower = device_name; + std::transform(device_lower.begin(), device_lower.end(), device_lower.begin(), ::tolower); + std::smatch gfx_match; + // Match 3- or 4-digit gfx tokens; the trailing nibble can be hex (e.g. gfx90a). + if (std::regex_search(device_lower, gfx_match, std::regex(R"((gfx[0-9a-f]{3,4}))"))) { + return gfx_match[1].str(); + } + return ""; + +} + +// Helper to identify ROCm architecture from GPU name. +std::string identify_rocm_arch_from_name(const std::string& device_name) { + std::string device_lower = device_name; + std::string gfx; + std::transform(device_lower.begin(), device_lower.end(), device_lower.begin(), ::tolower); + + gfx = get_gfx_from_device_name(device_lower); + if (!gfx.empty()) { + return gfx; + } + + // Linux will pass the ISA from KFD, transform it to what the rest of lemonade expects + gfx = transform_isakfd_to_gfx(device_lower); + if (!gfx.empty()) { + return gfx; + } + if (device_lower.find("radeon") == std::string::npos && device_lower.find("amd") == std::string::npos) { return ""; diff --git a/src/cpp/server/utils/rocm_arch_utils.cpp b/src/cpp/server/utils/rocm_arch_utils.cpp index c18b1d952c..0e904f3538 100644 --- a/src/cpp/server/utils/rocm_arch_utils.cpp +++ b/src/cpp/server/utils/rocm_arch_utils.cpp @@ -53,4 +53,4 @@ std::vector ROCmArchUtils::rocm_arch_get_active_devices(const js } -} // namespace lemon \ No newline at end of file +} // namespace lemon From a4c4b63a64c730a0f2ff8e4959c6fb041cbb05ea Mon Sep 17 00:00:00 2001 From: Gabriel Reus Date: Mon, 15 Jun 2026 19:50:42 +0200 Subject: [PATCH 7/8] Refactoring helpers of functions --- src/cpp/include/lemon/utils/rocm_arch_utils.h | 3 + src/cpp/server/system_info.cpp | 11 +-- src/cpp/server/utils/rocm_arch_utils.cpp | 67 +++++++++++++------ 3 files changed, 56 insertions(+), 25 deletions(-) diff --git a/src/cpp/include/lemon/utils/rocm_arch_utils.h b/src/cpp/include/lemon/utils/rocm_arch_utils.h index d5a4d7b434..6ebc05c6cb 100644 --- a/src/cpp/include/lemon/utils/rocm_arch_utils.h +++ b/src/cpp/include/lemon/utils/rocm_arch_utils.h @@ -17,9 +17,12 @@ struct ROCmDeviceInfo { class ROCmArchUtils { public: + static std::string transform_isakfd_to_gfx(const std::string& isa); + static std::string get_gfx_from_device_name(const std::string& device_name); static std::string rocm_arch_numeric_to_gfx(const std::string& numeric_version); static bool rocm_arch_is_valid_gfx(const std::string& gfx_arch); static std::vector rocm_arch_get_active_devices(const json& json_devices); + }; } // namespace lemon diff --git a/src/cpp/server/system_info.cpp b/src/cpp/server/system_info.cpp index 11ed4abb4d..6ac3552144 100644 --- a/src/cpp/server/system_info.cpp +++ b/src/cpp/server/system_info.cpp @@ -6,6 +6,7 @@ #include "lemon/utils/version_utils.h" #include "lemon/utils/json_utils.h" #include "lemon/utils/process_manager.h" +#include "lemon/utils/rocm_arch_utils.h" #include "lemon/backends/backend_utils.h" #include #include @@ -1832,7 +1833,7 @@ std::string identify_cuda_arch_from_name(const std::string& device_name) { } return ""; } - +/* std::string transform_isakfd_to_gfx(const std::string& isa) { if (!isa.empty() && std::all_of(isa.begin(), isa.end(), ::isdigit)) { @@ -1855,7 +1856,7 @@ std::string transform_isakfd_to_gfx(const std::string& isa) { } } -std::string get_gfx_from_device_name(const std::string device_name) { +std::string get_gfx_from_device_name(const std::string& device_name) { std::string device_lower = device_name; std::transform(device_lower.begin(), device_lower.end(), device_lower.begin(), ::tolower); @@ -1867,20 +1868,20 @@ std::string get_gfx_from_device_name(const std::string device_name) { return ""; } - +*/ // Helper to identify ROCm architecture from GPU name. std::string identify_rocm_arch_from_name(const std::string& device_name) { std::string device_lower = device_name; std::string gfx; std::transform(device_lower.begin(), device_lower.end(), device_lower.begin(), ::tolower); - gfx = get_gfx_from_device_name(device_lower); + gfx = ROCmArchUtils::get_gfx_from_device_name(device_lower); if (!gfx.empty()) { return gfx; } // Linux will pass the ISA from KFD, transform it to what the rest of lemonade expects - gfx = transform_isakfd_to_gfx(device_lower); + gfx = ROCmArchUtils::transform_isakfd_to_gfx(device_lower); if (!gfx.empty()) { return gfx; } diff --git a/src/cpp/server/utils/rocm_arch_utils.cpp b/src/cpp/server/utils/rocm_arch_utils.cpp index 0e904f3538..196155e12d 100644 --- a/src/cpp/server/utils/rocm_arch_utils.cpp +++ b/src/cpp/server/utils/rocm_arch_utils.cpp @@ -5,33 +5,60 @@ namespace lemon{ + +std::string ROCmArchUtils::transform_isakfd_to_gfx(const std::string& isa) { + if (!isa.empty() && + std::all_of(isa.begin(), isa.end(), ::isdigit)) { + int v; + try { + v = std::stoi(isa); + } catch (const std::exception& e) { + throw std::runtime_error( + "Failed to parse gfx_target_version '" + isa + "': " + e.what()); + } + int major = v / 10000; + int minor = (v / 100) % 100; + int step = v % 100; + + char buf[16]; + std::snprintf(buf, sizeof(buf), "gfx%d%x%x", major, minor, step); + return std::string(buf); + } else { + return ""; + } +} + +std::string ROCmArchUtils::get_gfx_from_device_name(const std::string& device_name) { + std::string device_lower = device_name; + std::transform(device_lower.begin(), device_lower.end(), device_lower.begin(), ::tolower); + + std::smatch gfx_match; + // Match 3- or 4-digit gfx tokens; the trailing nibble can be hex (e.g. gfx90a). + if (std::regex_search(device_lower, gfx_match, std::regex(R"((gfx[0-9a-f]{3,4}))"))) { + return gfx_match[1].str(); + } + return ""; + +} + + bool ROCmArchUtils::rocm_arch_is_valid_gfx(const std::string& gfx_arch) { + + + std::string gfx = ROCmArchUtils::get_gfx_from_device_name(gfx_arch); + return !gfx.empty(); + + /* std::smatch gfx_match; return std::regex_search(gfx_arch, gfx_match, std::regex(R"((gfx\d{4}))")); + */ } // In this function we tranform the rocm archictecture from numeric format to gfx format. std::string ROCmArchUtils::rocm_arch_numeric_to_gfx(const std::string& numeric_arch) { - try { - // We convert the string with numeric version to long long number - long long num = std::stoll(numeric_arch); - - // We get the differents components of version. - long long major = num / 10000; - long long minor = (num / 100) % 100; - long long stepping = num % 100; - - // We build the gfx version with the previous components. - return "gfx" + std::to_string(major) + std::to_string(minor) + std::to_string(stepping); - } - catch (const std::invalid_argument& e) { - // The case that the conversion of stoll cannot be done. - throw std::invalid_argument("The numeric version is not a valid number"); - } - catch (const std::out_of_range& e) { - // The case that the conversion is bigger than long long limits. - throw std::invalid_argument("The numeric version is not a valid number"); - } + + std::string gfx = ROCmArchUtils::transform_isakfd_to_gfx(numeric_arch); + return gfx; } std::vector ROCmArchUtils::rocm_arch_get_active_devices(const json& devices) { From d4d9150b70e8dc1f1cdf6f306ebd9cdfcb040571 Mon Sep 17 00:00:00 2001 From: Gabriel Reus Date: Mon, 15 Jun 2026 20:26:09 +0200 Subject: [PATCH 8/8] Clean the code --- src/cpp/include/lemon/utils/rocm_arch_utils.h | 2 -- src/cpp/server/system_info.cpp | 35 ------------------- src/cpp/server/utils/rocm_arch_utils.cpp | 18 +--------- 3 files changed, 1 insertion(+), 54 deletions(-) diff --git a/src/cpp/include/lemon/utils/rocm_arch_utils.h b/src/cpp/include/lemon/utils/rocm_arch_utils.h index 6ebc05c6cb..80c8c77241 100644 --- a/src/cpp/include/lemon/utils/rocm_arch_utils.h +++ b/src/cpp/include/lemon/utils/rocm_arch_utils.h @@ -19,10 +19,8 @@ class ROCmArchUtils { public: static std::string transform_isakfd_to_gfx(const std::string& isa); static std::string get_gfx_from_device_name(const std::string& device_name); - static std::string rocm_arch_numeric_to_gfx(const std::string& numeric_version); static bool rocm_arch_is_valid_gfx(const std::string& gfx_arch); static std::vector rocm_arch_get_active_devices(const json& json_devices); - }; } // namespace lemon diff --git a/src/cpp/server/system_info.cpp b/src/cpp/server/system_info.cpp index 6ac3552144..37e2d0d0f7 100644 --- a/src/cpp/server/system_info.cpp +++ b/src/cpp/server/system_info.cpp @@ -1833,42 +1833,7 @@ std::string identify_cuda_arch_from_name(const std::string& device_name) { } return ""; } -/* -std::string transform_isakfd_to_gfx(const std::string& isa) { - if (!isa.empty() && - std::all_of(isa.begin(), isa.end(), ::isdigit)) { - int v; - try { - v = std::stoi(isa); - } catch (const std::exception& e) { - throw std::runtime_error( - "Failed to parse gfx_target_version '" + isa + "': " + e.what()); - } - int major = v / 10000; - int minor = (v / 100) % 100; - int step = v % 100; - - char buf[16]; - std::snprintf(buf, sizeof(buf), "gfx%d%x%x", major, minor, step); - return std::string(buf); - } else { - return ""; - } -} - -std::string get_gfx_from_device_name(const std::string& device_name) { - std::string device_lower = device_name; - std::transform(device_lower.begin(), device_lower.end(), device_lower.begin(), ::tolower); - - std::smatch gfx_match; - // Match 3- or 4-digit gfx tokens; the trailing nibble can be hex (e.g. gfx90a). - if (std::regex_search(device_lower, gfx_match, std::regex(R"((gfx[0-9a-f]{3,4}))"))) { - return gfx_match[1].str(); - } - return ""; -} -*/ // Helper to identify ROCm architecture from GPU name. std::string identify_rocm_arch_from_name(const std::string& device_name) { std::string device_lower = device_name; diff --git a/src/cpp/server/utils/rocm_arch_utils.cpp b/src/cpp/server/utils/rocm_arch_utils.cpp index 196155e12d..d1ae0e6962 100644 --- a/src/cpp/server/utils/rocm_arch_utils.cpp +++ b/src/cpp/server/utils/rocm_arch_utils.cpp @@ -38,27 +38,12 @@ std::string ROCmArchUtils::get_gfx_from_device_name(const std::string& device_na return gfx_match[1].str(); } return ""; - } bool ROCmArchUtils::rocm_arch_is_valid_gfx(const std::string& gfx_arch) { - - std::string gfx = ROCmArchUtils::get_gfx_from_device_name(gfx_arch); return !gfx.empty(); - - /* - std::smatch gfx_match; - return std::regex_search(gfx_arch, gfx_match, std::regex(R"((gfx\d{4}))")); - */ -} - -// In this function we tranform the rocm archictecture from numeric format to gfx format. -std::string ROCmArchUtils::rocm_arch_numeric_to_gfx(const std::string& numeric_arch) { - - std::string gfx = ROCmArchUtils::transform_isakfd_to_gfx(numeric_arch); - return gfx; } std::vector ROCmArchUtils::rocm_arch_get_active_devices(const json& devices) { @@ -69,7 +54,7 @@ std::vector ROCmArchUtils::rocm_arch_get_active_devices(const js for (const auto& amd_gpu : devices["amd_gpu"]) { ROCmDeviceInfo dev; if (amd_gpu.contains("available") && amd_gpu["available"].is_boolean() && amd_gpu["available"]) { - dev.name = lemon::ROCmArchUtils::rocm_arch_numeric_to_gfx(amd_gpu["name"]); + dev.name = ROCmArchUtils::transform_isakfd_to_gfx(amd_gpu["name"]); dev.vram_gb = amd_gpu["vram_gb"]; active_devs.push_back(dev); } @@ -79,5 +64,4 @@ std::vector ROCmArchUtils::rocm_arch_get_active_devices(const js return active_devs; } - } // namespace lemon