gpustack-runtime 0.2.4.post2__tar.gz → 0.2.5__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.
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/PKG-INFO +2 -2
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/_version.py +2 -2
- gpustack_runtime-0.2.5/gpustack_runtime/_version_appendix.py +1 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/amd.py +53 -15
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/hygon.py +12 -3
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/pyproject.toml +3 -3
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_amd.py +96 -1
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_hygon.py +52 -3
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/uv.lock +57 -43
- gpustack_runtime-0.2.4.post2/gpustack_runtime/_version_appendix.py +0 -1
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/.codespelldict +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/.codespellrc +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/.dockerignore +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/.gitattributes +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/.gitignore +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/.pre-commit-config.yaml +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/.python-version +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/LICENSE +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/Makefile +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/README.md +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/deploy/manifests/docker-compose.yaml +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/deploy/manifests/kubernetes.yaml +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/docs/index.md +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/docs/modules/gpustack_runtime.deployer.md +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/docs/modules/gpustack_runtime.detector.md +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/docs/modules/gpustack_runtime.md +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/__main__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/_version.pyi +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/cmds/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/cmds/__types__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/cmds/deployer.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/cmds/detector.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/cmds/images.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/__patches__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/__types__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/__utils__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/cdi/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/cdi/__types__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/cdi/__utils__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/cdi/amd.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/cdi/ascend.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/cdi/hygon.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/cdi/iluvatar.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/cdi/metax.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/cdi/thead.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/docker.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/k8s/devicemanager/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/kuberentes.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/deployer/podman.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/__types__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/__utils__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/ascend.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/cambricon.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/iluvatar.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/metax.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/mthreads.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/nvidia.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pyamdgpu/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pyamdsmi/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pycndev/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pydcmi/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pydmi/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pyhgml/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pyhgml/libhgml.so +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pyhgml/libuki.so +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pyhsa/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pyixml/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pymtml/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pymxsml/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pynvml/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/pyrocmsmi/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/detector/thead.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/envs.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/gpustack_runtime/logging.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/hatch.toml +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/mkdocs.yml +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/pack/Dockerfile +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/pack/Dockerfile.dummy +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/pytest.ini +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/ruff.toml +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/specs/2026-08-14-detector-alignment-and-workload-exit-status.md +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/fixtures/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/fixtures/test_compare_versions.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/fixtures/test_correct_runner_image.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/fixtures/test_load_yaml_or_json.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/fixtures/test_load_yaml_or_json_multiple_jsons.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/fixtures/test_load_yaml_or_json_multiple_yamls.yaml +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/fixtures/test_load_yaml_or_json_single_json.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/fixtures/test_load_yaml_or_json_single_yaml.yaml +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/fixtures/test_nginx_entrypoint.sh +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/test_docker_status.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/test_kubernetes_status.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/test_podman_status.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/test_privileged.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/test_resource_injection_policy.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/test_runtime_class.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/test_termination_grace_period.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/test_utils.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/test_visible_devices_ordering.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/deployer/test_workload_status.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/fixtures/__init__.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/README.md +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_amd_mi300x.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_amd_mi308x.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_amd_rx7800xt.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_ascend_310p3.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_ascend_910b2.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_hygon_k100ai.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_metax_c500.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_gb10.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_h100.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_h100_mig.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_h200.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_rtx4080super.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_rtx4090_48g.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_rtx4090d.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_rtx5090d.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/detect_output_thead_ppu.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_amd_mi300x.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_amd_mi308x.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_amd_rx7800xt.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_ascend_310p3.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_ascend_910b2.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_hygon_k100ai.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_metax_c500.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_mthreads_s5000.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_h100.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_h100_mig.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_h200.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_rtx4080super.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_rtx4090_48g.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_rtx4090d.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_rtx5090d.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/samples/topology_output_thead_ppu.json +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_ascend.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_cambricon.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_detector_cli.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_detector_types.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_detector_utils.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_iluvatar.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_metax.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_mig_devices.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_mthreads.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_nvidia.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_pycndev.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_pydmi.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_samples.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_thead.py +0 -0
- {gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/uv.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: gpustack-runtime
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: GPUStack Runtime is library for detecting GPU resources and launching GPU workloads.
|
|
5
5
|
Project-URL: Homepage, https://github.com/gpustack/runtime
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/gpustack/gpustack/issues
|
|
@@ -16,7 +16,7 @@ Requires-Python: >=3.10
|
|
|
16
16
|
Requires-Dist: argcomplete>=3.6.3
|
|
17
17
|
Requires-Dist: cachetools>=5.5.2
|
|
18
18
|
Requires-Dist: docker>=7.1.0
|
|
19
|
-
Requires-Dist: gpustack-runner>=0.1.
|
|
19
|
+
Requires-Dist: gpustack-runner>=0.1.29
|
|
20
20
|
Requires-Dist: kubernetes>=33.1.0
|
|
21
21
|
Requires-Dist: mthreads-ml-py>=2.2.10
|
|
22
22
|
Requires-Dist: nvidia-ml-py>=13.580.65
|
|
@@ -27,8 +27,8 @@ version_tuple: VERSION_TUPLE
|
|
|
27
27
|
__commit_id__: COMMIT_ID
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
|
|
30
|
-
__version__ = version = '0.2.
|
|
31
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
30
|
+
__version__ = version = '0.2.5'
|
|
31
|
+
__version_tuple__ = version_tuple = (0, 2, 5)
|
|
32
32
|
try:
|
|
33
33
|
from ._version_appendix import git_commit
|
|
34
34
|
__commit_id__ = commit_id = git_commit
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
git_commit = "81fd0aa"
|
|
@@ -4,6 +4,7 @@ import contextlib
|
|
|
4
4
|
import logging
|
|
5
5
|
from functools import lru_cache
|
|
6
6
|
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
7
8
|
|
|
8
9
|
from .. import envs
|
|
9
10
|
from ..logging import debug_log_exception, debug_log_warning
|
|
@@ -137,7 +138,7 @@ class AMDDetector(Detector):
|
|
|
137
138
|
)
|
|
138
139
|
|
|
139
140
|
dev_gpu_driver_info = pyamdsmi.amdsmi_get_gpu_driver_info(dev)
|
|
140
|
-
dev_driver_ver = dev_gpu_driver_info
|
|
141
|
+
dev_driver_ver = _get_reading(dev_gpu_driver_info, "driver_version")
|
|
141
142
|
|
|
142
143
|
# The operator resolves the name from the local PCI ID database
|
|
143
144
|
# first: pci.ids knows the board -- the subsystem vendor's name
|
|
@@ -157,7 +158,7 @@ class AMDDetector(Detector):
|
|
|
157
158
|
):
|
|
158
159
|
dev_name = pyamdgpu.amdgpu_get_marketing_name(dev_gpudev)
|
|
159
160
|
if not dev_name:
|
|
160
|
-
dev_name = dev_gpu_asic_info
|
|
161
|
+
dev_name = _get_reading(dev_gpu_asic_info, "market_name", "")
|
|
161
162
|
|
|
162
163
|
dev_cc = dev_hsa_agent.compute_capability
|
|
163
164
|
if not dev_cc:
|
|
@@ -211,12 +212,12 @@ class AMDDetector(Detector):
|
|
|
211
212
|
# The power limit is inventory, so it stays here, while the used
|
|
212
213
|
# power the same call carries belongs to the usage query.
|
|
213
214
|
dev_power = None
|
|
214
|
-
|
|
215
|
+
with contextlib.suppress(pyamdsmi.AmdSmiException):
|
|
215
216
|
dev_power_info = pyamdsmi.amdsmi_get_power_info(dev)
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
dev_power_limit = _get_reading(dev_power_info, "power_limit")
|
|
218
|
+
if dev_power_limit is not None:
|
|
219
|
+
dev_power = dev_power_limit // 1000000 # uW to W
|
|
220
|
+
if dev_power is None:
|
|
220
221
|
with contextlib.suppress(pyrocmsmi.ROCMSMIError):
|
|
221
222
|
dev_power = pyrocmsmi.rsmi_dev_power_cap_get(dev_idx)
|
|
222
223
|
|
|
@@ -308,8 +309,14 @@ class AMDDetector(Detector):
|
|
|
308
309
|
dev_temp = None
|
|
309
310
|
try:
|
|
310
311
|
dev_gpu_metrics_info = pyamdsmi.amdsmi_get_gpu_metrics_info(dev)
|
|
311
|
-
dev_cores_util =
|
|
312
|
-
|
|
312
|
+
dev_cores_util = _get_reading(
|
|
313
|
+
dev_gpu_metrics_info,
|
|
314
|
+
"average_gfx_activity",
|
|
315
|
+
)
|
|
316
|
+
dev_temp = _get_reading(
|
|
317
|
+
dev_gpu_metrics_info,
|
|
318
|
+
"temperature_hotspot",
|
|
319
|
+
)
|
|
313
320
|
except pyamdsmi.AmdSmiException:
|
|
314
321
|
with contextlib.suppress(pyrocmsmi.ROCMSMIError):
|
|
315
322
|
dev_cores_util = pyrocmsmi.rsmi_dev_busy_percent_get(dev_idx)
|
|
@@ -353,15 +360,21 @@ class AMDDetector(Detector):
|
|
|
353
360
|
if dev_ecc_count.uncorrectable_err > 0:
|
|
354
361
|
dev_mem_status = DeviceMemoryStatusEnum.UNHEALTHY
|
|
355
362
|
|
|
363
|
+
# A sentinel reading means the same as a failed call -- AMD SMI
|
|
364
|
+
# cannot tell the used power -- so both route to ROCm SMI.
|
|
356
365
|
dev_power_used = None
|
|
357
|
-
|
|
366
|
+
with contextlib.suppress(pyamdsmi.AmdSmiException):
|
|
358
367
|
dev_power_info = pyamdsmi.amdsmi_get_power_info(dev)
|
|
359
|
-
dev_power_used = (
|
|
360
|
-
dev_power_info
|
|
361
|
-
|
|
362
|
-
else dev_power_info.get("average_socket_power", 0)
|
|
368
|
+
dev_power_used = _get_reading(
|
|
369
|
+
dev_power_info,
|
|
370
|
+
"current_socket_power",
|
|
363
371
|
)
|
|
364
|
-
|
|
372
|
+
if dev_power_used is None:
|
|
373
|
+
dev_power_used = _get_reading(
|
|
374
|
+
dev_power_info,
|
|
375
|
+
"average_socket_power",
|
|
376
|
+
)
|
|
377
|
+
if dev_power_used is None:
|
|
365
378
|
with contextlib.suppress(pyrocmsmi.ROCMSMIError):
|
|
366
379
|
dev_power_used = pyrocmsmi.rsmi_dev_power_get(dev_idx)
|
|
367
380
|
|
|
@@ -510,6 +523,31 @@ class AMDDetector(Detector):
|
|
|
510
523
|
return ret
|
|
511
524
|
|
|
512
525
|
|
|
526
|
+
def _get_reading(dev_info: dict, key: str, default: Any = None) -> Any:
|
|
527
|
+
"""
|
|
528
|
+
Read one value out of an AMD SMI answer, treating its sentinel as absent.
|
|
529
|
+
|
|
530
|
+
AMD SMI reports an unavailable reading in-band: it rewrites the 0xFFFF (or
|
|
531
|
+
max-uint) the driver answered into the string "N/A" before returning, so a
|
|
532
|
+
dict otherwise holding numbers can carry a string at any key. A VF is where
|
|
533
|
+
this surfaces, its host-side telemetry being invisible to the guest.
|
|
534
|
+
|
|
535
|
+
Args:
|
|
536
|
+
dev_info:
|
|
537
|
+
The answer AMD SMI returned.
|
|
538
|
+
key:
|
|
539
|
+
The reading to take.
|
|
540
|
+
default:
|
|
541
|
+
What an absent or unavailable reading becomes.
|
|
542
|
+
|
|
543
|
+
Returns:
|
|
544
|
+
The reading, or the default.
|
|
545
|
+
|
|
546
|
+
"""
|
|
547
|
+
dev_reading = dev_info.get(key, "N/A")
|
|
548
|
+
return default if dev_reading == "N/A" else dev_reading
|
|
549
|
+
|
|
550
|
+
|
|
513
551
|
def _get_pci_device_name_by_bdf(dev_bdf: str) -> str:
|
|
514
552
|
"""
|
|
515
553
|
Get the name of a device from the local PCI ID database.
|
|
@@ -349,8 +349,15 @@ class HygonDetector(Detector):
|
|
|
349
349
|
for dev_idx in range(devs_count):
|
|
350
350
|
dev_uuid = f"GPU-{pyrocmsmi.rsmi_dev_unique_id_get(dev_idx)[2:]}"
|
|
351
351
|
|
|
352
|
-
|
|
353
|
-
|
|
352
|
+
# Each reading is isolated on its own, mirroring the AMD path:
|
|
353
|
+
# ROCm SMI raises on one it cannot serve, and an unwrapped call
|
|
354
|
+
# would cost the whole sweep rather than the reading.
|
|
355
|
+
dev_cores_util = None
|
|
356
|
+
with contextlib.suppress(pyrocmsmi.ROCMSMIError):
|
|
357
|
+
dev_cores_util = pyrocmsmi.rsmi_dev_busy_percent_get(dev_idx)
|
|
358
|
+
dev_temp = None
|
|
359
|
+
with contextlib.suppress(pyrocmsmi.ROCMSMIError):
|
|
360
|
+
dev_temp = pyrocmsmi.rsmi_dev_temp_metric_get(dev_idx)
|
|
354
361
|
if dev_cores_util is None:
|
|
355
362
|
debug_log_warning(
|
|
356
363
|
logger,
|
|
@@ -376,7 +383,9 @@ class HygonDetector(Detector):
|
|
|
376
383
|
if dev_ecc_count.uncorrectable_err > 0:
|
|
377
384
|
dev_mem_status = DeviceMemoryStatusEnum.UNHEALTHY
|
|
378
385
|
|
|
379
|
-
dev_power_used =
|
|
386
|
+
dev_power_used = None
|
|
387
|
+
with contextlib.suppress(pyrocmsmi.ROCMSMIError):
|
|
388
|
+
dev_power_used = pyrocmsmi.rsmi_dev_power_get(dev_idx)
|
|
380
389
|
|
|
381
390
|
usages.append(
|
|
382
391
|
Device(
|
|
@@ -23,7 +23,7 @@ dependencies = [
|
|
|
23
23
|
# NB(thxCode): Pin to this Podman version for a custom patch. See gpustack_runtime/deployer/__patches__.py.
|
|
24
24
|
"podman==5.6.0",
|
|
25
25
|
"pyyaml",
|
|
26
|
-
"gpustack-runner>=0.1.
|
|
26
|
+
"gpustack-runner>=0.1.29",
|
|
27
27
|
"nvidia-ml-py>=13.580.65",
|
|
28
28
|
"mthreads-ml-py>=2.2.10",
|
|
29
29
|
"argcomplete>=3.6.3",
|
|
@@ -43,13 +43,13 @@ gpustack-runtime = "gpustack_runtime.__main__:main"
|
|
|
43
43
|
dev=[
|
|
44
44
|
"pyclean==3.4.0",
|
|
45
45
|
"pre-commit==4.5.0",
|
|
46
|
-
"pytest
|
|
46
|
+
"pytest>=9.0.3,<10",
|
|
47
47
|
"hatchling",
|
|
48
48
|
"hatch-vcs",
|
|
49
49
|
"mkdocs>=1.6.1",
|
|
50
50
|
"mkdocstrings-python>=1.18.0",
|
|
51
51
|
"mkdocs-material>=9.6.18",
|
|
52
|
-
"pymdown-extensions>=
|
|
52
|
+
"pymdown-extensions>=11.0.1",
|
|
53
53
|
"dockerpty>=0.4.1",
|
|
54
54
|
"amdsmi>=7.0.2",
|
|
55
55
|
]
|
{gpustack_runtime-0.2.4.post2 → gpustack_runtime-0.2.5}/tests/gpustack_runtime/detector/test_amd.py
RENAMED
|
@@ -152,7 +152,14 @@ class _FakeRocmSmi:
|
|
|
152
152
|
|
|
153
153
|
def rsmi_dev_power_get(self, dev_idx: int) -> int:
|
|
154
154
|
self.calls.append("rsmi_dev_power_get")
|
|
155
|
-
|
|
155
|
+
# A card whose fixture carries no used power stands for the one ROCm
|
|
156
|
+
# SMI cannot read either -- a VF, where the binding raises rather than
|
|
157
|
+
# answering the sentinel AMD SMI would.
|
|
158
|
+
power_used = self.cards[dev_idx]["power_used"]
|
|
159
|
+
if power_used is None:
|
|
160
|
+
msg = "power is not supported on this device"
|
|
161
|
+
raise _FakeRocmSmiError(msg)
|
|
162
|
+
return power_used
|
|
156
163
|
|
|
157
164
|
|
|
158
165
|
class _FakeHSA:
|
|
@@ -527,6 +534,94 @@ def test_detect_composes_the_information_and_the_usage(amd_bindings):
|
|
|
527
534
|
assert devices[0].power_used == 142
|
|
528
535
|
|
|
529
536
|
|
|
537
|
+
# --------------------------------------------------------------------------- #
|
|
538
|
+
# AMD SMI's "N/A": an unavailable reading is reported in-band, as a string #
|
|
539
|
+
# inside a dict otherwise holding numbers. A VF exposes no host-side power #
|
|
540
|
+
# telemetry, so its driver answers 0xFFFF and the library hands over "N/A". #
|
|
541
|
+
# --------------------------------------------------------------------------- #
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
def test_detect_info_falls_back_when_the_sentinel_hides_the_power_limit(amd_bindings):
|
|
545
|
+
# The limit is floor-divided from uW to W, so a sentinel reaching that
|
|
546
|
+
# arithmetic raises a TypeError -- which is not an AmdSmiException, so it
|
|
547
|
+
# escapes the handler and costs the host every AMD card.
|
|
548
|
+
card = _card("0000:05:00.0", "0x00a1b2c3d4e5f600")
|
|
549
|
+
card["power"]["power_limit"] = "N/A"
|
|
550
|
+
calls = amd_bindings([card], agents=[_agent("0000:05:00.0")])
|
|
551
|
+
|
|
552
|
+
devices = AMDDetector().detect_info()
|
|
553
|
+
|
|
554
|
+
assert "rsmi_dev_power_cap_get" in calls
|
|
555
|
+
assert devices[0].power == 700
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
def test_detect_info_reports_no_driver_version_when_the_sentinel_hides_it(
|
|
559
|
+
amd_bindings,
|
|
560
|
+
):
|
|
561
|
+
card = _card("0000:05:00.0", "0x00a1b2c3d4e5f600")
|
|
562
|
+
card["driver_info"]["driver_version"] = "N/A"
|
|
563
|
+
amd_bindings([card], agents=[_agent("0000:05:00.0")])
|
|
564
|
+
|
|
565
|
+
devices = AMDDetector().detect_info()
|
|
566
|
+
|
|
567
|
+
assert devices[0].driver_version is None
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
def test_detect_info_never_names_a_board_after_the_sentinel(amd_bindings):
|
|
571
|
+
# The ASIC market name is the last link of the name chain, so a sentinel
|
|
572
|
+
# there would otherwise be stored as the board's name.
|
|
573
|
+
card = _card("0000:05:00.0", "0x00a1b2c3d4e5f600")
|
|
574
|
+
card["asic_info"]["market_name"] = "N/A"
|
|
575
|
+
amd_bindings([card], pci_ids=None)
|
|
576
|
+
|
|
577
|
+
devices = AMDDetector().detect_info()
|
|
578
|
+
|
|
579
|
+
assert devices[0].name == ""
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
def test_detect_usage_falls_back_when_the_sentinel_hides_the_socket_power(
|
|
583
|
+
amd_bindings,
|
|
584
|
+
):
|
|
585
|
+
# The sentinel has to route to the ROCm SMI fallback the same way an AMD
|
|
586
|
+
# SMI failure does -- both mean "AMD SMI cannot tell us the used power".
|
|
587
|
+
card = _card("0000:05:00.0", "0x00a1b2c3d4e5f600")
|
|
588
|
+
card["power"]["current_socket_power"] = "N/A"
|
|
589
|
+
card["power"]["average_socket_power"] = "N/A"
|
|
590
|
+
calls = amd_bindings([card], agents=[_agent("0000:05:00.0")])
|
|
591
|
+
|
|
592
|
+
devices = AMDDetector().detect_usage()
|
|
593
|
+
|
|
594
|
+
assert "rsmi_dev_power_get" in calls
|
|
595
|
+
assert devices[0].power_used == 131
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
def test_detect_usage_reports_no_power_when_no_binding_can_read_it(amd_bindings):
|
|
599
|
+
# The reported VF: AMD SMI answers the sentinel for both socket readings
|
|
600
|
+
# and ROCm SMI cannot read the power either, so the field is absent rather
|
|
601
|
+
# than carrying a string the consumer parses as a number.
|
|
602
|
+
card = _card("0000:05:00.0", "0x00a1b2c3d4e5f600")
|
|
603
|
+
card["power"]["current_socket_power"] = "N/A"
|
|
604
|
+
card["power"]["average_socket_power"] = "N/A"
|
|
605
|
+
card["power_used"] = None
|
|
606
|
+
amd_bindings([card], agents=[_agent("0000:05:00.0")])
|
|
607
|
+
|
|
608
|
+
devices = AMDDetector().detect_usage()
|
|
609
|
+
|
|
610
|
+
assert devices[0].power_used is None
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
def test_detect_usage_reports_no_metrics_when_the_sentinel_hides_them(amd_bindings):
|
|
614
|
+
card = _card("0000:05:00.0", "0x00a1b2c3d4e5f600")
|
|
615
|
+
card["metrics"]["average_gfx_activity"] = "N/A"
|
|
616
|
+
card["metrics"]["temperature_hotspot"] = "N/A"
|
|
617
|
+
amd_bindings([card], agents=[_agent("0000:05:00.0")])
|
|
618
|
+
|
|
619
|
+
devices = AMDDetector().detect_usage()
|
|
620
|
+
|
|
621
|
+
assert devices[0].cores_utilization == 0
|
|
622
|
+
assert devices[0].temperature is None
|
|
623
|
+
|
|
624
|
+
|
|
530
625
|
# --------------------------------------------------------------------------- #
|
|
531
626
|
# The CDI generator, which numbers its device nodes from the appendix. #
|
|
532
627
|
# --------------------------------------------------------------------------- #
|
|
@@ -244,11 +244,11 @@ class _FakeRocmSmi:
|
|
|
244
244
|
|
|
245
245
|
def rsmi_dev_busy_percent_get(self, dev_idx: int) -> int:
|
|
246
246
|
self.calls.append("rsmi_dev_busy_percent_get")
|
|
247
|
-
return self.
|
|
247
|
+
return self._reading(dev_idx, "busy_percent")
|
|
248
248
|
|
|
249
249
|
def rsmi_dev_temp_metric_get(self, dev_idx: int) -> int:
|
|
250
250
|
self.calls.append("rsmi_dev_temp_metric_get")
|
|
251
|
-
return self.
|
|
251
|
+
return self._reading(dev_idx, "temperature")
|
|
252
252
|
|
|
253
253
|
def rsmi_dev_power_cap_get(self, dev_idx: int) -> int:
|
|
254
254
|
self.calls.append("rsmi_dev_power_cap_get")
|
|
@@ -256,7 +256,17 @@ class _FakeRocmSmi:
|
|
|
256
256
|
|
|
257
257
|
def rsmi_dev_power_get(self, dev_idx: int) -> int:
|
|
258
258
|
self.calls.append("rsmi_dev_power_get")
|
|
259
|
-
return self.
|
|
259
|
+
return self._reading(dev_idx, "power_used")
|
|
260
|
+
|
|
261
|
+
def _reading(self, dev_idx: int, key: str) -> int:
|
|
262
|
+
# A card whose fixture carries None for a reading stands for the one
|
|
263
|
+
# ROCm SMI cannot answer: the binding checks every return code and
|
|
264
|
+
# raises, rather than handing back a sentinel the way AMD SMI does.
|
|
265
|
+
reading = self.cards[dev_idx][key]
|
|
266
|
+
if reading is None:
|
|
267
|
+
msg = f"{key} is not supported on this device"
|
|
268
|
+
raise _FakeRocmSmiError(msg)
|
|
269
|
+
return reading
|
|
260
270
|
|
|
261
271
|
def rsmi_topo_get_numa_node_number(self, dev_idx: int) -> int:
|
|
262
272
|
return self.cards[dev_idx]["numa"]
|
|
@@ -629,6 +639,45 @@ def test_detect_composes_the_information_and_the_usage(hygon_bindings):
|
|
|
629
639
|
assert devices[0].power_used == 217
|
|
630
640
|
|
|
631
641
|
|
|
642
|
+
def test_detect_usage_bounds_an_unreadable_power_to_its_own_card(hygon_bindings):
|
|
643
|
+
# ROCm SMI raises on a reading it cannot serve, so an unwrapped read takes
|
|
644
|
+
# the whole sweep down with it and leaves every card on the host with its
|
|
645
|
+
# information-query values.
|
|
646
|
+
hygon_bindings(
|
|
647
|
+
[
|
|
648
|
+
_card("0000:0b:00.0", "0x9f8e7d6c5b4a3921", power_used=None),
|
|
649
|
+
_card("0000:0c:00.0", "0x9f8e7d6c5b4a3922"),
|
|
650
|
+
],
|
|
651
|
+
agents=[_agent("0000:0b:00.0"), _agent("0000:0c:00.0")],
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
devices = HygonDetector().detect_usage()
|
|
655
|
+
|
|
656
|
+
assert [dev.power_used for dev in devices] == [None, 217]
|
|
657
|
+
# The rest of the faulty card's usage still arrives, and the healthy card
|
|
658
|
+
# is untouched.
|
|
659
|
+
assert [dev.cores_utilization for dev in devices] == [44, 44]
|
|
660
|
+
assert [dev.temperature for dev in devices] == [51, 51]
|
|
661
|
+
assert [dev.memory_used for dev in devices] == [1024, 1024]
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
def test_detect_usage_bounds_an_unreadable_utilization_to_its_own_reading(
|
|
665
|
+
hygon_bindings,
|
|
666
|
+
):
|
|
667
|
+
# Each reading is isolated on its own, so an unreadable utilization does
|
|
668
|
+
# not carry off the temperature the next call would have served.
|
|
669
|
+
hygon_bindings(
|
|
670
|
+
[_card("0000:0b:00.0", "0x9f8e7d6c5b4a3921", busy_percent=None)],
|
|
671
|
+
agents=[_agent("0000:0b:00.0")],
|
|
672
|
+
)
|
|
673
|
+
|
|
674
|
+
devices = HygonDetector().detect_usage()
|
|
675
|
+
|
|
676
|
+
assert devices[0].cores_utilization == 0
|
|
677
|
+
assert devices[0].temperature == 51
|
|
678
|
+
assert devices[0].power_used == 217
|
|
679
|
+
|
|
680
|
+
|
|
632
681
|
# --------------------------------------------------------------------------- #
|
|
633
682
|
# The CDI generator, which numbers its device nodes from the appendix. #
|
|
634
683
|
# --------------------------------------------------------------------------- #
|