如何在电路板上发现PCIe总线拓扑和插槽号?

时间:2015-08-18 13:21:29

标签: c++ windows cuda pci pci-e

例如,当我使用带有CUDA C / C ++和GPUDirect 2.0 P2P的多GPU系统时,我使用嵌套的PCI-Express交换机,如图所示,那么我必须知道任何两个GPU之间有多少交换机PCI总线ID,用于优化数据传输和计算分配。

或者如果我已经知道带有PCIe交换机的硬件PCIe拓扑,那么我必须知道,板上哪个硬件PCIe插槽连接了任何GPU卡。 enter image description here

据我所知,即使我已经知道具有PCIe交换机的硬件PCIe拓扑,这些标识符也不会硬连接到板上的PCIe插槽,并且这些ID可能会发生变化,并且与系统的运行不同:

  • CUDA device_id
  • nvidia-smi / nvml GPU id
  • PCI总线ID

使用详细的设备树和电路板上的PCIe插槽数量来发现PCIe总线拓扑的最佳方法是什么?在Windows和Linux上

7 个答案:

答案 0 :(得分:5)

以下是不需要解析注册表的脚本版本。所有信息(此处使用)均在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]
                }
            }
        }
    }
} 

答案 1 :(得分:3)

PCI设备(端点)具有唯一的地址。这个地址有3个部分:

  • BusID
  • 的DeviceID
  • 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将总线02的设备00到03列为连接到总线00,设备11,功能0

根据这些信息,您可以重建完整的PCI总线树。除非您添加或删除设备,否则启动后树始终相同。

Windows设备管理器提供相同的信息。属性对话框显示设备类型,供应商和位置:例如PCI bus 0, device 2, function 0用于集成Intel HD 4600显卡。

目前,我不知道如何通过脚本或编程语言在Windows环境中获取这些信息,但互联网上有商业和免费工具提供这些信息。也许有一个API。

答案 2 :(得分:1)

在Windows上,您可以使用例如:以下Powershell-Script和Windows设备驱动程序工具包中的devcon.exe工具:

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

答案 3 :(得分: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

答案 4 :(得分:1)

对于网络适配器,从Windows 8或Windows 2012开始,可以使用WMI类MSFT_NetAdapterHardwareInfoSettingData

gwmi -Namespace root\standardcimv2 MSFT_NetAdapterHardwareInfoSettingData | Format-Table Description,BusNumber,DeviceNumber,FunctionNumber

Description                        BusNumber DeviceNumber FunctionNumber
-----------                        --------- ------------ --------------
Red Hat VirtIO Ethernet Adapter #6         0           17              0
Red Hat VirtIO Ethernet Adapter #3         0            9              0
Red Hat VirtIO Ethernet Adapter #5         0           16              0
Red Hat VirtIO Ethernet Adapter #2         0            8              0
Red Hat VirtIO Ethernet Adapter #7         0           18              0
Red Hat VirtIO Ethernet Adapter #8         0           19              0
Red Hat VirtIO Ethernet Adapter            0            3              0
Red Hat VirtIO Ethernet Adapter #4         0           10              0

...或PowerShell命令Get-NetAdapterHardwareInfo

Get-NetAdapterHardwareInfo | Format-Table Description,Bus,Device,Function

Description                        Bus Device Function
-----------                        --- ------ --------
Red Hat VirtIO Ethernet Adapter #6   0     17        0
Red Hat VirtIO Ethernet Adapter #3   0      9        0
Red Hat VirtIO Ethernet Adapter #5   0     16        0
Red Hat VirtIO Ethernet Adapter #2   0      8        0
Red Hat VirtIO Ethernet Adapter #7   0     18        0
Red Hat VirtIO Ethernet Adapter #8   0     19        0
Red Hat VirtIO Ethernet Adapter      0      3        0
Red Hat VirtIO Ethernet Adapter #4   0     10        0

答案 5 :(得分:0)

在Windows上,设备ID和功能也被编码在PNPDeviceID的最后一部分中,这很容易获得。但是,没有记录它们的编码方式。

示例:PCI\\VEN_8086&DEV_2829&SUBSYS_00000000&REV_02\\3&267A616A&0&68

68(十六进制)可能是 device 数字13(十进制)向左移动3位,而最后3位可能是 function 数字0。 由于 function 通常为0,因此您可能会注意到PNPDeviceID的大多数值都以08结尾。 3位偏移可能来自CONFIG_ADDRESS PCI register

  

CONFIG_ADDRESS的格式如下:

     

0x80000000 |公共汽车<< 16 |设备<< 11 |功能<< 8 |偏移量

另请参阅Intel chipset documentation,第5页:

  
      
  1. 必须将设备的“ PCI设备号”写入设备的[15:11]位   I / O位置CF8h
  2.   
0之前的

68可能表示公共汽车号。

答案 6 :(得分:0)

-a的设备属性中,在注册表项或-a的输出中,有Address属性。这是32位整数(WMI_PnPDevice),其中高16位是设备号,低16位是函数号:

devcon.exe

Question关于地址和answer的含义。 我的answer on related question