Live 18/11 · Cohorte 318 nov à 19h00 MSK — atelier pratique gratuit sur les agents IA · La Cohorte 3 démarre le 23/11Atelier 18/11 →Cohorte 3 (23/11)

Zero-Host-Copy : faire tourner YOLOv8m à 165–215 FPS en sortant le CPU de la boucle critique

Quand les modèles INT8 s'exécutent en quelques millisecondes, ce n'est plus le calcul qui ralentit, mais tout ce qui l'entoure : copies d'images via PCIe et synchronisation cachée due à cudaMalloc. Les auteurs de l'analyse ont construit un pipeline bare-metal en C++/CUDA, sans DeepStream, où les images restent en mémoire GPU du décodeur à l'encodeur. YOLOv8m en 1024x1024 et INT8 atteint 165–215 FPS sur une RTX 3060 Ti et environ 38 FPS sur un Jetson Orin Nano Super.

Traité par IA depuis Хабр: Машинное обучение ; édité par Hamidun News
Zero-Host-Copy : faire tourner YOLOv8m à 165–215 FPS en sortant le CPU de la boucle critique
Source : Хабр: Машинное обучение. Collage: Hamidun News.
Écouter l'article
Fiche synthèse et chiffres clés
ParamètreDonnées
Source primaireХабр: Машинное обучение ↗
Rédacteur en chef
Chiffre clé #1Les images restent en mémoire GPU du décodage à l'encodage
La mémoire est allouée à l'avanceni cudaMalloc ni new en phase critique
Trois phasesinitialisation, préchauffage, fonctionnement actif

Vous avez optimisé votre modèle, vous l'avez quantifié en INT8, et l'inférence ne prend plus que quelques millisecondes. Pourtant, les FPS restent loin de ce que l'on attendait. L'histoire est classique : le goulot d'étranglement n'est pas l'unité de calcul, mais tout ce qui l'entoure. Une analyse publiée sur Habr montre comment y remédier concrètement.

Où les images se perdent réellement

Sur une carte graphique dédiée, chaque image haute résolution envoyée vers la mémoire vive puis renvoyée paie un tribut au bus PCIe. Si l'on fait en plus des allers-retours avec des résultats intermédiaires, par exemple les bounding boxes de la détection, la bande passante chute nettement. Plus le modèle est rapide, plus ce coût saute aux yeux : le calcul prend 2 ms, et la copie dure plus longtemps que le calcul lui-même.

L'idée de Zero-Host-Copy est simple : depuis la lecture sur disque et le décodage jusqu'à l'encodage final et l'écriture, les données restent en mémoire GPU. Seule la carte graphique les traite, et les copies GPU → CPU et inversement sont réduites au minimum. Le principe voisin du Zero-Copy consiste à transmettre entre les étapes du pipeline un pointeur vers le bloc de données, et non le bloc lui-même.

Le tueur silencieux : cudaMalloc

Le second problème est moins évident. Un appel à cudaMalloc entraîne une synchronisation implicite : le CPU doit attendre le GPU, et le pipeline asynchrone cesse de l'être. Un seul appel de ce type dans la boucle de traitement des images peut provoquer une chute de performances que le profileur présentera sous forme de pauses mystérieuses.

La solution est un cycle de vie en trois phases :

  • Initialisation. L'application alloue à l'avance des pools de mémoire, des tampons et des files d'attente avec une profondeur initiale.
  • Préchauffage. La file de traitement complète est lancée. Si des tampons supplémentaires sont nécessaires, le système les alloue à ce moment-là.
  • Fonctionnement actif. Après les premières images, toute allocation dynamique est interdite : pas de cudaMalloc ni de new, uniquement la réutilisation des blocs déjà alloués.

C'est en somme une technique bien connue des moteurs de jeu et du traitement audio : on fait tout le travail lourd avant le démarrage, et dans la boucle critique on se contente de réutiliser.

Les résultats

L'auteur a implémenté un pipeline sans DeepStream, en C++/CUDA pur. YOLOv8m en résolution 1024x1024 et INT8 affiche environ 165–215 FPS sur une RTX 3060 Ti et près de 38 FPS sur un Jetson Orin Nano Super. Pour une plateforme embarquée, c'est un très bon résultat avec une telle taille d'entrée.

Limites et conclusion

Le prix de cette approche est la complexité. Un pipeline bare-metal exige une gestion manuelle des pools, de la synchronisation des flux et du cycle de vie des tampons. Une erreur de dimensionnement d'un pool provoquera un plantage ou une dégradation silencieuse en phase critique. La maintenance coûte plus cher qu'une solution fondée sur DeepStream ou un framework prêt à l'emploi. De plus, les chiffres ont été obtenus sur un modèle et un matériel précis, et l'article, d'après son annonce, ne compare pas cette approche aux piles existantes dans les mêmes conditions : il faut donc vérifier le gain sur vos propres données.

Conclusions pratiques pour ceux qui font de l'analyse vidéo ou travaillent avec des appareils edge :

  • Avant d'optimiser davantage le modèle, mesurez le temps consacré aux copies et aux allocations.
  • Repérez dans la boucle critique tous les cudaMalloc, new et synchronisations implicites, et déplacez-les vers l'initialisation.
  • Concevez le pipeline pour que l'image ne quitte jamais le GPU : décodage matériel, prétraitement, inférence, post-traitement, encodage.
  • Prévoyez une phase de préchauffage et vérifiez qu'aucune allocation n'a lieu après elle.

Quand le modèle est déjà rapide, le gain se trouve dans la rigueur d'ingénierie qui l'entoure. Pour le temps réel sur des flux vidéo, c'est souvent le moyen le moins coûteux d'obtenir un gain de FPS multiplié.

Dossier

Questions clés sur cet article

Que sait-on sur Où les images se perdent réellement ?

Sur une carte graphique dédiée, chaque image haute résolution envoyée vers la mémoire vive puis renvoyée paie un tribut au bus PCIe. Si l'on fait en plus des allers-retours avec des résultats intermédiaires, par exemple les bounding boxes de la détection, la bande passante chute nettement. Plus le modèle est rapide, plus ce coût saute aux yeux : le calcul prend 2 ms, et la copie dure plus longtemps que le calcul lui-même.

Que sait-on sur Le tueur silencieux : cudaMalloc ?

Le second problème est moins évident. Un appel à cudaMalloc entraîne une synchronisation implicite : le CPU doit attendre le GPU, et le pipeline asynchrone cesse de l'être. Un seul appel de ce type dans la boucle de traitement des images peut provoquer une chute de performances que le profileur présentera sous forme de pauses mystérieuses. La solution est un cycle de vie en trois phases : Initialisation.

Que sait-on sur Les résultats ?

L'auteur a implémenté un pipeline sans DeepStream, en C++/CUDA pur. YOLOv8m en résolution 1024x1024 et INT8 affiche environ 165–215 FPS sur une RTX 3060 Ti et près de 38 FPS sur un Jetson Orin Nano Super. Pour une plateforme embarquée, c'est un très bon résultat avec une telle taille d'entrée.

ZK
Zhemal Khamidun — CPO d'Alpina Digital, product manager d'AlpinaGPT. Conçoit des produits IA depuis 2019. Hamidun News est un projet personnel devenu un agrégateur en production avec plus de 6 000 lecteurs.
✦ Unified AI Workspace · Nomad

Test Frontier LLMs & Autonomous Agents in One Workspace

Run Claude Opus 5.5, GPT-6, Gemini 3.1, and DeepSeek side-by-side in Nomad AI (nomadnet.ai) — unified model routing, deep research, and multimodal workflows under one subscription.

Try Nomad AI →Launch Nomad Agent
Qu'en pensez-vous ?
Chargement des commentaires…