2021 네이버 부스트캠프 - Ai tech

Week_3 Pytorch - Out of Memory, OOM 해결

미미수 2021. 8. 20. 14:08

Out  OMemory

 

딥러닝 모델을 돌리다 보면 종종 OOM 에러가 뜨면서 프로그램이 중단되는 현상이 발생한다.

gpu내부 메모리가 꽉차서 발생하는 현상인데, 해결하기 어려운 이유들은 아래와 같다.

 

- 왜 발생했나? → 알기 어려움

- 그럼 어디서 발생했나? → 알기 어려움

- 어찌저찌 Error backtracking해봄 → 엉뚱한데로 감

- 실행하자마자 띡 하고 종료되는게 아니라 누적돼서 특정 시점에 빵하고 터진경우일수 있는데,

이럴때 중단 전 메모리 상황파악이 어려움.

 

등등,, 가지각색의 이유로 발생하는 OOM은 처리하기 까다롭지만 무시할수 있는 에러가 아니기 때문에 해결해야한다.

 


 

해결방법

우선, GPUUtil 사용해서 iter마다 메모리 쌓이는지 확인해보자

 

#!pip install GPUtil

import GPUtil
GPUtil.showUtilization()

 

GPUtil을 사용하면 각 iteration마다 메모리가 늘어나는지 확인 할 수 있다. 

학습은 주로 epoch이란 iteration을 돌기 때문에 메모리가 누적돼서 OOM이 발생할 수 있다.

 

 

 

메모리가 쌓이는게 확인되면, 아래와 같은 조치를 취할 수 있다.

 

 

1. torch.cuda.empty.cache() 로 캐시 비우기

 

사용되지 않고있는 GPU상 cache를 처리하면 그만큼 가용 메모리가 생긴다.

del과는 다르다. 사용한 tensor를 지워도 캐시는 남아있으니 구분해서 사용해야 한다.

 

- : 느리다. 3-5s

 

사용한다면, 매 학습전에 torch.cuda.empty_cache()를 호출해 필요없는 캐시를 날려버리자.

 

 

 

2. Training Loos에서 Tensor로 축적되는 변수 바꾸기

 

total_loss = 0 #loss_sum 초기화
for i in range(100000):
    optimizer.zero_grad()
    output = model(input)
    loss = criterion(output)
    loss.backward()
    optimizer.step()
    
    total_loss += loss  # 문제 지점!!

 

코드를 보면 total_loss에 loss가 계속 누적된다. 

loss만 축적되는것이 아니라 미분에 필요한 computational graph가 계속 생성된다.

total_loss = l1 +l2 +l3 +l4 +....

 

이런 경우 , 아래와 같이 바꿔주면 된다.

total_loss += float(loss)

total_loss += loss.item()

 

3. del 명령어 사용

 

다쓴 변수는 del 키워드를 사용해서 적절하게 삭제해주자.

특히 파이썬은 loop이 끝나도 메모리에 남아있기 때문에 삭제해주면 메모리를 조금 벌 수 있다.

 

 

4. Batch size가 너무 클때

가능한 batch size를 실험해보자.

batch size를 1로 해서 실험해보면 배치사이즈에 따른 문제인지 알 수 있다.

 

oom = False

try:
	run_model(batch_size)
except RunTimeError:
	oom = True
    
if oom:
	for _ in range(batch_size):
    	run_model(1)

 

5. Inference 시점에 torch.no_grad() 사용

 

학습시에는 BackProp을 위해 gradient를 사용해야하지만, 

추론시점에는 gradient가 필요없다. 이럴때, torch.no_grad()를 사용해주자.

 

with torch.no_grad():
	##추론 ~