File size: 4,562 Bytes
e2fa5fb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | """Report Anima MixBit runtime-mode eligibility for the local NVIDIA GPU."""
from __future__ import annotations
import argparse
import json
import sys
from typing import Any
STANDARD_VALIDATED_NAMES = (
"nvidia geforce rtx 3090",
"nvidia geforce rtx 5080 laptop gpu",
)
LOW_VRAM_VALIDATED_NAMES = ("nvidia geforce rtx 5080 laptop gpu",)
def native_nvfp4_eligible(capability: tuple[int, int]) -> bool:
"""Match the native scaled_mm capability gate used by the runtime."""
major, minor = capability
return (major, minor) == (8, 9) or major >= 9
def classify(name: str, capability: tuple[int, int]) -> dict[str, Any]:
normalized = name.strip().lower()
native_eligible = native_nvfp4_eligible(capability)
standard_validated = any(item in normalized for item in STANDARD_VALIDATED_NAMES)
low_vram_validated = any(item in normalized for item in LOW_VRAM_VALIDATED_NAMES)
if low_vram_validated:
low_vram_status = "validated"
elif native_eligible:
low_vram_status = "capability_eligible_not_package_validated"
else:
low_vram_status = "unsupported_by_native_nvfp4_gate"
return {
"name": name,
"compute_capability": f"{capability[0]}.{capability[1]}",
"standard_mode": "validated" if standard_validated else "not_package_validated",
"low_vram_mode": low_vram_status,
"native_nvfp4_eligible": native_eligible,
"recommended_mode": (
"low_vram_or_standard" if native_eligible else "standard"
),
}
def self_test() -> int:
expectations = {
(8, 0): False,
(8, 6): False,
(8, 9): True,
(9, 0): True,
(12, 0): True,
}
for capability, expected in expectations.items():
actual = native_nvfp4_eligible(capability)
if actual != expected:
raise AssertionError(f"Capability {capability}: {actual} != {expected}")
print("PASS: GPU compatibility rules are internally consistent.")
return 0
def inspect_device(index: int) -> dict[str, Any]:
try:
import torch
except ImportError as error:
return {
"ready": False,
"error": f"PyTorch is not installed: {error}",
}
if not torch.cuda.is_available():
return {
"ready": False,
"error": "CUDA is not available. This package has no validated CPU runtime.",
}
if index < 0 or index >= torch.cuda.device_count():
return {
"ready": False,
"error": f"CUDA device index {index} is out of range.",
}
name = torch.cuda.get_device_name(index)
capability = tuple(int(value) for value in torch.cuda.get_device_capability(index))
result = classify(name, capability)
result.update(
{
"ready": True,
"device_index": index,
"pytorch": torch.__version__,
"cuda_runtime": torch.version.cuda,
}
)
return result
def print_human(result: dict[str, Any]) -> None:
if not result.get("ready"):
print(f"判定不能: {result['error']}")
return
standard = {
"validated": "実機検証済み",
"not_package_validated": "このパッケージでは未検証",
}[result["standard_mode"]]
low_vram = {
"validated": "実機検証済み",
"capability_eligible_not_package_validated": "演算条件適合・パッケージ未検証",
"unsupported_by_native_nvfp4_gate": "非対応(native NVFP4条件外)",
}[result["low_vram_mode"]]
recommendation = (
"VRAMを優先するなら省VRAM、速度と互換性を優先するなら通常"
if result["native_nvfp4_eligible"]
else "通常"
)
print(f"GPU: {result['name']}")
print(f"Compute Capability: {result['compute_capability']}")
print(f"通常モード: {standard}")
print(f"省VRAMモード: {low_vram}")
print(f"推奨: {recommendation}")
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--device", type=int, default=0)
parser.add_argument("--json", action="store_true")
parser.add_argument("--self-test", action="store_true")
args = parser.parse_args()
if args.self_test:
return self_test()
result = inspect_device(args.device)
if args.json:
print(json.dumps(result, ensure_ascii=False, indent=2))
else:
print_human(result)
return 0 if result.get("ready") else 2
if __name__ == "__main__":
sys.exit(main())
|