fix: prefer discrete GPUs in auto-fit device selection (#2259)

This commit is contained in:
leejet authored and GitHub committed 2026-11-02 01:09:36 +08:00
1 parent 5d33b1bd2b
commit 133087deb8
2 files changed
+23 -9

No files matched your search

+4 -1
View File
@@ -135,7 +135,10 @@ regardless of argument order, even with `--auto-fit on`.
Auto-fit preserves explicit `--backend` assignments, including per-module Auto-fit preserves explicit `--backend` assignments, including per-module
assignments and device lists. For modules without a runtime assignment, it chooses assignments and device lists. For modules without a runtime assignment, it chooses
the GPU with the largest available memory budget (the first device on a tie). the discrete GPU with the largest positive memory budget (the first device on a
tie), falling back to integrated GPUs when no discrete GPU has a positive budget.
An integrated GPU's shared system memory does not give it priority over a discrete
GPU. Explicit assignments such as `--backend Vulkan1` still select that device.
It then derives parameter placements from the model metadata, each module's It then derives parameter placements from the model metadata, each module's
compute devices, and the remaining memory budgets. The chosen backend compute devices, and the remaining memory budgets. The chosen backend
specifications are printed. specifications are printed.
+19 -8
View File
@@ -42,8 +42,9 @@ namespace sd::backend_fit {
struct Device { struct Device {
std::string name; std::string name;
std::string description; std::string description;
int64_t free_bytes = 0; int64_t free_bytes = 0;
int64_t budget_bytes = 0; int64_t budget_bytes = 0;
enum ggml_backend_dev_type type = GGML_BACKEND_DEVICE_TYPE_GPU;
}; };
enum class ParamsLocation { enum class ParamsLocation {
@@ -140,6 +141,7 @@ namespace sd::backend_fit {
Device device; Device device;
device.name = ggml_backend_dev_name(dev); device.name = ggml_backend_dev_name(dev);
device.description = ggml_backend_dev_description(dev); device.description = ggml_backend_dev_description(dev);
device.type = type;
size_t free_bytes = 0, total_bytes = 0; size_t free_bytes = 0, total_bytes = 0;
ggml_backend_dev_memory(dev, &free_bytes, &total_bytes); ggml_backend_dev_memory(dev, &free_bytes, &total_bytes);
device.free_bytes = (int64_t)free_bytes; device.free_bytes = (int64_t)free_bytes;
@@ -193,14 +195,23 @@ namespace sd::backend_fit {
} }
static size_t select_main_device(const std::vector<Device>& devices) { static size_t select_main_device(const std::vector<Device>& devices) {
size_t main_device = SIZE_MAX; // Shared system memory must not make an integrated GPU outrank a discrete GPU.
for (size_t di = 0; di < devices.size(); ++di) { for (bool discrete : {true, false}) {
if (devices[di].budget_bytes > 0 && size_t main_device = SIZE_MAX;
(main_device == SIZE_MAX || devices[di].budget_bytes > devices[main_device].budget_bytes)) { for (size_t di = 0; di < devices.size(); ++di) {
main_device = di; if ((devices[di].type == GGML_BACKEND_DEVICE_TYPE_GPU) != discrete) {
continue;
}
if (devices[di].budget_bytes > 0 &&
(main_device == SIZE_MAX || devices[di].budget_bytes > devices[main_device].budget_bytes)) {
main_device = di;
}
}
if (main_device != SIZE_MAX) {
return main_device;
} }
} }
return main_device; return SIZE_MAX;
} }
static Plan compute_plan(const std::vector<Component>& components, static Plan compute_plan(const std::vector<Component>& components,