Как узнать топологию шины PCIe и номера слотов на плате?

Например, когда я использую систему с несколькими графическими процессорами с CUDA C / C ++ и GPUDirect 2.0 P2P и использую вложенные коммутаторы PCI-Express, как показано на рисунке, то я должен знать, сколько коммутаторов между любыми двумя графическими процессорами использует их идентификатор шины PCI. , для оптимизации передачи данных и распределения расчетов.

Или, если я уже знаю аппаратную топологию PCIe с PCIe-коммутаторами, то я должен знать, к какому аппаратному слоту PCIe на плате подключена любая видеокарта.
введите описание изображения здесь

Как я знаю, даже если я уже знаю аппаратную топологию PCIe с PCIe-коммутаторами, эти идентификаторы не привязаны жестко к слотам PCIe на плате, и эти идентификаторы могут изменяться и отличаться от запуска к запуску системы:

  • CUDA device_id
  • nvidia-smi / nvml идентификатор графического процессора
  • Идентификатор шины PCI

Как лучше всего определить топологию шины PCIe с подробным деревом устройств и количеством слотов PCIe на плате? в Windows и Linux?

3

Решение

Вот версия скрипта, которая не нуждается в разборе реестра. Вся информация (используемая здесь) доступна в win32_pnpentity.

Function Get-BusFunctionID {

gwmi -namespace root\cimv2 -class Win32_PnPEntity |% {

if ($_.PNPDeviceID -like "PCI\*") {

$locationInfo = $_.GetDeviceProperties('DEVPKEY_Device_LocationInfo').deviceProperties.Data

if ($locationInfo -match 'PCI bus (\d+), device (\d+), function (\d+)') {

new-object psobject -property @{
"Name"       = $_.Name
"PnPID"      = $_.PNPDeviceID
"BusID"      = $matches[1]
"DeviceID"   = $matches[2]
"FunctionID" = $matches[3]
}
}
}
}
}
4

Другие решения

Устройства PCI (конечные точки) имеют уникальный адрес. Этот адрес состоит из 3 частей:

  • BusID
  • Идентификатор устройства
  • FunctionID

Например, функция 3 устройства 12 на шине 3 записана в виде BDF: 03:0C.3, Расширенная нотация BDF добавляет домен (в основном 0000) в качестве префикса: 0000:03:0c.3,

Linux перечисляет эти устройства в /sys/bus/pci/devices

paebbels@debian8:~$ ll /sys/bus/pci/devices/
drwxr-xr-x 2 root root 0 Aug 19 11:44 .
drwxr-xr-x 5 root root 0 Aug  5 15:14 ..
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:00.0 -> ../../../devices/pci0000:00/0000:00:00.0
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:01.0 -> ../../../devices/pci0000:00/0000:00:01.0
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:07.0 -> ../../../devices/pci0000:00/0000:00:07.0
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:07.1 -> ../../../devices/pci0000:00/0000:00:07.1
...
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:18.6 -> ../../../devices/pci0000:00/0000:00:18.6
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:18.7 -> ../../../devices/pci0000:00/0000:00:18.7
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:02:00.0 -> ../../../devices/pci0000:00/0000:00:11.0/0000:02:00.0
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:02:01.0 -> ../../../devices/pci0000:00/0000:00:11.0/0000:02:01.0
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:02:02.0 -> ../../../devices/pci0000:00/0000:00:11.0/0000:02:02.0
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:02:03.0 -> ../../../devices/pci0000:00/0000:00:11.0/0000:02:03.0
lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:03:00.0 -> ../../../devices/pci0000:00/0000:00:15.0/0000:03:00.0

Здесь вы можете видеть, что sys-fs перечисляет устройства с 00 по 03 шины 02 как подключенные к шине 00, устройство 11, функция 0

Исходя из этой информации, вы можете перестроить полное дерево шин PCI. Дерево всегда одинаково после загрузки, если только вы не добавляете и не удаляете устройства.

Диспетчер устройств Windows предлагает ту же информацию. Диалог свойств показывает тип устройства, поставщика и местоположение: например, PCI bus 0, device 2, function 0 для интегрированной графики Intel HD 4600.

В настоящее время я не знаю, как вы можете получить эту информацию с помощью сценариев или языка программирования в среде Windows, но в Интернете есть коммерческие и бесплатные инструменты, которые предоставляют эту информацию. Может быть, есть API.

2

В Windows вы можете использовать, например: следующий скрипт Powershell-Script с инструментом devcon.exe из набора драйверов устройств Windows:

Function Get-BusFunctionID {
$Devices = .\devcon.exe find PCI\*

for($i=0; $i -lt $Devices.length; $i++) {

if(!($Devices[$i] -match "PCI\\*")) {
continue
}
$DevInfo = $Devices[$i].split(":")
$deviceId = $DevInfo[0]
$locationInfo = (get-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Enum\$deviceID" -name locationinformation).locationINformation

$businfo = Resolve-PCIBusInfo -locationInfo $locationinfo

new-object psobject -property @{
"Name"        = $DevInfo[1];
"PnPID"       = $DevInfo[0]
"PCIBusID"      = $businfo.BusID;
"PCIDeviceID"   = $businfo.DeviceID;
"PCIFunctionID" = $businfo.FunctionID
}
}
}

Function Resolve-PCIBusInfo {

param (
[parameter(ValueFromPipeline=$true,Mandatory=$true)]
[string]
$locationInfo
)
PROCESS {
[void]($locationInfo -match  "\d+,\d+,\d+")
$busId,$deviceID,$functionID = $matches[0] -split ","
new-object psobject -property @{
"BusID" = $busID;
"DeviceID" = "$deviceID""FunctionID" = "$functionID"}
}
}

Пример использования:

Get-BusFunctionID | Where-Object {$_.PCIBusID -eq 0 -and $_.PCIDeviceID -eq 0} | Format-Table
Get-BusFunctionID | Sort-Object PCIBusID, PCIDeviceID, PCIFunctionID | Format-Table -GroupBy PCIBusID
Get-BusFunctionID | Sort-Object PCIBusID, PCIDeviceID, PCIFunctionID | Out-GridView
1

Для Windows готов запустить Powershell-скрипт:

Function Get-BusFunctionID {
#gwmi -query "SELECT * FROM Win32_PnPEntity"$Devices = get-wmiobject -namespace root\cimv2 -class Win32_PnPEntity

for($i=0; $i -lt $Devices.length; $i++) {

if(!($Devices[$i].PNPDeviceID -match "PCI\\*")) {
continue
}
$deviceId = $Devices[$i].PNPDeviceID
$locationInfo = (get-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Enum\$deviceID" -name locationinformation).locationINformation

$businfo = Resolve-PCIBusInfo -locationInfo $locationinfo

new-object psobject -property @{
"Name"        = $Devices[$i].Name;
"PnPID"       = $Devices[$i].PNPDeviceID
"PCIBusID"      = $businfo.BusID;
"PCIDeviceID"   = $businfo.DeviceID;
"PCIFunctionID" = $businfo.FunctionID
}
}
}

Function Resolve-PCIBusInfo {

param (
[parameter(ValueFromPipeline=$true,Mandatory=$true)]
[string]
$locationInfo
)
PROCESS {
[void]($locationInfo -match  "\d+,\d+,\d+")
$busId,$deviceID,$functionID = $matches[0] -split ","
new-object psobject -property @{
"BusID" = $busID;
"DeviceID" = "$deviceID""FunctionID" = "$functionID"}
}
}

Пример использования:

Get-BusFunctionID | Where-Object {$_.PCIBusID -eq 0 -and $_.PCIDeviceID -eq 0} | Format-Table
Get-BusFunctionID | Sort-Object PCIBusID, PCIDeviceID, PCIFunctionID | Format-Table -GroupBy
0
По вопросам рекламы [email protected]