重置GPU.ps1
|
<#PSScriptInfo
.VERSION 1.0.0 .GUID 9c750cc4-ecc4-4f74-876c-4331a1c820ce .AUTHOR 埃博拉酱 .COMPANYNAME 无 .COPYRIGHT (c) 2026 埃博拉酱 .TAGS NVIDIA GPU Reset TDR PnP CUDA 显卡 重置 .LICENSEURI https://opensource.org/licenses/MIT .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .SYNOPSIS 重置指定序号的 NVIDIA GPU(无需重启整机) .DESCRIPTION 参考 https://juejin.cn/post/7663097122267414555 通过 Windows PnP 接口禁用再启用目标 GPU,触发驱动重新初始化, 清空 CUDA context、复位传感器、恢复时钟。 .PARAMETER 序号 GPU 在 nvidia-smi 中显示的序号(0, 1, 2, ...) .EXAMPLE .\重置GPU.ps1 -序号 1 重置 GPU 1 .NOTES - 仅限未连接显示器的 GPU(Display Attached = No) - 重置会断开该 GPU 上所有 CUDA context,正在运行的计算任务将丢失 - 需要管理员权限运行 #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, HelpMessage = "GPU 序号(nvidia-smi 中的 index)")] [int]$序号 ) $ErrorActionPreference = 'Stop' # ========== 0. 检查管理员权限 ========== $当前用户 = [Security.Principal.WindowsIdentity]::GetCurrent() $主体 = New-Object Security.Principal.WindowsPrincipal($当前用户) if (-not $主体.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Error "请以管理员身份运行 PowerShell 后重试" exit 1 } # ========== 1. 获取目标 GPU 的 PCI 总线号 ========== Write-Host "==> 查询 GPU $序号 的 PCI 总线号..." -ForegroundColor Cyan $所有行 = nvidia-smi --query-gpu=index,pci.bus_id --format=csv,noheader $目标行 = $所有行 | Where-Object { [int](($_ -split ',')[0].Trim()) -eq $序号 } if (-not $目标行) { Write-Error "未找到序号为 $序号 的 GPU,请检查 nvidia-smi 输出" exit 1 } # bus_id 形如 00000000:36:00.0,取中间段十六进制转十进制 $总线号十六进制 = (($目标行 -split ',')[1].Trim() -split ':')[1] $总线号 = [Convert]::ToInt32($总线号十六进制, 16) Write-Host " PCI 总线号: 0x$总线号十六进制 = $总线号 (十进制)" # ========== 2. 确认 GPU 未连接显示器 ========== Write-Host "==> 检查显示器连接状态..." -ForegroundColor Cyan $显示状态 = nvidia-smi -q -i $序号 | Select-String -Pattern 'Display Attached|Display Active' $已连接显示器 = ($显示状态 -match 'Display Attached\s+:\s+Yes') if ($已连接显示器) { Write-Error "GPU $序号 连接了显示器,禁用会导致黑屏,操作已中止" exit 1 } Write-Host " Display Attached: No (可安全重置)" # ========== 3. 通过 PCI 总线号匹配 PnP InstanceId ========== Write-Host "==> 匹配 PnP InstanceId..." -ForegroundColor Cyan $显示设备 = Get-PnpDevice -Class 'Display' -Status OK, Unknown | Where-Object { $_.FriendlyName -like '*NVIDIA*' } $实例ID = $null foreach ($设备 in $显示设备) { $位置信息 = Get-PnpDeviceProperty -InstanceId $设备.InstanceId ` -KeyName 'DEVPKEY_Device_LocationInfo' -ErrorAction SilentlyContinue # 位置信息形如 "PCI bus 54, device 0, function 0" 或 "PCI 总线 54、设备 0、功能 0" if ($位置信息.Data -match "PCI (bus|总线)\s*$总线号[、,]") { $实例ID = $设备.InstanceId break } } if (-not $实例ID) { Write-Error "未找到 PCI 总线 $总线号 对应的 NVIDIA PnP 设备" exit 1 } Write-Host " InstanceId: $实例ID" # ========== 4. 显示重置前状态 ========== Write-Host "`n===== 重置前状态 =====" -ForegroundColor Yellow nvidia-smi --query-gpu=index,utilization.gpu,power.draw,temperature.gpu,pstate,memory.used ` --format=csv -i $序号 # ========== 5. 禁用 → 等待 → 启用 ========== Write-Host "`n==> 正在禁用 GPU $序号 ..." -ForegroundColor Cyan Disable-PnpDevice -InstanceId $实例ID -Confirm:$false Write-Host "==> 等待 3 秒..." -ForegroundColor Cyan Start-Sleep -Seconds 3 Write-Host "==> 正在重新启用 GPU $序号 ..." -ForegroundColor Cyan Enable-PnpDevice -InstanceId $实例ID -Confirm:$false # 等待驱动初始化完成 Start-Sleep -Seconds 2 # ========== 6. 验证重置结果 ========== Write-Host "`n===== 重置后状态 =====" -ForegroundColor Green nvidia-smi --query-gpu=index,utilization.gpu,power.draw,temperature.gpu,pstate,memory.used ` --format=csv -i $序号 Write-Host "`nGPU $序号 重置完成 ✓" -ForegroundColor Green Write-Host "提示:若利用率/功耗/温度仍为异常组合,可能需要重启整机" -ForegroundColor DarkGray |