Contexte matériel et logique

Le serveur utilise un commutateur PCIe Broadcom PEX88096 installé dans le seul slot x16 de la carte mère. Quatre cartes AMD Radeon AI PRO R9700 (32 Go chacune) et deux RTX 3090 sont connectées via un répartiteur PCIe. Le commutateur attribue huit voies à chaque carte et permet le transfert direct de données (peer‑to‑peer, P2P) sans passer par le processeur, à condition que chaque GPU possède une BAR redimensionnable (Resizable BAR) de 32 Go.

Une BAR (Base Address Register) représente la portion d’espace d’adressage physique du CPU qui mappe la mémoire du GPU. Par défaut, le BIOS ne réserve que 256 Mo ; l’option Resizable BAR étend ce registre à la capacité maximale du GPU, ici 32 Go, ce qui est indispensable pour activer le P2P de ROCm.

Bug de dimensionnement du pont sous Linux 7.0

Linux 7.0.6 calcule la fenêtre mémoire du pont en additionnant simplement la taille ou l’alignement de chaque enfant, via la fonction pbus_size_mem() du fichier drivers/pci/setup-bus.c :

r_size = resource_size(r);
size += max(r_size, align);

Lorsque chaque R9700 possède une BAR de 32 Go + 2 Mo (doorbell) avec une alignement de 32 Go, le total devient 128,6 Go pour le commutateur. Le calcul ne laisse aucun espace entre les fenêtres, ce qui élimine le « gap » d’environ 32 Go entre la doorbell d’une carte et le début de la suivante. Le résultat : seules deux des quatre cartes obtiennent leur fenêtre, le reste reste non assigné, d’où le message d’erreur pci 0000:1b:00.0: bridge window [mem size 0x800200000 64bit pref]: can't assign; no space.

Correctif et module d’ajustement

Ilpo Järvinen a proposé une série de 14 correctifs (v5) qui modifient l’algorithme de placement des ressources, mais ils ne sont pas encore intégrés au noyau. En attendant, l’auteur a publié le module out‑of‑tree gpu-rebar-layout, chargé depuis l’initramfs avant le démarrage des pilotes GPU.

Le module exécute les étapes suivantes :

  • Écriture du registre de taille BAR pour chaque GPU afin de forcer 32 Go.
  • Suppression du port racine du commutateur puis rescannage du bus PCI.
  • Élévation de l’alignement de chaque BAR pré‑fetchable 64 bits à la taille maximale rencontrée sur le segment, créant des fenêtres de 64 Go pour les R9700 et de 512 Mo pour les RTX 3090.

Après redémarrage, les quatre R9700 affichent des adresses de 160 GB, 224 GB, 288 GB et 352 GB, tandis que les RTX 3090 se placent immédiatement après. Le pilote amdgpu confirme la prise en compte complète de la mémoire : amdgpu 0000:14:00.0: [drm] Detected VRAM RAM=32624M, BAR=32768M.

Performances et recommandations

Avec l’option pci=disable_acs_redir= activée sur les ports du commutateur, le P2P entre les R9700 atteint 14,0 GB/s par lien, soit la bande passante théorique d’un lien gen4 x8. Un anneau de copie simultané entre les quatre cartes génère 54,7 GB/s.

En cas d’échec d’allocation BAR, les étapes conseillées sont :

  • Vérifier les rapports « can't assign » sur la liste de diffusion linux‑pci.
  • Appliquer le redimensionnement et le rescannage depuis l’initramfs.
  • Éviter de rescanner un GPU déjà initialisé, ce qui peut bloquer le système.

Ces mesures permettent de contourner la régression du noyau et d’exploiter pleinement la capacité de 32 Go de chaque GPU derrière le commutateur PCIe.