Comment gérer la mémoire CUDA?

quand j'exécute mon programme CUDA qui n'alloue qu'une petite quantité de mémoire globale (moins de 20 M), j'ai une erreur "out of memory". (D'après les messages d'autres personnes, je pense que le problème est lié à la fragmentation de la mémoire) j'essaie de comprendre ce problème, et je me rends compte que j'ai quelques questions liées à la gestion de la mémoire CUDA.

  1. Existe-t-il un concept de mémoire virtuelle dans CUDA?

  2. si un seul noyau est autorisé à tourner sur CUDA simultanément, après sa résiliation, seront tous de la mémoire utilisés ou destinés libéré? Si non, quand ces souvenirs ont été libérés?

  3. si plus d'un noyau est autorisé à tourner sur CUDA, comment peuvent-ils s'assurer que la mémoire qu'ils utilisent ne se chevauche pas?

quelqu'un Peut-il m'aider à répondre à ces questions? Merci

Edit 1: système d'exploitation: x86_64 GNU/Linux CUDA version: 4.0 Dispositif: Geforce 200, il est l'un des GPUS attachés à la machine, et je ne pense pas que ce soit un dispositif d'affichage.

Edit 2: voici ce que j'ai obtenu après avoir fait quelques recherches. Hésitez pas à me corriger.

  1. CUDA va créer un contexte pour chaque thread hôte. Ce contexte conservera des informations telles que quelle partie de mémoire (mémoire pré-attribuée ou mémoire dynamiquement attribuée) a été réservée pour cette application de sorte que l'autre application ne peut pas y écrire. Quand cette application se termine (pas le noyau) , cette partie de la mémoire sera libérée.

  2. la mémoire CUDA est maintenue par une liste de liens. Quand une application a besoin d'allouer de la mémoire, elle va passer par cette liste de liens pour voir s'il y a un morceau de mémoire continue disponible pour l'allocation. Si elle ne parvient pas à trouver un tel morceau, une erreur "out of memory" sera signalée aux utilisateurs même si la taille totale de mémoire disponible est supérieure à la mémoire demandée. Et c'est le problème de la mémoire fragmentation.

  3. cuMemGetInfo vous indiquera combien de mémoire est libre, mais pas nécessairement combien de mémoire vous pouvez allouer dans une allocation maximale en raison de la fragmentation de la mémoire.

  4. sur la plateforme Vista (WDDM), la virtualisation de la mémoire GPU est possible. C'est-à-dire que plusieurs applications peuvent affecter la quasi-totalité de la mémoire GPU et WDDM va gérer le retour des données d'échange à la mémoire principale.

nouvelles questions: 1. Si la mémoire réservés dans le contexte sera entièrement libéré après que la demande a été mis un terme à la fragmentation de la mémoire ne devrait pas exister. Il doit y avoir un type de données dans la mémoire. 2. Y a-t-il un moyen de restructurer la mémoire GPU ?

24
demandé sur talonmies 2011-12-31 02:42:13

2 réponses

la mémoire de l'appareil disponible pour votre code à l'exécution est essentiellement calculée comme

Free memory =   total memory 
              - display driver reservations 
              - CUDA driver reservations
              - CUDA context static allocations (local memory, constant memory, device code)
              - CUDA context runtime heap (in kernel allocations, recursive call stack, printf buffer, only on Fermi and newer GPUs)
              - CUDA context user allocations (global memory, textures)

si vous obtenez un message indiquant que la mémoire, alors il est probable que l'un ou plusieurs des trois premiers éléments consomme plus de la mémoire GPU avant de votre code d'utilisateur tente d'obtenir la mémoire du GPU. Si, comme vous l'avez indiqué, vous ne fonctionnez pas sur un GPU d'affichage, alors les allocations statiques de contexte sont la source la plus probable de votre problème. CUDA travaille en pré-attribuant tous les mémoire un contexte nécessite au moment où le contexte est établi sur le périphérique. Il y a beaucoup de choses qui sont allouées pour soutenir un contexte, mais le plus grand consommateur dans un contexte est la mémoire locale. Le moteur d'exécution réserver la quantité maximale de mémoire locale que tout noyau dans un contexte consommera pour le nombre maximum de threads que chaque multiprocesseur peut exécuter simultanément, pour chaque multiprocesseur sur le périphérique. Cela peut entrer dans des centaines de Mo de mémoire si un la mémoire locale lourde noyau est chargé sur un appareil avec beaucoup de multiprocesseurs.

la meilleure façon de voir ce qui pourrait se passer est d'écrire un programme hôte sans code de périphérique qui établit un contexte et appelle cudaMemGetInfo. Cela vous montrera combien de mémoire l'appareil a avec le contexte minimal au-dessus de lui. Puis lancez votre code problématique, en ajoutant le même cudaMemGetInfo appel avant le premier cudaMalloc appel qui vous donnera la quantité de mémoire de votre contexte. Qui pourrait laissez-vous obtenez une poignée de où la mémoire s'en va. Il est très peu probable que la fragmentation soit le problème si vous obtenez l'échec sur le premier cudaMalloc appel.

25
répondu talonmies 2017-12-09 09:50:42
  1. la mémoire GPU off-chip est séparée en mémoire globale, locale et constante. Ces trois types de mémoire sont un concept de mémoire virtuelle. La mémoire globale est libre pour tous les threads, la mémoire locale est juste pour un thread seulement (principalement utilisé pour le débordement de registre) et la mémoire constante est mise en cache de la mémoire globale (accessible en écriture seulement à partir du code hôte). Consultez la Section 5.3.2 du guide de programmation de CUDA C.

  2. EDIT: removed

  3. Mémoire allouée à l'aide de cudaMalloc ne se chevauche jamais. Pour la mémoire qu'un noyau affecte pendant l'exécution, il devrait y avoir suffisamment de mémoire disponible. Si vous n'avez plus de mémoire et que vous essayez de lancer un noyau (seulement une supposition de ma part), vous devriez recevoir le message d'erreur "Erreur inconnue". Le pilote qui n'était pas capable de démarrer et/ou exécute le noyau.

4
répondu Michael Haidl 2011-12-31 10:14:37