본문 바로가기

인공지능/Python

Tensorflow/Keras Out of memory 해결

Out of memory

out of memory(이후 OOM)는 여러가지 경우에 발생할 수 있다. 하지만 본문에서 다뤄볼 경우는 하나의 서버 (multi-gpu 환경 포함)에서 여러 keras process를 실행할 때 발생하는 OOM에 대해 말한다. 우선 같은 서버 내에 keras model을 사용하는 process를 실행한 뒤 keras model을 사용하는 process를 하나 더 실행하게 되면 나중에 실행한 process는 높은 확률로 OOM에러를 뿜고 사망할 것이다.

 

Why?

사용자의 잘못이 아닌 tensorflow의 정책 때문이다.

이에 대한 이유로 다음과 같이 설명하고 있다:

By default, TensorFlow maps nearly all of the GPU memory of all GPUs (subject to CUDA_VISIBLE_DEVICES) visible to the process. This is done to more efficiently use the relatively precious GPU memory resources on the devices by reducing memory fragmentation.

요약하면 메모리 조각화(memory fragmentation)을 막기 위해 GPU의 모든 메모리를 일단 배정해놓고 본다는 것

그렇기 때문에 나중에 실행한 process에서는 OOM을 뱉고 사망하는 것이다.

 

Solution

다양한 해결법이 있으나 작성자가 사용한 해결법은 allow_growth 방식이다.

import tensorflow as tf 

config = tf.ConfigProto() 
config.gpu_options.allow_growth = True 
session = tf.Session(config=config)
...

allow_growth 옵션을 True로 설정할 경우 모든 gpu memory를 할당하지 않고 아주 적은 메모리 할당으로 시작해서 process가 필요한 메모리만큼만 제공하게 된다.

이는 해당 process에서 얼마만큼의 메모리가 필요한지 모르는 경우에 적합하게 사용할 수 있다.

문제점은 늘어난 메모리가 다시 줄어들지는 않는다는 점이다. 즉 한번 늘어난 메모리가 프로세스가 죽기 전까지는 줄어들지 않기 때문에 memory fragmentation이 심해질 수 있다고 한다.


두 번째 해결법으로는 직접 사용하지는 않았지만 위의 방식과는 다르게 필요한 메모리의 양을 아는 경우에 사용할 수 있는 per_process_gpu_memory_fraction 방식이다.

import tensorflow as tf 

config = tf.ConfigProto() 
config.gpu_options.per_process_gpu_memory_fraction = 0.4 
session = tf.Session(config=config)
...

per_process_gpu_memory_fraction 옵션은 얼마만큼의 비율로 메모리를 할당해줄 것인지 정해주는 옵션으로 0.4는 gpu하나의 메모리의 40%를 사용하겠다는 뜻이다. 즉 16GB의 gpu메모리를 가지고 있는 경우, 6.4GB의 메모리를 사용한다는 뜻이다.

 

Result

실제 일을 할때 rtsp로 영상을 받아 활성도를 측정해 db에 저장해주는 프로세스 4개를 allow_growth 방식을 이용해 실행한 결과이다.

프로세스 하나당 340MiB를 사용하는 것을 확인할 수 있다. (allow_growth 방식 적용 전에는 첫번째 프로세스가 실행되고 있을 때 다른 프로세스를 실행하면 OOM을 뱉었다.)

Discussion

위 내용은 keras에 적용 가능한 내용으로 pytorch에서는 다른 방식을 이용해 해결법을 제시한다.

pytorch 1.8 release부터 제공하는 gpu memory fraction에 대한 내용을 설명한 블로그를 공유한다.