Scan vulkan devices in reverse order, to avoid main GPU - #917
Conversation
|
One line, and it changes device selection for everyone: - for (uint32_t i = 0; i < count; i++)
+ for (int i = (int)count - 1; i >= 0; i--)The problem is real — on a box with an iGPU and a discrete card, or two discrete cards, Vulkan enumerates in an order the driver chooses and colibri takes the first. If that is your display GPU, you get VRAM contention with the desktop. @Limalski hit an adjacent version of this in #848. But reverse order is not a fix, it is a different arbitrary choice. It works on your machine because your enumeration happens to put the card you want last. On the next reporter's machine it will be first again, and the one-line change will need reverting for them. What the engine should do is pick, not iterate:
The last of those may already be most of the way there: please check whether If you want to take the typed selection, I would take that PR. If you would rather just report the environment, post 3 of 5 checklist items and CI has not reported yet; I have approved the workflow run so it will. |
How about an option to choose which device then? |
|
I propose options can cure the issues, leaving defaults as is, and it's pretty simple. The scanning can rank each choice based on a few metrics, and choose the best one as an additive ranking. When there is a tie amongst multiple devices, the device with the most free VRAM wins. So that means: That's how I think it could be solved, with minimal effort, and it would provide a few safety checks. |
|
@xxxajk — eight days without an answer to a design proposal you wrote in good faith is on us, sorry. Here is where it stands, with the part you will want to know first: half of what you proposed is already on
int rank = p.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU ? 4 :
p.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU ? 3 :
p.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU ? 2 :
p.deviceType == VK_PHYSICAL_DEVICE_TYPE_OTHER ? 1 : 0; // CPU lastThat is your "is this CPU only? skip it / can it do compute? +1 / dedicated? +1" additive ranking, in the shape it ended up taking — and it means the original symptom of this PR is likely fixed for the iGPU + discrete case, without either arbitrary enumeration order. Worth testing on your box before anything else: if What is still missing from your design, and is still wanted:
So: this PR as written should close — the one-line reverse is superseded by the ranking, and we agreed it was a different arbitrary choice rather than a fix. Your proposal should become a new PR, scoped to (1) and (2): an explicit selector plus a free-VRAM tie-break on top of the existing ranking. That is small, testable, and does not need (3) to be useful. Would you like to write it, or would you rather we do and have you test it on the multi-GPU box? Either is fine — you found the problem and designed the fix, so the choice is yours. Closing this one only when you have said which. |
|
Cool, no rush, I'll give it a look asap, right now my GPUs are involved in a long horizon task. |
|
BTW, finding out if the GPU is compute only, I did a search, and this is what I found: A compute-only device exposes queue families with compute/transfer flags but lacks support for presenting images to a window or screen surface. HTH :-) |
ZacharyZcR
left a comment
There was a problem hiding this comment.
The loop bound has an off-by-one that changes the semantics beyond the stated goal: for (uint32_t i = nd-1; i > 0; i--) never evaluates devs[0] at all — the condition excludes index 0, so device 0 is not merely deprioritized on ties, it is excluded from ranking entirely. Two concrete consequences:
- On a machine where
devs[0]is the only discrete GPU (common: dGPU enumerates first, iGPU second), this selects the integrated GPU unconditionally — the rank comparison that is supposed to prefer discrete never sees the discrete device. nd == 1works only by accident:i = 0, loop body never runs,bestrankstays-1, and thedevs[0]fallback catches it.
If the intent is 'on equal rank, prefer the later-enumerated device' (avoid the display GPU), the full-coverage form does that with no exclusion:
for (uint32_t i = nd; i-- > 0;) {— iterates nd-1 .. 0 inclusive, and with the existing strict > comparison the first-seen (highest-index) device wins ties, which is exactly the avoid-main-GPU behavior this PR wants, while a lone discrete GPU at index 0 still outranks everything. An explicit VK_DEVICE=<index> override might serve the underlying use case (compute on the non-display GPU) more predictably than enumeration-order heuristics, but that's the maintainer's call; the bound fix stands either way.
|
@ZacharyZcR nice catch. |
Summary
Chose a Vulkan device in reverse order, so that the main display GPU is not chosen by default in a multi-GPU setup.
Simple one-line fix.
Validation
make -C c checkmake -C c cuda-test(if applicable)Compatibility