Detectron: Ficando sem memória em um cartão de 4 GB

Criado em 24 jan. 2018  ·  24Comentários  ·  Fonte: facebookresearch/Detectron

Estou tentando executar o Faster-RCNN em uma Nvidia GTX 1050Ti, mas estou ficando sem memória. A Nvidia-smi diz que cerca de 170 MB já estão em uso, mas o Faster-RCNN realmente usa 3,8 GB de VRAM para processar uma imagem?

Eu tentei o Mask-RCNN também (o modelo no tutorial de introdução) e obtive cerca de 4 imagens (5 se eu fechasse meu navegador) antes de travar.

Isso é um bug ou ele realmente só precisa de mais de 4 GB de memória?

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

Comentários muito úteis

Uma observação adicional: a implementação atual usa otimizações de memória durante o treinamento, mas não durante a inferência. No caso de inferência, é possível reduzir substancialmente o uso de memória, uma vez que as ativações intermediárias não são necessárias depois de consumidas. Consideraremos a adição de otimização de memória somente inferência no futuro.

Todos 24 comentários

Olá @Omegastick , os requisitos de memória do algoritmo Faster R-CNN variam dependendo de uma série de fatores, incluindo a arquitetura da rede de backbone e as escalas de imagem de teste usadas.

Por exemplo, você pode executar o Faster R-CNN com a configuração padrão do ResNet-50 usando:

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

que não deve exigir mais de 3 GB para rodar nas imagens de demonstração.

Uma observação adicional: a implementação atual usa otimizações de memória durante o treinamento, mas não durante a inferência. No caso de inferência, é possível reduzir substancialmente o uso de memória, uma vez que as ativações intermediárias não são necessárias depois de consumidas. Consideraremos a adição de otimização de memória somente inferência no futuro.

@Omegastick Testado em minha máquina, o Faster RCNN-resnet 101 e o Mask RCNN-resnet 101 usam cerca de 4 GB de memória GPU.

@ ir413 Obrigado, o modelo que você vinculou funciona muito bem (rodando com 2,5 GB de uso de VRAM) na minha máquina.

Seria legal se a inferência não precisasse de uma GPU.

como posso executar o mask-rcnn com uma GPU de memória 2G? Alguém pode me ajudar ?

Este problema é devido à implementação do Caffe 2 ou Detectron? Quais arquivos no Detectron devo examinar para resolver este problema?

@rbgirshick

No caso de inferência, é possível reduzir substancialmente o uso de memória, uma vez que as ativações intermediárias não são necessárias depois de consumidas. Consideraremos a adição de otimização de memória somente inferência no futuro.

Já existe algo implementado no PyTorch / Caffe2? Se sim, onde precisamos cavar?

@gadcam Isso está na minha lista de tarefas há muito tempo, mas infelizmente sua prioridade tem diminuído em vez de aumentar: /. Acho que caffe2.python.memonger.release_blobs_when_used (https://github.com/pytorch/pytorch/blob/master/caffe2/python/memonger.py#L229) deve implementar a maior parte do que precisamos. No entanto, existem alguns problemas não triviais que precisam ser resolvidos:

  • Para algumas redes (por exemplo, Máscara R-CNN), várias redes são usadas no momento da inferência e, portanto, nem todas as ativações podem ser liberadas raciocinando sobre apenas um gráfico (porque podem ser necessárias para outro gráfico, por exemplo, a rede da cabeça da máscara).
  • Esta função requer o uso de um gerenciador de memória de cache, que não testamos, então pode haver problemas em simplesmente ligá-lo.

@rbgirshick Obrigado por sua explicação detalhada!

Pelo que entendi, para nós release_blobs_when_used atua como um conversor de um Proto normal para um "otimizado para memória".

Para algumas redes (por exemplo, Máscara R-CNN), várias redes são usadas no momento da inferência e, portanto, nem todas as ativações podem ser liberadas raciocinando sobre apenas um gráfico (porque podem ser necessárias para outro gráfico, por exemplo, a rede da cabeça da máscara).

Em outras palavras, temos que preencher dont_free_blobs com blobs usados ​​pelo segundo estágio?

Esta função requer o uso de um gerenciador de memória de cache, que não testamos, então pode haver problemas em simplesmente ligá-lo.

Portanto, se quisermos testá-lo, precisaremos definir FLAGS_caffe2_cuda_memory_pool como cub (ou thc ), mas podemos fazer isso em Python?
Uma das poucas referências que consegui encontrar está aqui https://github.com/pytorch/pytorch/blob/6223bfdb1d3273a57b58b2a04c25c6114eaf3911/caffe2/core/context_gpu.cu#L190

@gadcam

Pelo que entendi, para nós, release_blobs_when_used atua como um conversor de um Proto normal para um "com memória otimizada".

Sim esta correto. Ele analisa o gráfico de computação, determina quando cada blob não será mais usado e, em seguida, insere uma operação de liberação de memória.

Em outras palavras, temos que preencher dont_free_blobs com blobs usados ​​pelo segundo estágio?

Sim, com a ressalva de que não tenho certeza se essa função é bem usada e / ou testada ... pelo código grep, parece que ela não é realmente usada. Portanto, devo ter em mente que pode não funcionar como esperado.

Portanto, se quisermos testá-lo, precisaremos definir FLAGS_caffe2_cuda_memory_pool como cub (ou thc), mas podemos fazer isso em Python?

sim. Acho que o gerenciador de memória thc recém-adicionado é mais eficiente. Precisamos usá-lo em vez de cub para um caso de uso recente (embora diferente).

@rbgirshick Você está certo, parece um caminho arriscado!

sim. Acho que o gerenciador de memória recém-adicionado é mais eficiente. Precisávamos usá-lo em vez de cub para um caso de uso recente (embora diferente).

O que eu quis dizer é que você sabe onde posso encontrar documentação para fazer isso ou você tem um exemplo? (Lamento muito insistir neste, talvez eu tenha esquecido alguma coisa, mas não consegui encontrar nenhuma documentação sobre isso)

@gadcam em relação à documentação, que eu saiba. Desculpa!

@asaadaldien , sinto muito por incomodá-lo, mas você parece ser uma das poucas pessoas que aconselhou a

CERTIFIQUE-SE de que caffe2_cuda_memory_pool está definido

quando usamos memonger ou data_parallel_model (para referência estava aqui ).
Você tem alguma dica sobre como garantir que temos um gerenciador de memória cache habilitado? (Usando Caffe2 em Python)

@gadcam Você pode habilitar o alocador em cache do cub passando cub para o sinalizador caffe2_cuda_memory_pool. por exemplo :

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

No entanto, isso é necessário apenas ao usar o memonger de memória dinâmica.

@asaadaldien
Eu teria demorado muito para descobrir como fazer, pois não há documentação sobre GlobalInit .
Muito obrigado pela ajuda! Agora posso começar alguns experimentos!

Eu tenho uma solução simples para este problema.
Você pode definir 'P2 ~ P5' e 'rois' como blobs de saída, não apenas o blob do meio, então ele não será otimizado ao usar a otimização de memória.

Não parece funcionar para mim.
O modelo que testei é e2e_keypoint_rcnn_R-50-FPN_s1x.yaml .
Tentei testá-lo com a parte model.net .

Usei infer_simple.py para os testes.

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

e

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) 

onde test_release_blobs_when_used é inspirado em 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)

Observe que dont_free_blobs não está definido com um valor correto!

Esta função me diz que nenhum blob inesperado seria liberado e que alguns estão faltando.
(o que é normal porque dont_free_blobs não está correto)
Então, continuo executando o modelo.

E ... nada acontece. Eu verifiquei usando a função save_graph : as operações gratuitas estão realmente aqui no lugar certo.

O uso de memória para minhas entradas de amostra desta linha é 1910 Mo +/- 5 Mo
https://github.com/facebookresearch/Detectron/blob/6c5835862888e784e861824e0ad6ac93dd01d8f5/detectron/core/test.py#L158

Mas algo realmente surpreendente acontece se eu definir o gerenciador de memória para CUB

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

O uso de RAM da linha RunNet é aumentado em algo como 3 Go !! (usando o código normal ou personalizado com os blobs gratuitos)

Não consigo entender o que está acontecendo ...

Conforme descrito em # 507, também estou enfrentando um erro de falta de memória ao iniciar a inferência no Jetson TX1.
A solução descrita neste tópico, como:
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
Também não funciona, continuo sem memória, embora tenha um total de 4 GB de RAM disponível (embora a CPU e a memória GPU sejam compartilhadas).
Existe um modelo menor que eu poderia experimentar?
Como @Omegastick descreveu, ele deve ocupar apenas 2,5 GB de memória, mas ainda não parece caber no Jetson. Alguma outra sugestão que eu possa tentar?

@johannathiemich Eu tenho o mesmo problema. Não há erros, mas o processo foi encerrado. Você já resolveu o problema? Eu também uso o Jetson TX1.

@ ll884856 Sim, na verdade eu fiz. Acabei trocando a rede de base pelo squeezenet e treinei a rede novamente. Mas lembre-se de que o desempenho é muito pior do que com o backbone ResNet original.
O que você também pode tentar antes de alterar o basenet é desligar o FPN que também pode ajudar. Mas também reduzirá o desempenho, embora eu espere que a queda não seja tão ruim.
Se você quiser, posso dar minha implementação e pesos do squeezenet para você. Atualmente, estou trabalhando em minha tese de bacharelado sobre esse assunto.

@johannathiemich Obrigado pela sua resposta! Na verdade, acabei de entrar neste campo e não estou muito certo sobre a arquitetura do Mask R-CNN. Se você puder me dar sua implementação e pesos, vai me ajudar muito a entender e implementar o Mask R-CNN. Meu e-mail é [email protected]
Obrigado !

Sim, você pode fazer o Mask-RCNN na CPU, mas não com o detectron:

Vejo:
https://vimeo.com/277180815

Eu tenho um problema semelhante, então se houver alguém para me ajudar aqui, eu realmente apreciaria https://github.com/facebookresearch/detectron2/issues/1539 Eu realmente não entendo por que isso está acontecendo. Portanto, preciso de 9,3 GB de RAM para prever 25 imagens em um lote na CPU, após incluir a parte torch.nograd ().

Esta página foi útil?
0 / 5 - 0 avaliações