amd-smi-wsl 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,69 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.2.0] - 2026-06-11
11
+
12
+ ### Fixed
13
+ - **Critical:** infinite recursion / `RecursionError` when used with a real
14
+ PyTorch ROCm build. torch's ROCm device enumeration resolves the device count
15
+ *through* `amdsmi` (`amdsmi_init` + `amdsmi_get_processor_handles`), which this
16
+ package shadows, so `amdsmi_init()` -> backend probe -> `torch.cuda` ->
17
+ `amdsmi_init()` looped forever. A thread-local re-entrancy guard now makes the
18
+ re-entrant `amdsmi_init()` raise so torch falls back to its native HIP device
19
+ count. This was the blocker that prevented the package (and vLLM through it)
20
+ from working at all on the target WSL2 + torch-ROCm environment.
21
+ - `amdsmi_get_clock_info` / `amdsmi_get_temp_metric` / `amdsmi_get_power_info`
22
+ could leak `AMDSMI_STATUS_NOT_FOUND` (and risk re-entrancy) when torch routed
23
+ the sensor query back through amdsmi; they now degrade cleanly to
24
+ `AMDSMI_STATUS_NOT_SUPPORTED`.
25
+
26
+ ### Changed
27
+ - `amdsmi_get_gpu_asic_info` now returns `device_id`, `vendor_id`,
28
+ `subvendor_id`, `subsystem_id` and `rev_id` as lowercase, zero-padded hex
29
+ strings (e.g. `"0x1586"`, `"0xc1"`), matching the upstream contract. This lets
30
+ vLLM resolve the canonical device name from its hex-keyed
31
+ `_ROCM_DEVICE_ID_NAME_MAP` (e.g. `AMD_Radeon_8060S`) instead of falling back
32
+ to the raw marketing string. `amdsmi_get_gpu_subsystem_id` /
33
+ `amdsmi_get_gpu_revision` likewise return hex strings.
34
+ - `driver_date` from the Windows probe is parsed from the raw WMI
35
+ `/Date(ms)/` serialization into a readable `YYYY-MM-DD` string.
36
+ - The Windows interop probe is cached persistently (PCI metadata is static), so
37
+ vLLM's `with_amdsmi_context` no longer re-spawns `powershell.exe` on every
38
+ call.
39
+ - Degenerate placeholder UUIDs reported by torch on WSL2 (e.g.
40
+ `66666666-...`) are detected and replaced with a stable synthesized id, kept
41
+ consistent across `device_uuid`, `asic_serial`, and board `product_serial`.
42
+
43
+ ### Tested
44
+ - Verified end-to-end on WSL2 + AMD Radeon 8060S (Strix Halo, gfx1151) +
45
+ ROCm 7.2.4 + PyTorch 2.9.1: `import amdsmi` works, vLLM ROCm platform
46
+ detection succeeds, and `RocmPlatform.get_device_name(0)` returns
47
+ `AMD_Radeon_8060S`.
48
+
49
+ ## [0.1.0] - 2026-06-04
50
+
51
+ ### Added
52
+ - Initial release: a drop-in replacement for the `amdsmi` Python package that
53
+ works on WSL2 / Windows, where the native AMD SMI library cannot run because
54
+ the KFD interface (`/dev/kfd`, `/sys/class/kfd`) is unavailable.
55
+ - Full API parity with upstream `amdsmi`: all 189 `amdsmi_*` functions, 37
56
+ `AmdSmi*` enums, the complete exception hierarchy, and `AmdSmiEventReader`.
57
+ - Real implementations for the queryable subset, backed by:
58
+ - the HIP runtime via `torch.cuda` (device count, name, gfx arch, VRAM, compute
59
+ units, live memory usage), and
60
+ - Windows interop (`powershell.exe Get-CimInstance Win32_VideoController`) to
61
+ recover the real PCI device id, subsystem id, and driver version.
62
+ - a static `gfx -> metadata` fallback table.
63
+ - Faithful degradation: capabilities that genuinely do not exist on WSL2 raise
64
+ `AmdSmiLibraryException(AMDSMI_STATUS_NOT_SUPPORTED)`, matching native behavior.
65
+ - `AMDSMI_WSL_DISABLE` environment variable to disable the shim.
66
+
67
+ [Unreleased]: https://github.com/JoursBleu/amd-smi-wsl/compare/v0.2.0...HEAD
68
+ [0.2.0]: https://github.com/JoursBleu/amd-smi-wsl/compare/v0.1.0...v0.2.0
69
+ [0.1.0]: https://github.com/JoursBleu/amd-smi-wsl/releases/tag/v0.1.0
@@ -0,0 +1,39 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest in improving `amd-smi-wsl`.
4
+
5
+ ## Scope
6
+
7
+ This package is a **drop-in replacement** for the upstream `amdsmi` Python
8
+ binding, targeted at WSL2 / Windows environments where the native AMD SMI
9
+ library cannot run. The guiding principle is **API fidelity**: the public
10
+ surface (function names, signatures, return shapes, enums, exceptions) must
11
+ match upstream `amdsmi`. Where a capability cannot be supported on WSL2, the
12
+ corresponding function should raise
13
+ `AmdSmiLibraryException(AMDSMI_STATUS_NOT_SUPPORTED)` rather than returning
14
+ fabricated data.
15
+
16
+ ## Development setup
17
+
18
+ ```bash
19
+ git clone git@github.com:JoursBleu/amd-smi-wsl.git
20
+ cd amd-smi-wsl
21
+ python -m venv .venv && . .venv/bin/activate
22
+ pip install -e ".[test]"
23
+ pytest
24
+ ```
25
+
26
+ ## Guidelines
27
+
28
+ - Keep full parity with upstream `amdsmi` — do not rename or drop public symbols.
29
+ - Constants and enums are extracted verbatim from upstream; do not edit their
30
+ values by hand.
31
+ - New real implementations must degrade gracefully when no GPU / no torch is
32
+ present.
33
+ - Add or update tests in `tests/` for any behavior change.
34
+ - Run `pytest` before opening a pull request.
35
+
36
+ ## Reporting issues
37
+
38
+ Please include: OS (Windows version + WSL distro), ROCm version, GPU model,
39
+ `python -c "import torch; print(torch.version.hip)"`, and the full traceback.
@@ -0,0 +1,29 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 JoursBleu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ Portions of this project (the AMDSMI_* status constants, the AmdSmi* enum
26
+ value definitions, and the exception classes) are derived from the ROCm/amdsmi
27
+ project, which is also distributed under the MIT License:
28
+
29
+ Copyright (C) Advanced Micro Devices. All rights reserved.
@@ -0,0 +1,5 @@
1
+ include LICENSE
2
+ include README.md
3
+ include CHANGELOG.md
4
+ include CONTRIBUTING.md
5
+ include src/amdsmi/py.typed
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: amd-smi-wsl
3
+ Version: 0.2.0
4
+ Summary: Drop-in amdsmi replacement for WSL2 / Windows (HIP + Windows interop backed).
5
+ Author: JoursBleu
6
+ License: MIT
7
+ Project-URL: Homepage, https://joursbleu.github.io/amd-smi-wsl/
8
+ Project-URL: Documentation, https://joursbleu.github.io/amd-smi-wsl/
9
+ Project-URL: Repository, https://github.com/JoursBleu/amd-smi-wsl
10
+ Project-URL: Issues, https://github.com/JoursBleu/amd-smi-wsl/issues
11
+ Project-URL: Changelog, https://github.com/JoursBleu/amd-smi-wsl/blob/main/CHANGELOG.md
12
+ Keywords: amdsmi,amd-smi,rocm,wsl2,wsl,hip,gpu,vllm
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: GPU
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: Microsoft :: Windows
18
+ Classifier: Operating System :: POSIX :: Linux
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: System :: Hardware
26
+ Classifier: Topic :: System :: Monitoring
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.9
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Provides-Extra: test
32
+ Requires-Dist: pytest; extra == "test"
33
+ Dynamic: license-file
34
+
35
+ # amd-smi-wsl
36
+
37
+ A **drop-in replacement for the `amdsmi` Python package** that works inside
38
+ **WSL2 / Windows**, where the native AMD SMI library cannot run.
39
+
40
+ This is a property of the WSL2 GPU stack rather than of any single card, so it
41
+ applies broadly to AMD GPUs used with ROCm under WSL2 — across RDNA
42
+ generations (e.g. RDNA3 / RDNA3.5 / RDNA4 desktop Radeon and Radeon PRO cards,
43
+ as well as Ryzen AI APUs). The data sources it builds on (the HIP runtime and
44
+ Windows interop) are GPU-agnostic; only the per-device details (PCI id, market
45
+ name, gfx arch) differ from card to card.
46
+
47
+ ```python
48
+ import amdsmi # this package, not the native one
49
+ amdsmi.amdsmi_init()
50
+ h = amdsmi.amdsmi_get_processor_handles()[0]
51
+ print(amdsmi.amdsmi_get_gpu_asic_info(h)["market_name"])
52
+ ```
53
+
54
+ ## Why
55
+
56
+ On WSL2 **any** AMD GPU is exposed through DirectX para-virtualisation
57
+ (`/dev/dxg` + `dxgkrnl`), **not** the native `amdgpu` KFD driver. The Linux
58
+ `/dev/kfd` device and its sysfs topology simply do not exist, so — regardless
59
+ of which Radeon / Ryzen GPU you have:
60
+
61
+ - `import amdsmi` (native) fails / `amdsmi_init()` raises, and
62
+ - downstream code such as **vLLM** then fails ROCm platform detection and
63
+ device-name / topology queries at startup,
64
+
65
+ even though the HIP runtime itself works perfectly via `/dev/dxg`.
66
+
67
+ This package restores the `amdsmi` import surface and re-implements the
68
+ *queryable* subset on top of data sources that **do** work in WSL2:
69
+
70
+ | Source | Provides |
71
+ | --- | --- |
72
+ | `torch.cuda` (HIP runtime) | device count, name, GCN arch, total VRAM, compute units, UUID, live mem usage |
73
+ | Windows interop (`Get-CimInstance Win32_VideoController`) | real PCI device id, subsystem id, revision, driver version/date |
74
+ | Static `gfx -> metadata` table | marketing name / VRAM type / device id fallbacks |
75
+
76
+ > **Note on `torch` re-entrancy.** PyTorch's ROCm build resolves its device
77
+ > count *through* `amdsmi` itself. Since this package replaces `amdsmi`, a
78
+ > naive probe would recurse (`amdsmi_init` -> `torch.cuda` -> `amdsmi_init` ...).
79
+ > A thread-local re-entrancy guard breaks that cycle so `torch` falls back to
80
+ > its native HIP device count. See the v0.2.0 entry in the changelog.
81
+
82
+ ## API coverage
83
+
84
+ The package exposes **every** public symbol of the upstream binding —
85
+ all 189 `amdsmi_*` functions, all 37 `AmdSmi*` enums, and the full
86
+ exception hierarchy — so `import amdsmi` is binary-compatible at the
87
+ Python level.
88
+
89
+ - **Implemented for real** (read-only queries that map cleanly to HIP /
90
+ Windows data): init / shutdown, processor & socket handle enumeration,
91
+ `asic_info`, `board_info`, `vram_info`, `vram_usage`, `memory_total`,
92
+ `memory_usage`, `device_uuid`, `device_bdf`, `driver_info`, `gpu_id`,
93
+ `subsystem_id`/`name`, `revision`, `vendor_name`, `topo_get_link_type`,
94
+ `topo_get_numa_node_number`, `lib_version`, `rocm_version`,
95
+ `status_code_to_string`, and best-effort `activity` / `clock_info` /
96
+ `temp_metric` / `power_info` (when the running `torch` build exposes them).
97
+ - **Faithful `NOT_SUPPORTED` stubs** for everything the platform genuinely
98
+ lacks under WSL2: the entire CPU/HSMP/EPYC surface, performance counters,
99
+ RAS/ECC, compute/memory partitioning, every `set_*` mutator, GPU reset,
100
+ KFD info, XGMI status, and event notification. These raise
101
+ `AmdSmiLibraryException(AMDSMI_STATUS_NOT_SUPPORTED)` — exactly what the
102
+ native library does for unsupported features.
103
+
104
+ ## Install
105
+
106
+ ```bash
107
+ pip install amd-smi-wsl
108
+ ```
109
+
110
+ `torch` (ROCm build) is expected to already be present in your environment and
111
+ is therefore **not** declared as a hard dependency.
112
+
113
+ > Only install this where the real `amdsmi` cannot be used. In a normal
114
+ > native-Linux ROCm install you should keep the official `amdsmi`.
115
+
116
+ ## Environment variables
117
+
118
+ - `AMDSMI_WSL_DISABLE=1` — make `amdsmi_init()` raise `NOT_SUPPORTED`, useful
119
+ to test a caller's fallback path.
120
+
121
+ ## Relationship to vLLM
122
+
123
+ This package makes the native-`amdsmi` code paths in vLLM's
124
+ `vllm/platforms/rocm.py` and `vllm/platforms/__init__.py` work unchanged on
125
+ WSL2, as an alternative to patching vLLM with `torch.cuda` fallbacks
126
+ (cf. vLLM PR #37189).
127
+
128
+ With this package installed, vLLM resolves the **canonical** device name from
129
+ its hex-keyed `_ROCM_DEVICE_ID_NAME_MAP` (because `asic_info["device_id"]` is
130
+ returned as a lowercase hex string such as `"0x1586"`), e.g.:
131
+
132
+ ```python
133
+ from vllm.platforms import rocm_platform_plugin
134
+ import vllm.platforms.rocm as rocm
135
+ rocm_platform_plugin() # -> 'vllm.platforms.rocm.RocmPlatform'
136
+ rocm.RocmPlatform.get_device_name(0) # -> 'AMD_Radeon_8060S'
137
+ rocm._GCN_ARCH # -> 'gfx1151'
138
+ ```
139
+
140
+ ## Verified environment
141
+
142
+ The mechanism is GPU-agnostic (it only relies on the HIP runtime + Windows
143
+ interop, which behave the same for any Radeon / Ryzen GPU under WSL2). The
144
+ numbers below are from one fully validated end-to-end setup — **WSL2 + AMD
145
+ Radeon 8060S (Strix Halo, gfx1151) + ROCm 7.2.4 + PyTorch 2.9.1** — and the
146
+ device-specific values (name, `device_id`, gfx arch) will naturally differ on
147
+ other cards:
148
+
149
+ | Check | Result |
150
+ | --- | --- |
151
+ | `import amdsmi` + `amdsmi_init()` | OK (no recursion) |
152
+ | `amdsmi_get_gpu_asic_info()["market_name"]` | `AMD Radeon(TM) 8060S Graphics` |
153
+ | `amdsmi_get_gpu_asic_info()["device_id"]` | `0x1586` (hex string) |
154
+ | `target_graphics_version` | `gfx1151` |
155
+ | test suite (`pytest`) | **16 passed** |
156
+ | vLLM `rocm_platform_plugin()` | `vllm.platforms.rocm.RocmPlatform` |
157
+ | vLLM `RocmPlatform.get_device_name(0)` | `AMD_Radeon_8060S` |
158
+ | vLLM `is_fully_connected([0])` | `True` |
159
+
160
+ Telemetry that the platform does not expose (`clock_info`, `temp_metric`,
161
+ `power_info`, `gpu_activity`) raises `AMDSMI_STATUS_NOT_SUPPORTED`, as expected.
162
+
163
+ ## License
164
+
165
+ MIT. Status constants, enum values and exception classes are derived from the
166
+ MIT-licensed [ROCm/amdsmi](https://github.com/ROCm/amdsmi) project.
@@ -0,0 +1,132 @@
1
+ # amd-smi-wsl
2
+
3
+ A **drop-in replacement for the `amdsmi` Python package** that works inside
4
+ **WSL2 / Windows**, where the native AMD SMI library cannot run.
5
+
6
+ This is a property of the WSL2 GPU stack rather than of any single card, so it
7
+ applies broadly to AMD GPUs used with ROCm under WSL2 — across RDNA
8
+ generations (e.g. RDNA3 / RDNA3.5 / RDNA4 desktop Radeon and Radeon PRO cards,
9
+ as well as Ryzen AI APUs). The data sources it builds on (the HIP runtime and
10
+ Windows interop) are GPU-agnostic; only the per-device details (PCI id, market
11
+ name, gfx arch) differ from card to card.
12
+
13
+ ```python
14
+ import amdsmi # this package, not the native one
15
+ amdsmi.amdsmi_init()
16
+ h = amdsmi.amdsmi_get_processor_handles()[0]
17
+ print(amdsmi.amdsmi_get_gpu_asic_info(h)["market_name"])
18
+ ```
19
+
20
+ ## Why
21
+
22
+ On WSL2 **any** AMD GPU is exposed through DirectX para-virtualisation
23
+ (`/dev/dxg` + `dxgkrnl`), **not** the native `amdgpu` KFD driver. The Linux
24
+ `/dev/kfd` device and its sysfs topology simply do not exist, so — regardless
25
+ of which Radeon / Ryzen GPU you have:
26
+
27
+ - `import amdsmi` (native) fails / `amdsmi_init()` raises, and
28
+ - downstream code such as **vLLM** then fails ROCm platform detection and
29
+ device-name / topology queries at startup,
30
+
31
+ even though the HIP runtime itself works perfectly via `/dev/dxg`.
32
+
33
+ This package restores the `amdsmi` import surface and re-implements the
34
+ *queryable* subset on top of data sources that **do** work in WSL2:
35
+
36
+ | Source | Provides |
37
+ | --- | --- |
38
+ | `torch.cuda` (HIP runtime) | device count, name, GCN arch, total VRAM, compute units, UUID, live mem usage |
39
+ | Windows interop (`Get-CimInstance Win32_VideoController`) | real PCI device id, subsystem id, revision, driver version/date |
40
+ | Static `gfx -> metadata` table | marketing name / VRAM type / device id fallbacks |
41
+
42
+ > **Note on `torch` re-entrancy.** PyTorch's ROCm build resolves its device
43
+ > count *through* `amdsmi` itself. Since this package replaces `amdsmi`, a
44
+ > naive probe would recurse (`amdsmi_init` -> `torch.cuda` -> `amdsmi_init` ...).
45
+ > A thread-local re-entrancy guard breaks that cycle so `torch` falls back to
46
+ > its native HIP device count. See the v0.2.0 entry in the changelog.
47
+
48
+ ## API coverage
49
+
50
+ The package exposes **every** public symbol of the upstream binding —
51
+ all 189 `amdsmi_*` functions, all 37 `AmdSmi*` enums, and the full
52
+ exception hierarchy — so `import amdsmi` is binary-compatible at the
53
+ Python level.
54
+
55
+ - **Implemented for real** (read-only queries that map cleanly to HIP /
56
+ Windows data): init / shutdown, processor & socket handle enumeration,
57
+ `asic_info`, `board_info`, `vram_info`, `vram_usage`, `memory_total`,
58
+ `memory_usage`, `device_uuid`, `device_bdf`, `driver_info`, `gpu_id`,
59
+ `subsystem_id`/`name`, `revision`, `vendor_name`, `topo_get_link_type`,
60
+ `topo_get_numa_node_number`, `lib_version`, `rocm_version`,
61
+ `status_code_to_string`, and best-effort `activity` / `clock_info` /
62
+ `temp_metric` / `power_info` (when the running `torch` build exposes them).
63
+ - **Faithful `NOT_SUPPORTED` stubs** for everything the platform genuinely
64
+ lacks under WSL2: the entire CPU/HSMP/EPYC surface, performance counters,
65
+ RAS/ECC, compute/memory partitioning, every `set_*` mutator, GPU reset,
66
+ KFD info, XGMI status, and event notification. These raise
67
+ `AmdSmiLibraryException(AMDSMI_STATUS_NOT_SUPPORTED)` — exactly what the
68
+ native library does for unsupported features.
69
+
70
+ ## Install
71
+
72
+ ```bash
73
+ pip install amd-smi-wsl
74
+ ```
75
+
76
+ `torch` (ROCm build) is expected to already be present in your environment and
77
+ is therefore **not** declared as a hard dependency.
78
+
79
+ > Only install this where the real `amdsmi` cannot be used. In a normal
80
+ > native-Linux ROCm install you should keep the official `amdsmi`.
81
+
82
+ ## Environment variables
83
+
84
+ - `AMDSMI_WSL_DISABLE=1` — make `amdsmi_init()` raise `NOT_SUPPORTED`, useful
85
+ to test a caller's fallback path.
86
+
87
+ ## Relationship to vLLM
88
+
89
+ This package makes the native-`amdsmi` code paths in vLLM's
90
+ `vllm/platforms/rocm.py` and `vllm/platforms/__init__.py` work unchanged on
91
+ WSL2, as an alternative to patching vLLM with `torch.cuda` fallbacks
92
+ (cf. vLLM PR #37189).
93
+
94
+ With this package installed, vLLM resolves the **canonical** device name from
95
+ its hex-keyed `_ROCM_DEVICE_ID_NAME_MAP` (because `asic_info["device_id"]` is
96
+ returned as a lowercase hex string such as `"0x1586"`), e.g.:
97
+
98
+ ```python
99
+ from vllm.platforms import rocm_platform_plugin
100
+ import vllm.platforms.rocm as rocm
101
+ rocm_platform_plugin() # -> 'vllm.platforms.rocm.RocmPlatform'
102
+ rocm.RocmPlatform.get_device_name(0) # -> 'AMD_Radeon_8060S'
103
+ rocm._GCN_ARCH # -> 'gfx1151'
104
+ ```
105
+
106
+ ## Verified environment
107
+
108
+ The mechanism is GPU-agnostic (it only relies on the HIP runtime + Windows
109
+ interop, which behave the same for any Radeon / Ryzen GPU under WSL2). The
110
+ numbers below are from one fully validated end-to-end setup — **WSL2 + AMD
111
+ Radeon 8060S (Strix Halo, gfx1151) + ROCm 7.2.4 + PyTorch 2.9.1** — and the
112
+ device-specific values (name, `device_id`, gfx arch) will naturally differ on
113
+ other cards:
114
+
115
+ | Check | Result |
116
+ | --- | --- |
117
+ | `import amdsmi` + `amdsmi_init()` | OK (no recursion) |
118
+ | `amdsmi_get_gpu_asic_info()["market_name"]` | `AMD Radeon(TM) 8060S Graphics` |
119
+ | `amdsmi_get_gpu_asic_info()["device_id"]` | `0x1586` (hex string) |
120
+ | `target_graphics_version` | `gfx1151` |
121
+ | test suite (`pytest`) | **16 passed** |
122
+ | vLLM `rocm_platform_plugin()` | `vllm.platforms.rocm.RocmPlatform` |
123
+ | vLLM `RocmPlatform.get_device_name(0)` | `AMD_Radeon_8060S` |
124
+ | vLLM `is_fully_connected([0])` | `True` |
125
+
126
+ Telemetry that the platform does not expose (`clock_info`, `temp_metric`,
127
+ `power_info`, `gpu_activity`) raises `AMDSMI_STATUS_NOT_SUPPORTED`, as expected.
128
+
129
+ ## License
130
+
131
+ MIT. Status constants, enum values and exception classes are derived from the
132
+ MIT-licensed [ROCm/amdsmi](https://github.com/ROCm/amdsmi) project.
@@ -0,0 +1,50 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "amd-smi-wsl"
7
+ version = "0.2.0"
8
+ description = "Drop-in amdsmi replacement for WSL2 / Windows (HIP + Windows interop backed)."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "JoursBleu" }]
13
+ keywords = ["amdsmi", "amd-smi", "rocm", "wsl2", "wsl", "hip", "gpu", "vllm"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: GPU",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: Microsoft :: Windows",
20
+ "Operating System :: POSIX :: Linux",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Topic :: System :: Hardware",
28
+ "Topic :: System :: Monitoring",
29
+ "Typing :: Typed",
30
+ ]
31
+ dependencies = []
32
+
33
+ [project.optional-dependencies]
34
+ # torch is the runtime data source but is intentionally NOT a hard dependency:
35
+ # it is already present in any ROCm/vLLM environment and pinning it here would
36
+ # fight the user's existing install.
37
+ test = ["pytest"]
38
+
39
+ [project.urls]
40
+ Homepage = "https://joursbleu.github.io/amd-smi-wsl/"
41
+ Documentation = "https://joursbleu.github.io/amd-smi-wsl/"
42
+ Repository = "https://github.com/JoursBleu/amd-smi-wsl"
43
+ Issues = "https://github.com/JoursBleu/amd-smi-wsl/issues"
44
+ Changelog = "https://github.com/JoursBleu/amd-smi-wsl/blob/main/CHANGELOG.md"
45
+
46
+ [tool.setuptools.packages.find]
47
+ where = ["src"]
48
+
49
+ [tool.setuptools.package-data]
50
+ amdsmi = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: amd-smi-wsl
3
+ Version: 0.2.0
4
+ Summary: Drop-in amdsmi replacement for WSL2 / Windows (HIP + Windows interop backed).
5
+ Author: JoursBleu
6
+ License: MIT
7
+ Project-URL: Homepage, https://joursbleu.github.io/amd-smi-wsl/
8
+ Project-URL: Documentation, https://joursbleu.github.io/amd-smi-wsl/
9
+ Project-URL: Repository, https://github.com/JoursBleu/amd-smi-wsl
10
+ Project-URL: Issues, https://github.com/JoursBleu/amd-smi-wsl/issues
11
+ Project-URL: Changelog, https://github.com/JoursBleu/amd-smi-wsl/blob/main/CHANGELOG.md
12
+ Keywords: amdsmi,amd-smi,rocm,wsl2,wsl,hip,gpu,vllm
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: GPU
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: Microsoft :: Windows
18
+ Classifier: Operating System :: POSIX :: Linux
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: System :: Hardware
26
+ Classifier: Topic :: System :: Monitoring
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.9
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Provides-Extra: test
32
+ Requires-Dist: pytest; extra == "test"
33
+ Dynamic: license-file
34
+
35
+ # amd-smi-wsl
36
+
37
+ A **drop-in replacement for the `amdsmi` Python package** that works inside
38
+ **WSL2 / Windows**, where the native AMD SMI library cannot run.
39
+
40
+ This is a property of the WSL2 GPU stack rather than of any single card, so it
41
+ applies broadly to AMD GPUs used with ROCm under WSL2 — across RDNA
42
+ generations (e.g. RDNA3 / RDNA3.5 / RDNA4 desktop Radeon and Radeon PRO cards,
43
+ as well as Ryzen AI APUs). The data sources it builds on (the HIP runtime and
44
+ Windows interop) are GPU-agnostic; only the per-device details (PCI id, market
45
+ name, gfx arch) differ from card to card.
46
+
47
+ ```python
48
+ import amdsmi # this package, not the native one
49
+ amdsmi.amdsmi_init()
50
+ h = amdsmi.amdsmi_get_processor_handles()[0]
51
+ print(amdsmi.amdsmi_get_gpu_asic_info(h)["market_name"])
52
+ ```
53
+
54
+ ## Why
55
+
56
+ On WSL2 **any** AMD GPU is exposed through DirectX para-virtualisation
57
+ (`/dev/dxg` + `dxgkrnl`), **not** the native `amdgpu` KFD driver. The Linux
58
+ `/dev/kfd` device and its sysfs topology simply do not exist, so — regardless
59
+ of which Radeon / Ryzen GPU you have:
60
+
61
+ - `import amdsmi` (native) fails / `amdsmi_init()` raises, and
62
+ - downstream code such as **vLLM** then fails ROCm platform detection and
63
+ device-name / topology queries at startup,
64
+
65
+ even though the HIP runtime itself works perfectly via `/dev/dxg`.
66
+
67
+ This package restores the `amdsmi` import surface and re-implements the
68
+ *queryable* subset on top of data sources that **do** work in WSL2:
69
+
70
+ | Source | Provides |
71
+ | --- | --- |
72
+ | `torch.cuda` (HIP runtime) | device count, name, GCN arch, total VRAM, compute units, UUID, live mem usage |
73
+ | Windows interop (`Get-CimInstance Win32_VideoController`) | real PCI device id, subsystem id, revision, driver version/date |
74
+ | Static `gfx -> metadata` table | marketing name / VRAM type / device id fallbacks |
75
+
76
+ > **Note on `torch` re-entrancy.** PyTorch's ROCm build resolves its device
77
+ > count *through* `amdsmi` itself. Since this package replaces `amdsmi`, a
78
+ > naive probe would recurse (`amdsmi_init` -> `torch.cuda` -> `amdsmi_init` ...).
79
+ > A thread-local re-entrancy guard breaks that cycle so `torch` falls back to
80
+ > its native HIP device count. See the v0.2.0 entry in the changelog.
81
+
82
+ ## API coverage
83
+
84
+ The package exposes **every** public symbol of the upstream binding —
85
+ all 189 `amdsmi_*` functions, all 37 `AmdSmi*` enums, and the full
86
+ exception hierarchy — so `import amdsmi` is binary-compatible at the
87
+ Python level.
88
+
89
+ - **Implemented for real** (read-only queries that map cleanly to HIP /
90
+ Windows data): init / shutdown, processor & socket handle enumeration,
91
+ `asic_info`, `board_info`, `vram_info`, `vram_usage`, `memory_total`,
92
+ `memory_usage`, `device_uuid`, `device_bdf`, `driver_info`, `gpu_id`,
93
+ `subsystem_id`/`name`, `revision`, `vendor_name`, `topo_get_link_type`,
94
+ `topo_get_numa_node_number`, `lib_version`, `rocm_version`,
95
+ `status_code_to_string`, and best-effort `activity` / `clock_info` /
96
+ `temp_metric` / `power_info` (when the running `torch` build exposes them).
97
+ - **Faithful `NOT_SUPPORTED` stubs** for everything the platform genuinely
98
+ lacks under WSL2: the entire CPU/HSMP/EPYC surface, performance counters,
99
+ RAS/ECC, compute/memory partitioning, every `set_*` mutator, GPU reset,
100
+ KFD info, XGMI status, and event notification. These raise
101
+ `AmdSmiLibraryException(AMDSMI_STATUS_NOT_SUPPORTED)` — exactly what the
102
+ native library does for unsupported features.
103
+
104
+ ## Install
105
+
106
+ ```bash
107
+ pip install amd-smi-wsl
108
+ ```
109
+
110
+ `torch` (ROCm build) is expected to already be present in your environment and
111
+ is therefore **not** declared as a hard dependency.
112
+
113
+ > Only install this where the real `amdsmi` cannot be used. In a normal
114
+ > native-Linux ROCm install you should keep the official `amdsmi`.
115
+
116
+ ## Environment variables
117
+
118
+ - `AMDSMI_WSL_DISABLE=1` — make `amdsmi_init()` raise `NOT_SUPPORTED`, useful
119
+ to test a caller's fallback path.
120
+
121
+ ## Relationship to vLLM
122
+
123
+ This package makes the native-`amdsmi` code paths in vLLM's
124
+ `vllm/platforms/rocm.py` and `vllm/platforms/__init__.py` work unchanged on
125
+ WSL2, as an alternative to patching vLLM with `torch.cuda` fallbacks
126
+ (cf. vLLM PR #37189).
127
+
128
+ With this package installed, vLLM resolves the **canonical** device name from
129
+ its hex-keyed `_ROCM_DEVICE_ID_NAME_MAP` (because `asic_info["device_id"]` is
130
+ returned as a lowercase hex string such as `"0x1586"`), e.g.:
131
+
132
+ ```python
133
+ from vllm.platforms import rocm_platform_plugin
134
+ import vllm.platforms.rocm as rocm
135
+ rocm_platform_plugin() # -> 'vllm.platforms.rocm.RocmPlatform'
136
+ rocm.RocmPlatform.get_device_name(0) # -> 'AMD_Radeon_8060S'
137
+ rocm._GCN_ARCH # -> 'gfx1151'
138
+ ```
139
+
140
+ ## Verified environment
141
+
142
+ The mechanism is GPU-agnostic (it only relies on the HIP runtime + Windows
143
+ interop, which behave the same for any Radeon / Ryzen GPU under WSL2). The
144
+ numbers below are from one fully validated end-to-end setup — **WSL2 + AMD
145
+ Radeon 8060S (Strix Halo, gfx1151) + ROCm 7.2.4 + PyTorch 2.9.1** — and the
146
+ device-specific values (name, `device_id`, gfx arch) will naturally differ on
147
+ other cards:
148
+
149
+ | Check | Result |
150
+ | --- | --- |
151
+ | `import amdsmi` + `amdsmi_init()` | OK (no recursion) |
152
+ | `amdsmi_get_gpu_asic_info()["market_name"]` | `AMD Radeon(TM) 8060S Graphics` |
153
+ | `amdsmi_get_gpu_asic_info()["device_id"]` | `0x1586` (hex string) |
154
+ | `target_graphics_version` | `gfx1151` |
155
+ | test suite (`pytest`) | **16 passed** |
156
+ | vLLM `rocm_platform_plugin()` | `vllm.platforms.rocm.RocmPlatform` |
157
+ | vLLM `RocmPlatform.get_device_name(0)` | `AMD_Radeon_8060S` |
158
+ | vLLM `is_fully_connected([0])` | `True` |
159
+
160
+ Telemetry that the platform does not expose (`clock_info`, `temp_metric`,
161
+ `power_info`, `gpu_activity`) raises `AMDSMI_STATUS_NOT_SUPPORTED`, as expected.
162
+
163
+ ## License
164
+
165
+ MIT. Status constants, enum values and exception classes are derived from the
166
+ MIT-licensed [ROCm/amdsmi](https://github.com/ROCm/amdsmi) project.