1 points par GN⁺ 5 시간 전 | 1 commentaires | Partager sur WhatsApp
  • nbd-vram est un petit démon qui permet d’utiliser la VRAM inutilisée d’un GPU NVIDIA sous Linux comme espace de swap à haute priorité
  • Sur les ordinateurs portables à graphisme hybride, où la mémoire est soudée donc difficile à mettre à niveau et où le GPU intégré AMD/ATI assure l’affichage, il exploite la VRAM NVIDIA inutilisée pour atténuer la pression mémoire
  • L’environnement de test est un AMD/ATI + RTX 3070 Laptop, avec 16 Go de RAM, 8 Go de VRAM, le pilote NVIDIA 580.159.03, le kernel 6.17 et Pop!_OS ; 7 Go de VRAM ont été alloués au swap, pour constituer environ 46 Go de mémoire adressable en combinant zram et le swap SSD
  • L’ordre de fonctionnement est le suivant : la RAM se remplit d’abord, puis la VRAM absorbe via PCIe les pages qui débordent, ensuite zram compresse côté CPU, et enfin le SSD est utilisé en dernier recours
  • Le démon alloue la VRAM via l’API du pilote CUDA, fournit un périphérique bloc via le protocole NBD (Network Block Device) sur un socket Unix, et le pilote nbd intégré au kernel l’expose comme /dev/nbdX pour l’utiliser comme un périphérique de swap classique
  • Le chemin des données est : kernel swap subsystem → /dev/nbdX → nbd kernel driver → Unix socket → nbd-vram daemon → cuMemcpyHtoD/DtoH → VRAM du GPU
  • Aucun module kernel séparé ni symbole kernel NVIDIA n’est nécessaire, ce qui permet de conserver le fonctionnement après une mise à jour du kernel ou du pilote sans recompilation
  • Avec l’approche via l’API NVIDIA P2P, nvidia_p2p_get_pages_persistent renvoie EINVAL sur les GPU GeForce grand public, et l’approche d’accès direct BAR1 via ioremap_wc échoue aussi, car les lectures hors de la zone d’environ 16 MiB du framebuffer d’affichage renvoient 0
  • Le chemin de copie CUDA via cuMemcpyHtoD et cuMemcpyDtoH fonctionne sur les GPU CUDA sans privilèges particuliers, ce qui permet à l’accès NBD de contourner les limitations de P2P et de BAR1
  • Les prérequis sont un GPU NVIDIA compatible CUDA, un pilote NVIDIA avec libcuda.so.1, le module nbd du kernel Linux 3.0+, nbd-client, gcc et make ; le toolkit CUDA n’est pas nécessaire
  • Après l’installation, le service systemd vram-swap-nbd se lance automatiquement au démarrage, et VRAM_SETUP_SIZE_MB ainsi que VRAM_SWAP_PRIORITY dans /etc/systemd/system/vram-swap-nbd.service permettent d’ajuster la limite de VRAM utilisée et la priorité du swap
  • Le démon essaie d’abord la taille de VRAM demandée puis, si la mémoire GPU est insuffisante, réduit l’allocation par paliers de 512 MiB ; VRAM_SETUP_SIZE_MB agit donc comme une limite maximale et non comme une taille obligatoire
  • Si la gestion tenant compte de l’alimentation est activée, le service s’arrête automatiquement lors du débranchement du secteur ou sous un seuil critique de batterie, puis redémarre quand l’alimentation revient ; un systemctl stop manuel n’est pas écrasé
  • Dans les benchmarks sur RTX 3070 Laptop, le NVMe est plus rapide en débit séquentiel et en I/O aléatoires soutenues, mais en latence de lecture 4K à 1 request/sec, la VRAM atteint une moyenne de 335us, soit 27 fois plus rapide que les 9.05ms du NVMe
  • Le projet est proposé sous licence MIT, et le dépôt fournit aussi test-nbd.sh pour les smoke tests, test-fill.sh pour la vérification d’une partition complète, ainsi que des scripts de benchmark pour le débit, les IOPS et la latence

1 commentaires

 
GN⁺ 5 시간 전
Commentaires sur Hacker News
  • Si on le traite via CUDA comme un stockage de fichiers ou un montage, la surcharge est importante, donc avec le BAR, on pourrait sans doute nettement améliorer le débit et les IOPS

  • Si l’idée est que c’est destiné aux ordinateurs portables avec mémoire soudée et sans possibilité d’upgrade, ça répond à la question immédiate de savoir pourquoi on ferait du swap depuis de la RAM chère vers une RAM encore plus chère
    L’usage semble limité, mais utiliser 8 Go de VRAM inutilisés lorsqu’on commence à swapper sur SSD est une bonne idée quand on en a besoin

    • Une autre raison, c’est qu’on peut avoir de la VRAM sans l’utiliser en permanence
      Par exemple, si on a acheté un GPU pour jouer, quand on ne joue pas, on n’a pas besoin de 16 Go de VRAM pour le rendu du bureau, donc pourquoi ne pas les utiliser à autre chose ?
      Cela dit, il faut supposer que le système puisse libérer la VRAM utilisée comme swap au moment de lancer un jeu, et je me demande si c’est réellement possible
    • Peut-on réellement utiliser la VRAM comme de la RAM normale ? Par exemple, si on a une barrette de 16 Go de RAM et 16 Go de VRAM sur le GPU, peut-on faire en sorte que le système affiche 32 Go de RAM, et quel en serait l’impact ?
    • Autrefois, on appelait ça un RAM disk, et ça rendait l’Atari ST incroyablement rapide
      Sur les Amstrad PCW, très répandus au Royaume-Uni du milieu des années 80 au milieu des années 90, on pouvait utiliser jusqu’à 512 ko de RAM, dont une part assez importante pouvait devenir un RAM disk
      Même la compilation avec Turbo Pascal devenait très rapide :-)
  • L’idée est bonne, mais il semble y avoir quelque chose de très mal fichu ici
    On parle d’environ 1,3 Go/s de débit séquentiel sur un RTX 3070 Laptop, alors que cette puce RTX 3070 est en PCIe 4.0 x16 et devrait atteindre 64 Go/s, et que ses 8 Go de GDDR6 montent eux-mêmes à 448 Go/s
    Swapper sur un disque NVMe serait deux fois plus rapide, mais avec une latence plus élevée

    • Le PCIe 4.0 x16, c’est 32 Go/s par direction, et cette implémentation n’est pas du tout celle qu’on choisirait si on voulait de hautes performances
      En plus, le benchmark a été lancé avec ZRAM, qui compresse les pages avant de les écrire dans le swap. Je ne sais pas exactement quelle est la surcharge de performance, mais elle est probablement importante
      Déjà, on passe par un programme en espace utilisateur accroché au pilote nbd, connu pour être lent, et on utilise aussi un buffer de rebond en espace utilisateur avant le transfert vers le GPU. Si le noyau doit swapper une page, il doit d’abord la copier vers un buffer exposé à l’espace utilisateur, puis le programme utilisateur doit se réveiller de nouveau, lancer des opérations CUDA et recopier cette page vers la mémoire du périphérique
      nbd ne gère pas non plus très bien les profondeurs de file d’attente élevées ni la fusion des accès adjacents. Si le noyau émet beaucoup de swaps de pages de 4K sans fusion, même atteindre 4 Go/s demande au moins un million de changements de contexte noyau/espace utilisateur par seconde. Alors 64 Go/s, n’en parlons même pas. Et ça, c’est seulement la partie NBD, sans même compter la complexité du pilote NVIDIA
      Le PCIe peut déplacer beaucoup de données, mais pour approcher la bande passante totale, il faut utiliser un moteur DMA avec de longues listes de pages. Si on configure un transfert sur PCIe pour chaque page de 4K, on ne saturera jamais complètement le bus
      Le chemin de swap vers NVMe, lui, est extrêmement optimisé. Le swapper peut soumettre directement des listes de pages au pilote NVMe, et le contrôleur vient les récupérer par DMA directement depuis la RAM, sans aucune copie côté CPU ni changement de contexte
      En passant au pilote ublk, on pourrait peut-être éviter le buffer de rebond en espace utilisateur, et il serait aussi possible de configurer en parallèle des copies CUDA sur plusieurs files d’écriture, donc il y a sans doute de la marge d’amélioration
    • Swapper sur NVMe use aussi les cycles PE de la NAND, donc cela provoque de l’usure avec le temps
      La RAM ou la VRAM, elles, ne se dégradent pas à l’usage
  • J’ai une machine de développement avec 32 Go de RAM et 32 Go de VRAM qui restent la plupart du temps inutilisés quand je ne fais pas tourner de modèles d’IA, donc l’idée n’est pas si mauvaise

    • Ça donne un côté pcmasterrace, avec un énorme haut du corps et des jambes toutes maigres
  • Je me demande comment est gérée la contre-pression. Que se passe-t-il si une demande d’allocation de VRAM arrive pendant que la VRAM sert d’espace de swap ?
    Sous X11, les buffers sont préalloués, donc ce n’est pas trop grave, mais sous Wayland les allocations sont bien plus dynamiques, donc si la VRAM vient à manquer, tout le bureau peut facilement mourir
    Ça m’est arrivé plusieurs fois en basculant la machine avec Hyprland+llama-server+KVM, faute d’avoir pu libérer la VRAM

  • Créer un périphérique de swap au niveau utilisateur fait partie depuis longtemps des problèmes classiques réputés insolubles
    Si le démon doit swap-in une page, mais qu’il doit d’abord swap-in ses propres pages pour pouvoir le faire, qu’est-ce qu’on fait ?
    Il y avait au moins ce genre de discussions comme raison pour laquelle les microkernels ne pourraient jamais fonctionner. Je ne vois pas bien quelle est la solution ici

    • Il suffit que le démon soit assez intelligent pour savoir quelles sont ses propres pages et empêcher qu’elles soient swap-out
      Le noyau Linux empêche déjà que ses propres pages de texte soient swap-out, donc la solution existe déjà, et je ne vois pas pourquoi elle ne s’appliquerait pas aussi à la conception des microkernels
    • Le principe général, c’est que ce qui participe à la pagination ne doit pas lui-même être paginé
      Si on verrouille en mémoire toute la mémoire de ce démon, le problème devient trivial à résoudre
  • Je me souviens avoir fait quelque chose de similaire autrefois avec le pilote MTD/phram de Linux : https://wiki.archlinux.org/title/Swap_on_video_RAM
    Je ne sais pas si c’est encore pertinent aujourd’hui, parce que je ne sais pas comment cela interagit avec DRM ni comment on gère la réservation d’une partie de la VRAM. La méthode qui consiste à proposer une limitation via xorg.conf est probablement assez dépassée maintenant
    Cette page mentionne aussi un système de fichiers FUSE implémenté au-dessus d’OpenCL : https://github.com/Overv/vramfs
    Ça pourrait être plus compatible

    • À l’époque, j’utilisais mtd pour mapper 8 Mo de mémoire vidéo, et ça aidait à construire ces... pilotes X11
      Ça rappelle des souvenirs
  • J’ai déjà vu quelque chose de similaire sous Windows il y a quelques années
    C’était un pilote expérimental de preuve de concept permettant de créer un RAM drive à partir de la VRAM d’une carte NVIDIA, et les accès séquentiels étaient rapides comme prévu, mais les accès aléatoires laissaient encore beaucoup de marge d’amélioration
    GpuRamDrive crée un lecteur virtuel soutenu par la RAM du GPU : https://github.com/prsyahmi/GpuRamDrive
    Fork avec support AMD : https://github.com/brzz/GpuRamDrive/

  • C’est similaire, mais en utilisant l’API OpenCL, donc ça fonctionne aussi sur AMD
    Cela dit, les pilotes AMD sont assez bogués, donc il faut définir ce qu’on entend par « fonctionne » : https://libguestfs.org/nbdkit-vram-plugin.1.html

  • Je ne comprends pas pourquoi, sur un Mac Apple Silicon avec 32 Go de RAM, il utilise ou crée même un fichier de swap alors qu’il reste encore 20 Go inutilisés / « free »
    Pourquoi n’existe-t-il pas une commande simple comme swapoff -a sous Linux pour désactiver complètement le fichier de swap ?
    Si le but n’est pas de réduire volontairement la durée de vie du SSD, ça paraît assez absurde
    Ce serait bien d’avoir un réglage système dans l’interface graphique pour désactiver le fichier de swap, et Apple pourrait aussi enfin abandonner les « étapes » actuelles de son agencement des réglages système. Comparé aux panneaux de préférences de plusieurs décennies, ça ressemble encore à une salade de mots
    #Apple #Feedback #swapfile

    • Le principe d’un système de pagination, c’est que la mémoire principale est le cache du stockage secondaire
      Même la notion de « mémoire disponible » est idéalement plus proche de « mémoire qu’on peut récupérer rapidement pour un autre usage »
      À certains moments, il vaut mieux laisser des contenus de fichiers en cache occuper cette place plutôt que de conserver de la mémoire anonyme en mémoire principale