Detectron: Quedando sin memoria en una tarjeta de 4GB

Creado en 24 ene. 2018  ·  24Comentarios  ·  Fuente: facebookresearch/Detectron

Estoy intentando ejecutar Faster-RCNN en una Nvidia GTX 1050Ti, pero me estoy quedando sin memoria. Nvidia-smi dice que alrededor de 170 MB ya están en uso, pero ¿Faster-RCNN realmente usa 3.8 GB de VRAM para procesar una imagen?

También probé Mask-RCNN (el modelo en el tutorial de introducción) y obtuve alrededor de 4 imágenes (5 si cerré mi navegador) antes de que fallara.

¿Es esto un error o realmente solo necesita más de 4 GB de memoria?

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

Comentario más útil

Una nota adicional: la implementación actual usa optimizaciones de memoria durante el entrenamiento, pero no durante la inferencia. En el caso de la inferencia, es posible reducir sustancialmente el uso de memoria ya que no se necesitan activaciones intermedias una vez que se consumen. Consideraremos agregar optimización de memoria solo de inferencia en el futuro.

Todos 24 comentarios

Hola @Omegastick , los requisitos de memoria del algoritmo Faster R-CNN varían según una serie de factores, incluida la arquitectura de red troncal y las escalas de imagen de prueba utilizadas.

Por ejemplo, puede ejecutar Faster R-CNN con la configuración predeterminada de 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 no debería requerir más de 3 GB para ejecutarse en las imágenes de demostración.

Una nota adicional: la implementación actual usa optimizaciones de memoria durante el entrenamiento, pero no durante la inferencia. En el caso de la inferencia, es posible reducir sustancialmente el uso de memoria ya que no se necesitan activaciones intermedias una vez que se consumen. Consideraremos agregar optimización de memoria solo de inferencia en el futuro.

@Omegastick Probado en mi máquina, tanto Faster RCNN-resnet 101 como Mask RCNN-resnet 101 usan alrededor de 4GB de memoria GPU.

@ ir413 Gracias, el modelo que vinculó funciona muy bien (con un uso de VRAM de 2,5 GB) en mi máquina.

Sería genial si la inferencia no necesitara una GPU en absoluto.

¿Cómo puedo ejecutar mask-rcnn con una GPU de memoria 2G? Alguien puede ayudarme ?

¿Este problema se debe a la implementación de Caffe 2 o Detectron? ¿Qué archivos de Detectron debo mirar para resolver este problema?

@rbgirshick

En el caso de la inferencia, es posible reducir sustancialmente el uso de memoria ya que no se necesitan activaciones intermedias una vez que se consumen. Consideraremos agregar optimización de memoria solo de inferencia en el futuro.

¿Ya hay algo implementado en PyTorch / Caffe2? Si es así, ¿dónde tenemos que excavar?

@gadcam Esto ha estado en mi lista de caffe2.python.memonger.release_blobs_when_used (https://github.com/pytorch/pytorch/blob/master/caffe2/python/memonger.py#L229) debería implementar la mayor parte de lo que necesitamos. Sin embargo, hay algunos problemas no triviales que deben abordarse:

  • Para algunas redes (por ejemplo, Mask R-CNN) se utilizan varias redes en el momento de la inferencia y, por lo tanto, no todas las activaciones pueden liberarse razonando sobre un solo gráfico (porque pueden ser necesarias para otro gráfico, por ejemplo, la red de la cabeza de la máscara).
  • Esta función requiere el uso de un administrador de memoria caché, que no hemos probado, por lo que podría haber problemas con simplemente activarlo.

@rbgirshick ¡ Gracias por su explicación detallada!

Entonces, según tengo entendido, para nosotros release_blobs_when_used actúa como un convertidor de un Proto normal a uno "optimizado para memoria".

Para algunas redes (por ejemplo, Mask R-CNN) se utilizan varias redes en el momento de la inferencia y, por lo tanto, no todas las activaciones pueden liberarse razonando sobre un solo gráfico (porque pueden ser necesarias para otro gráfico, por ejemplo, la red de la cabeza de la máscara).

Dicho en otras palabras, ¿tenemos que llenar dont_free_blobs con blobs usados ​​por la segunda etapa?

Esta función requiere el uso de un administrador de memoria caché, que no hemos probado, por lo que podría haber problemas con simplemente activarlo.

Entonces, si queremos probarlo, necesitaríamos establecer FLAGS_caffe2_cuda_memory_pool en cub (o thc ) pero ¿podríamos hacer esto en Python?
Una de las escasas referencias que pude encontrar está aquí https://github.com/pytorch/pytorch/blob/6223bfdb1d3273a57b58b2a04c25c6114eaf3911/caffe2/core/context_gpu.cu#L190

@gadcam

Entonces, según tengo entendido, para nosotros, release_blobs_when_used actúa como un convertidor de un Proto normal a uno "optimizado para memoria".

Si eso es correcto. Analiza el gráfico de cálculo, determina cuándo ya no se utilizará cada blob y luego inserta una operación de liberación de memoria.

Dicho en otras palabras, ¿tenemos que llenar dont_free_blobs con blobs usados ​​por la segunda etapa?

Sí, con la advertencia de que no estoy seguro de qué tan bien utilizada y / o probada está esta función ... por el código grepping parece que no se usa realmente. Por lo tanto, debo tener en cuenta que es posible que no funcione como se esperaba.

Entonces, si queremos probarlo, tendríamos que configurar FLAGS_caffe2_cuda_memory_pool en cub (o thc), pero ¿podríamos hacer esto en Python?

Si. Creo que el administrador de memoria thc recién agregado es más eficiente. Necesitábamos usarlo en lugar de cub para un caso de uso reciente (aunque diferente).

@rbgirshick ¡ Tienes razón, parece un camino arriesgado!

Si. Creo que el administrador de memoria thc recién agregado es más eficiente. Necesitábamos usarlo en lugar de cub para un caso de uso reciente (aunque diferente).

Lo que quise decir es ¿sabe dónde puedo encontrar documentación para hacerlo o tiene un ejemplo? (Lamento mucho insistir en este, tal vez me perdí algo pero no pude encontrar ninguna documentación al respecto)

@gadcam con respecto a la documentación, no que yo sepa. ¡Perdón!

@asaadaldien Lamento mucho molestarte, pero pareces ser una de las pocas personas que me recomendó

ASEGÚRESE de que caffe2_cuda_memory_pool esté configurado

cuando usamos memonger o data_parallel_model (como referencia estaba aquí ).
¿Tiene alguna pista sobre cómo asegurarnos de que tengamos habilitado un administrador de memoria caché? (Usando Caffe2 en Python)

@gadcam Puede habilitar el asignador en caché cub pasando cub al indicador caffe2_cuda_memory_pool. p.ej :

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

Sin embargo, esto solo es necesario cuando se utiliza memonger de memoria dinámica.

@asaadaldien
Me habría llevado mucho tiempo averiguar cómo hacerlo, ya que no hay documentación sobre GlobalInit .
¡Muchas gracias por su ayuda! ¡Así que ahora puedo comenzar algunos experimentos!

Tengo una solución sencilla a este problema.
Puede establecer 'P2 ~ P5' y 'rois' como blobs de salida, no solo el blob del medio, entonces no se optimizará cuando se utilice la optimización de memoria.

No parece funcionar para mí.
El modelo que probé es e2e_keypoint_rcnn_R-50-FPN_s1x.yaml .
Traté de probarlo contra la parte model.net .

Usé infer_simple.py para las pruebas.

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

y

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) 

donde test_release_blobs_when_used está inspirado en 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)

¡Tenga en cuenta que dont_free_blobs no tiene un valor correcto!

Esta función me dice que no se liberará ningún blob inesperado y que faltan algunos.
(lo cual es normal porque dont_free_blobs no es correcto)
Así que sigo ejecutando el modelo.

Y ... no pasa nada. Verifiqué usando la función save_graph : las operaciones gratuitas están de hecho aquí en el lugar correcto.

El uso de memoria para mis entradas de muestra de esta línea es 1910 Mo +/- 5 Mo
https://github.com/facebookresearch/Detectron/blob/6c5835862888e784e861824e0ad6ac93dd01d8f5/detectron/core/test.py#L158

Pero sucede algo realmente sorprendente si configuro el administrador de memoria en CUB

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

El uso de RAM de la línea RunNet se incrementa en algo así como 3 Go !! (usando el código regular o el personalizado con los blobs gratuitos)

No entiendo lo que está pasando ...

Como se describe en el n. ° 507, también estoy enfrentando un error de memoria insuficiente al iniciar la inferencia en Jetson TX1.
La solución descrita en este hilo, 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
Tampoco funciona, todavía me quedo sin memoria, aunque tengo un total de 4 GB de RAM disponibles (aunque la CPU y la GPU son compartidas).
¿Todavía hay un modelo más pequeño que pueda probar?
Dado que, como lo describió

@johannathiemich tengo el mismo problema. No hay ningún error, pero el proceso se mató. ¿Has resuelto el problema? Yo también uso Jetson TX1.

@ ll884856 Sí, de hecho lo hice. Terminé intercambiando la red de base con un squeezenet y volví a entrenar la red. Pero tenga en cuenta que el rendimiento es mucho peor que con la red troncal ResNet original.
Lo que también podría intentar antes de cambiar la basenet es apagar el FPN que también podría ayudar. Pero también reducirá el rendimiento, aunque espero que la disminución no sea tan mala.
Si lo desea, puedo brindarle mi implementación y los pesos del squeezenet. Actualmente estoy trabajando en mi tesis de licenciatura sobre este tema.

@johannathiemich ¡ Gracias por tu respuesta! De hecho, acabo de estar en este campo y no tengo muy claro la arquitectura de Mask R-CNN. Si me puede dar su implementación y pesos, me ayudará mucho a entender e implementar Mask R-CNN. Mi correo electrónico es [email protected]
Gracias !

Sí, puedes hacer Mask-RCNN en la CPU pero no con detectron:

ver:
https://vimeo.com/277180815

Tengo un problema similar, así que si hay alguien que me ayude aquí, realmente lo agradecería https://github.com/facebookresearch/detectron2/issues/1539 Realmente no entiendo por qué está sucediendo esto. Entonces, necesito 9.3 GB de RAM para la predicción de 25 imágenes en un lote en la CPU después de incluirlo con la parte torch.nograd ().

¿Fue útil esta página
0 / 5 - 0 calificaciones