Detectron: Manque de mémoire sur une carte de 4 Go

Créé le 24 janv. 2018  ·  24Commentaires  ·  Source: facebookresearch/Detectron

J'essaie d'exécuter Faster-RCNN sur une Nvidia GTX 1050Ti, mais je manque de mémoire. Nvidia-smi dit qu'environ 170 Mo sont déjà utilisés, mais Faster-RCNN utilise-t-il vraiment 3,8 Go de VRAM pour traiter une image ?

J'ai également essayé Mask-RCNN (le modèle du didacticiel de démarrage) et j'ai obtenu environ 4 images (5 si je ferme mon navigateur) avant qu'il ne plante.

Est-ce un bug ou faut-il vraiment plus de 4 Go de mémoire ?

INFO infer_simple.py: 111: Processing demo/18124840932_e42b3e377c_k.jpg -> /home/px046/prog/Detectron/output/18124840932_e42b3e377c_k.jpg.pdf
terminate called after throwing an instance of 'caffe2::EnforceNotMet'
  what():  [enforce fail at blob.h:94] IsType<T>(). wrong type for the Blob instance. Blob contains nullptr (uninitialized) while caller expects caffe2::Tensor<caffe2::CUDAContext> .
Offending Blob name: gpu_0/conv_rpn_w.
Error from operator: 
input: "gpu_0/res4_5_sum" input: "gpu_0/conv_rpn_w" input: "gpu_0/conv_rpn_b" output: "gpu_0/conv_rpn" name: "" type: "Conv" arg { name: "kernel" i: 3 } arg { name: "exhaustive_search" i: 0 } arg { name: "pad" i: 1 } arg { name: "order" s: "NCHW" } arg { name: "stride" i: 1 } device_option { device_type: 1 cuda_gpu_id: 0 } engine: "CUDNN"
*** Aborted at 1516787658 (unix time) try "date -d @1516787658" if you are using GNU date ***
PC: @     0x7f08de455428 gsignal
*** SIGABRT (@0x3e800000932) received by PID 2354 (TID 0x7f087cda9700) from PID 2354; stack trace: ***
    @     0x7f08de4554b0 (unknown)
    @     0x7f08de455428 gsignal
    @     0x7f08de45702a abort
    @     0x7f08d187db39 __gnu_cxx::__verbose_terminate_handler()
    @     0x7f08d187c1fb __cxxabiv1::__terminate()
    @     0x7f08d187c234 std::terminate()
    @     0x7f08d1897c8a execute_native_thread_routine_compat
    @     0x7f08def016ba start_thread
    @     0x7f08de52741d clone
    @                0x0 (unknown)
Aborted (core dumped)

enhancement

Commentaire le plus utile

Une note supplémentaire : l'implémentation actuelle utilise des optimisations de mémoire pendant l'apprentissage, mais pas pendant l'inférence. Dans le cas de l'inférence, il est possible de réduire considérablement l'utilisation de la mémoire puisque les activations intermédiaires ne sont pas nécessaires une fois qu'elles sont consommées. Nous envisagerons d'ajouter une optimisation de la mémoire uniquement par inférence à l'avenir.

Tous les 24 commentaires

Bonjour @Omegastick , les besoins en mémoire de l'algorithme Faster R-CNN varient en fonction d'un certain nombre de facteurs, notamment l'architecture du réseau fédérateur et les échelles d'image de test utilisées.

Par exemple, vous pouvez exécuter Faster R-CNN avec la configuration ResNet-50 par défaut en utilisant :

python2 tools/infer_simple.py \
  --cfg configs/12_2017_baselines/e2e_faster_rcnn_R-50-FPN_2x.yaml \
  --output-dir /tmp/detectron-visualizations \ 
  --image-ext jpg \
  --wts https://s3-us-west-2.amazonaws.com/detectron/35857389/12_2017_baselines/e2e_faster_rcnn_R-50-FPN_2x.yaml.01_37_22.KSeq0b5q/output/train/coco_2014_train%3Acoco_2014_valminusminival/generalized_rcnn/model_final.pkl \
  demo

qui ne devrait pas nécessiter plus de 3 Go pour fonctionner sur les images de démonstration.

Une note supplémentaire : l'implémentation actuelle utilise des optimisations de mémoire pendant l'apprentissage, mais pas pendant l'inférence. Dans le cas de l'inférence, il est possible de réduire considérablement l'utilisation de la mémoire puisque les activations intermédiaires ne sont pas nécessaires une fois qu'elles sont consommées. Nous envisagerons d'ajouter une optimisation de la mémoire uniquement par inférence à l'avenir.

@Omegastick Testé sur ma machine, Faster RCNN-resnet 101 et Mask RCNN-resnet 101 utilisent environ 4 Go de mémoire GPU.

@ ir413 Merci, le modèle que vous avez lié fonctionne très bien (avec une utilisation de 2,5 Go de VRAM) sur ma machine.

Ce serait cool si l'inférence n'avait pas du tout besoin d'un GPU.

Comment puis-je exécuter le masque-rcnn avec un GPU à mémoire 2G ? Quelqu'un peut-il m'aider ?

Ce problème est-il dû à l'implémentation de Caffe 2 ou Detectron ? Quels fichiers dans Detectron dois-je regarder pour résoudre ce problème ?

@rbgirshick

Dans le cas de l'inférence, il est possible de réduire considérablement l'utilisation de la mémoire puisque les activations intermédiaires ne sont pas nécessaires une fois qu'elles sont consommées. Nous envisagerons d'ajouter une optimisation de la mémoire uniquement par inférence à l'avenir.

Y a-t-il déjà quelque chose d'implémenté dans PyTorch/Caffe2 ? Si oui où doit-on creuser ?

@gadcam Cela fait longtemps partie de ma liste de caffe2.python.memonger.release_blobs_when_used (https://github.com/pytorch/pytorch/blob/master/caffe2/python/memonger.py#L229) devrait implémenter la plupart de ce dont nous avons besoin. Cependant, il y a quelques problèmes non triviaux qui doivent être résolus :

  • Pour certains réseaux (par exemple Mask R-CNN) plusieurs réseaux sont utilisés au moment de l'inférence et donc toutes les activations ne peuvent pas être libérées en raisonnant sur un seul graphe (parce qu'elles peuvent être nécessaires par un autre graphe, par exemple, le mask head net).
  • Cette fonction nécessite l'utilisation d'un gestionnaire de mémoire cache, que nous n'avons pas testé, il pourrait donc y avoir des problèmes avec le simple fait de l'activer.

@rbgirshick Merci pour votre explication détaillée !

Donc, si je comprends bien, pour nous, release_blobs_when_used agit comme un convertisseur d'un Proto ordinaire vers un "mémoire optimisée".

Pour certains réseaux (par exemple Mask R-CNN) plusieurs réseaux sont utilisés au moment de l'inférence et donc toutes les activations ne peuvent pas être libérées en raisonnant sur un seul graphe (parce qu'elles peuvent être nécessaires par un autre graphe, par exemple, le mask head net).

En d'autres termes, nous devons remplir dont_free_blobs avec des blobs utilisés par la deuxième étape ?

Cette fonction nécessite l'utilisation d'un gestionnaire de mémoire cache, que nous n'avons pas testé, il pourrait donc y avoir des problèmes avec le simple fait de l'activer.

Donc, si nous voulons le tester, nous devons définir FLAGS_caffe2_cuda_memory_pool sur cub (ou thc ) mais pourrions-nous le faire en Python ?
L'une des très rares références que j'ai pu trouver est ici https://github.com/pytorch/pytorch/blob/6223bfdb1d3273a57b58b2a04c25c6114eaf3911/caffe2/core/context_gpu.cu#L190

@gadcam

Donc, si je comprends bien, pour nous, release_blobs_when_used agit comme un convertisseur d'un Proto ordinaire vers un "mémoire optimisée".

Oui c'est correct. Il analyse le graphe de calcul, détermine quand chaque blob ne sera plus utilisé, puis insère une opération de libération de mémoire.

En d'autres termes, nous devons remplir dont_free_blobs avec les blobs utilisés par la deuxième étape ?

Oui, avec la mise en garde que je ne suis pas sûr de savoir à quel point cette fonction est bien utilisée et/ou testée... à partir du code grapping, il semble qu'elle ne soit pas vraiment utilisée. Ainsi, je garderais à l'esprit que cela pourrait ne pas fonctionner comme prévu.

Donc, si nous voulons le tester, nous devons définir FLAGS_caffe2_cuda_memory_pool sur cub (ou thc) mais pourrions-nous le faire en Python ?

Oui. Je pense que le nouveau gestionnaire de mémoire thc est plus efficace. Nous devions l'utiliser au lieu de cub pour un cas d'utilisation récent (bien que différent).

@rbgirshick Vous avez raison, cela ressemble à un chemin risqué !

Oui. Je pense que le gestionnaire de mémoire thc nouvellement ajouté est plus efficace. Nous devions l'utiliser à la place de cub pour un cas d'utilisation récent (bien que différent).

Ce que je voulais dire, c'est savez-vous où je peux trouver de la documentation pour le faire ou avez-vous un exemple ? (Je suis vraiment désolé d'insister sur celui-ci, j'ai peut-être raté quelque chose mais je n'ai pu trouver aucune documentation à ce sujet)

@gadcam concernant la documentation, pas à ma connaissance. Désolé!

@asaadaldien Je suis vraiment désolé de vous ennuyer mais vous semblez être l'une des rares personnes à avoir conseillé de

ASSUREZ-VOUS que caffe2_cuda_memory_pool est défini

lorsque nous utilisons memonger ou data_parallel_model (pour référence, c'était ici ).
Avez-vous un indice sur la façon de s'assurer que nous avons un gestionnaire de mémoire cache activé ? (Utilisation de Caffe2 en Python)

@gadcam Vous pouvez activer l'allocateur mis en cache cub en passant cub au drapeau caffe2_cuda_memory_pool. par exemple :

workspace.GlobalInit([
'--caffe2_cuda_memory_pool=cub',
])

Cependant, cela n'est requis que lors de l'utilisation d'un memonger de mémoire dynamique.

@asaadaldien
Il m'aurait fallu beaucoup de temps pour comprendre comment faire car il n'y a pas de documentation sur GlobalInit .
Merci beaucoup pour votre aide! Alors maintenant, je suis en mesure de commencer quelques expériences!

J'ai une solution simple à ce problème.
Vous pouvez définir 'P2~P5' et 'rois' comme blobs de sortie, pas seulement le blob du milieu, alors il ne sera pas optimisé lors de l'utilisation de l'optimisation de la mémoire.

Ne semble pas fonctionner pour moi.
Le modèle que j'ai testé est e2e_keypoint_rcnn_R-50-FPN_s1x.yaml .
J'ai essayé de le tester par rapport à la partie model.net .

J'ai utilisé infer_simple.py pour les tests.

workspace.GlobalInit(['caffe2', '--caffe2_log_level=0', '--caffe2_cuda_memory_pool=thc']) 

et

dont_free_blobs = set(model.net.Proto().external_output)
expect_frees = set(i for op in model.net.Proto().op for i in op.input)
expect_frees -= dont_free_blobs

opti_net = release_blobs_when_used(model.net.Proto(), dont_free_blobs, selector_fun=None)
model.net.Proto().op.extend(copy.deepcopy(opti_net.op))

test_release_blobs_when_used(model.net.Proto(), expect_frees) 

test_release_blobs_when_used est inspiré de https://github.com/pytorch/pytorch/blob/bf58bb5e59fa64fb49d77467f3466c6bc0cc76c5/caffe2/python/memonger_test.py#L731

def test_release_blobs_when_used(with_frees, expect_frees):
    found_frees = set()
    for op in with_frees.op:
        if op.type == "Free":
            print("OP FREEE", op)
            assert(not op.input[0] in found_frees)  # no double frees
            found_frees.add(op.input[0])
        else:
            # Check a freed blob is not used anymore
            for inp in op.input:
                assert(not inp in found_frees)
            for outp in op.output:
                assert(not outp in found_frees)

    try:
        assert(expect_frees == found_frees)
    except:
        print("Found - Expect frees Nb=", len(found_frees - expect_frees), found_frees - expect_frees, "\n\n\n")
        print("Expect - Found frees Nb=", len(expect_frees - found_frees), expect_frees - found_frees, "\n\n\n")
       #assert(False)

Veuillez noter que dont_free_blobs n'est pas défini sur une valeur correcte !

Cette fonction m'indique qu'aucun blob inattendu ne sera libéré et qu'il en manque certains.
(ce qui est normal car dont_free_blobs n'est pas correct)
Je continue donc à exécuter le modèle.

Et... rien ne se passe. J'ai vérifié en utilisant la fonction save_graph : les ops gratuites sont bel et bien ici au bon endroit.

L'utilisation de la mémoire pour mes exemples d'entrées de cette ligne est de 1910 Mo +/- 5 Mo
https://github.com/facebookresearch/Detectron/blob/6c5835862888e784e861824e0ad6ac93dd01d8f5/detectron/core/test.py#L158

Mais quelque chose de vraiment surprenant se produit si je règle le gestionnaire de mémoire sur CUB

workspace.GlobalInit(['caffe2', '--caffe2_log_level=0', '--caffe2_cuda_memory_pool=cub']) 

L'utilisation de la RAM de la ligne RunNet est augmentée de quelque chose comme 3 Go !! (en utilisant le code normal ou le code personnalisé avec les blobs gratuits)

Je ne comprends pas ce qui se passe...

Comme décrit dans #507, je suis également confronté à une erreur de mémoire insuffisante lors du démarrage de l'inférence sur Jetson TX1.
La solution décrite dans ce fil, comme:
python2 tools/infer_simple.py \ --cfg configs/12_2017_baselines/e2e_faster_rcnn_R-50-FPN_2x.yaml \ --output-dir /tmp/detectron-visualizations \ --image-ext jpg \ --wts https://s3-us-west-2.amazonaws.com/detectron/35857389/12_2017_baselines/e2e_faster_rcnn_R-50-FPN_2x.yaml.01_37_22.KSeq0b5q/output/train/coco_2014_train%3Acoco_2014_valminusminival/generalized_rcnn/model_final.pkl \ demo
Ne fonctionne pas non plus, je manque toujours de mémoire, même si j'ai un total de 4 Go de RAM disponible (bien que la mémoire CPU et GPU soit partagée).
Existe-t-il encore un modèle plus petit que je pourrais essayer ?
Comme @Omegastick l'a décrit, cela ne devrait prendre que 2,5 Go de mémoire, mais cela ne semble toujours pas tenir sur le Jetson. D'autres suggestions que je pourrais essayer ?

@johannathiemich J'ai eu le même problème. Il n'y a pas d'erreurs mais le processus a été tué. Avez-vous résolu le problème ? J'utilise aussi Jetson TX1.

@ ll884856 Oui, en fait je l'ai fait. J'ai fini par échanger le filet de base avec un filet compressible et j'ai à nouveau entraîné le filet. Mais gardez à l'esprit que les performances sont bien pires qu'avec le backbone ResNet d'origine.
Ce que vous pouvez également essayer avant de changer le réseau de base, c'est de désactiver le FPN, ce qui pourrait également aider. Mais cela réduira également les performances même si j'espère que la diminution ne sera pas aussi grave.
Si vous le souhaitez, je peux vous donner ma mise en œuvre et les poids du filet. Je travaille actuellement sur ma thèse de licence sur ce sujet.

@johannathiemich Merci pour votre réponse ! En fait, je viens d'être dans ce domaine et je ne suis pas très clair sur l'architecture de Mask R-CNN. Si vous pouvez me donner votre implémentation et vos poids, cela m'aidera beaucoup à comprendre et à implémenter Mask R-CNN. Mon e-mail est [email protected]
Merci !

Ouais, vous pouvez faire Mask-RCNN sur le CPU mais pas avec detectron :

voir:
https://vimeo.com/277180815

J'ai un problème similaire, donc s'il y a quelqu'un pour m'aider ici, je l'apprécierais vraiment https://github.com/facebookresearch/detectron2/issues/1539 Je ne comprends vraiment pas pourquoi cela se produit. J'ai donc besoin de 9,3 Go de RAM pour la prédiction de 25 images dans un lot sur le processeur après y avoir inclus la partie torch.nograd().

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

fangpengcheng95 picture fangpengcheng95  ·  4Commentaires

rbgirshick picture rbgirshick  ·  3Commentaires

baristahell picture baristahell  ·  3Commentaires

junxiaoge picture junxiaoge  ·  3Commentaires

kleingeo picture kleingeo  ·  3Commentaires