例如,当我使用带有CUDA C / C ++和GPUDirect 2.0 P2P的多GPU系统时,我使用嵌套的PCI-Express交换机,如图所示,那么我必须知道任何两个GPU之间有多少交换机PCI总线ID,用于优化数据传输和计算分配。
或者如果我已经知道带有PCIe交换机的硬件PCIe拓扑,那么我必须知道,板上哪个硬件PCIe插槽连接了任何GPU卡。
据我所知,即使我已经知道具有PCIe交换机的硬件PCIe拓扑,这些标识符也不会硬连接到板上的PCIe插槽,并且这些ID可能会发生变化,并且与系统的运行不同:
使用详细的设备树和电路板上的PCIe插槽数量来发现PCIe总线拓扑的最佳方法是什么?在Windows和Linux上?
答案 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个部分:
例如,总线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
的大多数值都以0
或8
结尾。 3位偏移可能来自CONFIG_ADDRESS
PCI register:
CONFIG_ADDRESS的格式如下:
0x80000000 |公共汽车<< 16 |设备<< 11 |功能<< 8 |偏移量
另请参阅Intel chipset documentation,第5页:
在
- 必须将设备的“ PCI设备号”写入设备的[15:11]位 I / O位置CF8h
0
之前的 68
可能表示公共汽车号。
答案 6 :(得分:0)
在-a
的设备属性中,在注册表项或-a
的输出中,有Address
属性。这是32位整数(WMI_PnPDevice
),其中高16位是设备号,低16位是函数号:
devcon.exe
Question关于地址和answer的含义。 我的answer on related question。