The Virtual Topology Mirage: Chasing PCIe P2P in a Proxmox VM with 8 Blackwell GPUs
In the high-stakes world of multi-GPU machine learning inference, communication between GPUs is the invisible bottleneck that can make or break performance. When deploying a model like GLM-5-NVFP4 across 8 NVIDIA RTX PRO 6000 Blackwell GPUs, every microsecond of cross-GPU latency compounds across hundreds of all-reduce operations per inference step. This article examines a pivotal moment in a debugging session where an AI assistant, after hours of battling IOMMU groups, ACS settings, and BAR allocation failures, arrives at a clear-eyed understanding of the VM's PCIe topology and proposes an ambitious—and potentially futile—next step: building virtual PCIe switches to trick the NVIDIA driver into seeing a more favorable topology.
The Message in Context
The subject message, <msg id=375>, is the assistant's response after the user has been relentlessly pushing to get P2P (peer-to-peer) DMA working between GPUs in a Proxmox virtual machine. The conversation leading up to this point has been a journey of escalating complexity. Earlier segments covered installing NVIDIA drivers, resolving flash-attn build issues, deploying the GLM-5-NVFP4 model with SGLang, and discovering that the model crashes during decode due to NaN values—a problem eventually traced to attention backend compatibility. But the deeper, more insidious performance problem has been cross-GPU communication latency.
The user had shared the bare-metal nvidia-smi topo output showing a clean NUMA topology: GPUs 0-3 on NUMA node 0 with NODE interconnects, GPUs 4-7 on NUMA node 1 with NODE interconnects, and cross-socket links showing SYS. In the VM, however, all GPU pairs showed PHB—a flat topology that gives NCCL no information to optimize communication locality. The assistant had already investigated ACS disabling, IOMMU group merging, and kernel parameters, only to conclude that the hardware topology (each GPU on its own PCIe root complex on the ASUS ESC8000A-E13 motherboard) fundamentally prevents P2P in a VM.
Decoding the PCIe Topology Map
The message begins with the assistant laying out the VM's PCIe topology in a clear, structured format:
Now I can see the full picture. The VM has GPUs at: -00:10.0→ bus01(hostpci0) — PCIe Root Port group 1 -00:10.1→ bus02(hostpci1) -00:10.2→ bus03(hostpci2) -00:10.3→ bus04(hostpci3) -00:1c.0→ bus05(hostpci4) — PCIe Root Port group 2 (ICH9 PCIe ports) -00:1c.1→ bus06(hostpci5) -00:1c.2→ bus07(hostpci6) -00:1c.3→ bus08(hostpci7)
This mapping reveals something important: the eight GPUs are split across two groups of PCIe root ports. The first four (hostpci0 through hostpci3) hang off the PCIe root port at 00:10.[0-3], while the second four (hostpci4 through hostpci7) hang off a different set of root ports at 00:1c.[0-3]. The latter group uses ICH9 PCIe ports, which is a clue about the underlying QEMU chipset emulation.
The assistant correctly identifies the critical open question: are hostpci0-3 the NUMA 0 GPUs and hostpci4-7 the NUMA 1 GPUs? This is the linchpin of the entire topology optimization effort. If the mapping aligns—the first four physical GPUs (at PCI addresses 01:00.0, 11:00.0, 61:00.0, 71:00.0 on the host, all on NUMA 0) happen to be assigned to hostpci0-3, and the NUMA 1 GPUs (81:00.0, 91:00.0, e1:00.0, f1:00.0) to hostpci4-7—then the virtual topology already mirrors the physical NUMA split, and the assistant can build virtual PCIe switches to expose it. If the mapping is scrambled, the task becomes significantly harder.
The Reasoning Process: From Observation to Action
What makes this message particularly interesting is the reasoning arc it reveals. The assistant has been through several phases of understanding:
Phase 1: Naive optimism. Earlier in the conversation, the assistant believed that enabling IOMMU passthrough (iommu=pt) and migrating the VM to the Q35 chipset with pcie=1 might improve P2P capability. This was based on a reasonable assumption: that the right virtual PCIe configuration would allow VFIO to expose P2P DMA between passed-through devices.
Phase 2: Disillusionment. After testing, the assistant discovered that the bandwidth numbers were virtually identical before and after the changes—~33 GB/s for 4MB transfers and a ~13µs latency floor for small transfers. The assistant correctly diagnosed this as the inherent cost of GPU→host memory→GPU staged copies through the QEMU/KVM virtual device model. The honest assessment was damning: "P2P (direct GPU-to-GPU DMA) cannot be enabled in this VM setup."
Phase 3: Strategic pivot. Despite concluding that P2P is impossible, the assistant now proposes a different goal: not true P2P, but a virtual topology that would give NCCL better information for optimizing communication patterns. The key insight is that even without hardware P2P, NCCL can make smarter scheduling decisions if it knows which GPUs share a NUMA node. Getting NODE instead of PHB for intra-socket pairs, and SYS instead of PHB for cross-socket pairs, would allow NCCL to prefer local transfers and minimize cross-socket traffic.
The Proposed Solution: Virtual PCIe Switches via Custom QEMU Args
The second half of the message proposes a concrete—and invasive—next step:
Also, to build the virtual PCIe switch topology properly, I need to understand — are you comfortable with me writing custom QEMU args on the host to create virtual PCIe expander buses and switches (similar to the NVIDIA guide)? This would involve stopping the VM, changing the config withqm set 128 -args '...', and restarting. It's the only way to getNODE/SYSdistinction in the VM.
This proposal draws on NVIDIA's own documentation for configuring virtual machines for AI inference, which describes using pcie-switch-upstream-port and pcie-switch-downstream-port QEMU devices to create virtual PCIe switches. The idea is to group GPUs behind virtual switches that mirror the physical NUMA topology, so the NVIDIA driver reports NODE or PIX instead of PHB.
The assistant is careful to set expectations: this approach is "the only way to get NODE/SYS distinction in the VM." It's an admission that the earlier, simpler approaches (Q35 chipset, pcie=1, iommu=pt) were insufficient, and that only a deeply customized QEMU configuration—bypassing Proxmox's standard hostpci syntax—can achieve the desired topology.
Assumptions and Potential Pitfalls
The message rests on several assumptions that deserve scrutiny:
Assumption 1: The resource mapping file will reveal a clean NUMA split. The assistant assumes that the pro6000.cfg mapping file will show a one-to-one correspondence between hostpci indices and physical PCI addresses that aligns with the NUMA topology. If the mapping is scrambled—say, hostpci0 maps to a NUMA 1 GPU and hostpci1 to a NUMA 0 GPU—then the two groups of root ports wouldn't correspond to the two NUMA nodes, and the virtual switch topology would need to be more complex.
Assumption 2: Virtual PCIe switches will actually improve performance. This is the most significant assumption, and one that the assistant itself questioned earlier in the conversation. In <msg id=369>, the assistant stated: "Creating virtual PCIe switches would change what nvidia-smi topo reports (from NS to PIX), but the actual data path wouldn't change — transfers would still go GPU→host mem→GPU with the same ~13µs latency." Yet now the assistant is proposing exactly this approach. The shift in reasoning is subtle but important: the goal is no longer to change the data path but to change NCCL's scheduling. NCCL uses topology information to choose communication algorithms (ring vs. tree, chunk sizes, pipeline depth). A topology that distinguishes intra-socket from cross-socket links could allow NCCL to make better choices, even if the underlying hardware path is unchanged.
Assumption 3: Custom QEMU args are compatible with Proxmox's management layer. Proxmox uses qm commands and configuration files to manage VMs. Adding raw -args bypasses the standard configuration path and could cause issues with future VM management operations (migration, backup, template creation). The assistant acknowledges this by asking for explicit user consent.
The Input Knowledge Required
To fully understand this message, the reader needs knowledge of:
- PCIe topology concepts: Root complexes, root ports, PCIe switches, bus/device/function notation, and how
nvidia-smi topoclassifies connections (SYS, NODE, PHB, PIX, NV#). - NUMA architecture: How multi-socket systems divide memory and PCIe devices into NUMA nodes, and why GPU-to-GPU communication within a NUMA node is faster than across nodes.
- VFIO and IOMMU: How VFIO mediates device access in KVM, how IOMMU groups isolate devices for security, and why P2P DMA between devices in different IOMMU groups is restricted.
- Proxmox VE configuration: The
hostpcisyntax, resource mapping files (/etc/pve/mapping/pci/*.cfg), and theqmcommand-line interface. - QEMU device model: How QEMU emulates PCIe root ports, switches, and bridges, and how custom
-devicearguments can construct arbitrary virtual topologies. - NCCL communication patterns: How NCCL uses topology information to select communication algorithms and optimize all-reduce performance.
The Output Knowledge Created
This message produces several important pieces of knowledge:
- A complete map of the VM's virtual PCIe topology, showing which QEMU root port corresponds to which GPU bus and which
hostpciindex. - A testable hypothesis about NUMA mapping: that
hostpci0-3correspond to NUMA 0 andhostpci4-7to NUMA 1, pending verification via the mapping file. - A concrete action plan: read the mapping file, verify the NUMA alignment, then construct custom QEMU args to build virtual PCIe switches.
- An explicit request for user consent, acknowledging the invasive nature of the proposed change.
The Deeper Narrative: Virtualization's Hard Limits
Beneath the technical details, this message tells a story about the fundamental tension between virtualization and high-performance GPU computing. The assistant has spent hours—across multiple conversation segments—trying to solve a problem that may ultimately be unsolvable within the constraints of a virtualized environment. Each layer peeled back reveals another constraint: first the chipset, then the IOMMU, then ACS, then the hardware topology itself.
The message at <msg id=375> represents a moment of clarity and a strategic pivot. The assistant has accepted that true P2P is impossible and is now pursuing the next-best thing: a topology that gives NCCL better information, even if the underlying data path remains unchanged. It's a pragmatic compromise between the ideal (direct GPU-to-GPU DMA) and the achievable (better-informed NCCL scheduling).
Whether this compromise will yield meaningful performance improvements remains to be seen. The 13µs latency floor for small transfers—the fundamental bottleneck imposed by the GPU→host→GPU data path—may prove resistant to topology tricks. But in the world of ML inference optimization, even a 10-20% improvement in all-reduce throughput can translate to significant end-to-end latency reductions for large models.
Conclusion
The assistant's message at <msg id=375> is a masterclass in systematic debugging under constraints. It demonstrates how to read a complex PCIe topology, formulate testable hypotheses, and propose targeted interventions while honestly acknowledging their limitations. The proposed virtual PCIe switch approach may or may not improve performance, but the reasoning process itself—moving from naive optimism through disillusionment to a nuanced, pragmatic strategy—is a valuable model for anyone debugging multi-GPU performance in virtualized environments.
The next step, reading the Proxmox mapping file, will determine whether the topology puzzle can be solved with a clean mapping or whether further complexity awaits. Either way, the message captures a critical inflection point in the conversation: the moment when the assistant stops trying to enable P2P and starts trying to simulate it.