Skip to content

Commit de9f299

Browse files
authored
Add auto-detection for Intel GPU on Windows (#16280)
This PR enables `--torch-backend=auto` to automatically detect Intel GPUs. It follows up on [#14386](#14386). On Windows, detection is implemented by querying the `Win32_VideoController` class via the [WMI crate](https://github.com/ohadravid/wmi-rs/tree/v0.16.0). Currently, Intel GPUs (XPU) do not depend on specific driver or toolkit versions to determine which PyTorch wheel to use.
1 parent c12e8bb commit de9f299

6 files changed

Lines changed: 71 additions & 11 deletions

File tree

Cargo.lock

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ which = { version = "8.0.0", features = ["regex"] }
201201
windows = { version = "0.59.0", features = ["Win32_Globalization", "Win32_Security", "Win32_System_Console", "Win32_System_Kernel", "Win32_System_Diagnostics_Debug", "Win32_Storage_FileSystem", "Win32_System_Registry", "Win32_System_IO", "Win32_System_Ioctl"] }
202202
windows-registry = { version = "0.5.0" }
203203
wiremock = { version = "0.6.4" }
204+
wmi = { version = "0.16.0", default-features = false }
204205
xz2 = { version = "0.1.7" }
205206
zeroize = { version = "1.8.1" }
206207
zip = { version = "2.2.3", default-features = false, features = ["deflate", "zstd", "bzip2", "lzma", "xz"] }

crates/uv-torch/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,8 @@ thiserror = { workspace = true }
2525
tracing = { workspace = true }
2626
url = { workspace = true }
2727

28+
[target.'cfg(all(target_os = "windows"))'.dependencies]
29+
wmi = { workspace = true }
30+
2831
[lints]
2932
workspace = true

crates/uv-torch/src/accelerator.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ use tracing::debug;
66
use uv_pep440::Version;
77
use uv_static::EnvVars;
88

9+
#[cfg(windows)]
10+
use serde::Deserialize;
11+
#[cfg(windows)]
12+
use wmi::{COMLibrary, WMIConnection};
13+
914
#[derive(Debug, thiserror::Error)]
1015
pub enum AcceleratorError {
1116
#[error(transparent)]
@@ -60,6 +65,7 @@ impl Accelerator {
6065
/// 5. `nvidia-smi --query-gpu=driver_version --format=csv,noheader`.
6166
/// 6. `rocm_agent_enumerator`, which lists the AMD GPU architectures.
6267
/// 7. `/sys/bus/pci/devices`, filtering for the Intel GPU via PCI.
68+
/// 8. Windows Managmeent Instrumentation (WMI), filtering for the Intel GPU via PCI.
6369
pub fn detect() -> Result<Option<Self>, AcceleratorError> {
6470
// Constants used for PCI device detection.
6571
const PCI_BASE_CLASS_MASK: u32 = 0x00ff_0000;
@@ -187,6 +193,50 @@ impl Accelerator {
187193
Err(e) => return Err(e.into()),
188194
}
189195

196+
// Detect Intel GPU via WMI on Windows
197+
#[cfg(windows)]
198+
{
199+
#[derive(Deserialize, Debug)]
200+
#[serde(rename = "Win32_VideoController")]
201+
#[serde(rename_all = "PascalCase")]
202+
struct VideoController {
203+
#[serde(rename = "PNPDeviceID")]
204+
pnp_device_id: Option<String>,
205+
name: Option<String>,
206+
}
207+
208+
match COMLibrary::new() {
209+
Ok(com_library) => match WMIConnection::new(com_library) {
210+
Ok(wmi_connection) => match wmi_connection.query::<VideoController>() {
211+
Ok(gpu_controllers) => {
212+
for gpu_controller in gpu_controllers {
213+
if let Some(pnp_device_id) = &gpu_controller.pnp_device_id {
214+
if pnp_device_id
215+
.contains(&format!("VEN_{PCI_VENDOR_ID_INTEL:04X}"))
216+
{
217+
debug!(
218+
"Detected Intel GPU from WMI: PNPDeviceID={}, Name={:?}",
219+
pnp_device_id, gpu_controller.name
220+
);
221+
return Ok(Some(Self::Xpu));
222+
}
223+
}
224+
}
225+
}
226+
Err(e) => {
227+
debug!("Failed to query WMI for video controllers: {e}");
228+
}
229+
},
230+
Err(e) => {
231+
debug!("Failed to create WMI connection: {e}");
232+
}
233+
},
234+
Err(e) => {
235+
debug!("Failed to initialize COM library: {e}");
236+
}
237+
}
238+
}
239+
190240
debug!("Failed to detect GPU driver version");
191241

192242
Ok(None)

crates/uv-torch/src/backend.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,11 +466,10 @@ impl TorchStrategy {
466466
))),
467467
},
468468
Self::Xpu { os, source } => match os {
469-
Os::Manylinux { .. } => Either::Right(Either::Right(Either::Left(
469+
Os::Manylinux { .. } | Os::Windows => Either::Right(Either::Right(Either::Left(
470470
std::iter::once(TorchBackend::Xpu.index_url(*source)),
471471
))),
472-
Os::Windows
473-
| Os::Musllinux { .. }
472+
Os::Musllinux { .. }
474473
| Os::Macos { .. }
475474
| Os::FreeBsd { .. }
476475
| Os::NetBsd { .. }

docs/guides/integration/pytorch.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -460,12 +460,4 @@ $ # With an environment variable.
460460
$ UV_TORCH_BACKEND=cu126 uv pip install torch torchvision
461461
```
462462

463-
On Windows, Intel GPU (XPU) is not automatically selected with `--torch-backend=auto`, but you can
464-
manually specify it using `--torch-backend=xpu`:
465-
466-
```shell
467-
$ # Manual selection for Intel GPU.
468-
$ uv pip install torch torchvision --torch-backend=xpu
469-
```
470-
471463
At present, `--torch-backend` is only available in the `uv pip` interface.

0 commit comments

Comments
 (0)