Commit 133087d for stable-diffusion.cpp
commit 133087deb82abd8bcd4afdf0b895cf63a8714293
Author: leejet <leejet714@gmail.com>
Date: Mon Nov 2 01:09:36 2026 +0800
fix: prefer discrete GPUs in auto-fit device selection (#2259)
diff --git a/docs/backend.md b/docs/backend.md
index 49ca063..da90e48 100644
--- a/docs/backend.md
+++ b/docs/backend.md
@@ -135,7 +135,10 @@ regardless of argument order, even with `--auto-fit on`.
Auto-fit preserves explicit `--backend` assignments, including per-module
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
compute devices, and the remaining memory budgets. The chosen backend
specifications are printed.
diff --git a/src/core/backend_fit.cpp b/src/core/backend_fit.cpp
index c970d10..120cbe4 100644
--- a/src/core/backend_fit.cpp
+++ b/src/core/backend_fit.cpp
@@ -42,8 +42,9 @@ namespace sd::backend_fit {
struct Device {
std::string name;
std::string description;
- int64_t free_bytes = 0;
- int64_t budget_bytes = 0;
+ int64_t free_bytes = 0;
+ int64_t budget_bytes = 0;
+ enum ggml_backend_dev_type type = GGML_BACKEND_DEVICE_TYPE_GPU;
};
enum class ParamsLocation {
@@ -140,6 +141,7 @@ namespace sd::backend_fit {
Device device;
device.name = ggml_backend_dev_name(dev);
device.description = ggml_backend_dev_description(dev);
+ device.type = type;
size_t free_bytes = 0, total_bytes = 0;
ggml_backend_dev_memory(dev, &free_bytes, &total_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) {
- size_t main_device = SIZE_MAX;
- for (size_t di = 0; di < devices.size(); ++di) {
- if (devices[di].budget_bytes > 0 &&
- (main_device == SIZE_MAX || devices[di].budget_bytes > devices[main_device].budget_bytes)) {
- main_device = di;
+ // Shared system memory must not make an integrated GPU outrank a discrete GPU.
+ for (bool discrete : {true, false}) {
+ size_t main_device = SIZE_MAX;
+ for (size_t di = 0; di < devices.size(); ++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,