loss.backward() 시에 메모리 오류가났다

그래서 이에 관련하여 많은 정보들을 구글링함.

나한테 맞는 해결책은 1도 없었다..

결국 원인을 추적해서 해결함


구글링한 지식들이 아까워서 정리해보았다.

아래는 오류가 나는 상황들과 해결책이다.


1. for문 구조에 의한 data 중복

  python 기본 구조로 for문 사용 시, 이전 타임의 데이터를 가지고 있다고함

  그래서 어쩔수 없이 data = Data(input) 하면

  Data(input) 리턴 값에 해당하는 메모리가 순간적으로 2배가 사용된다는 의미임 (이전에 data 삽입된 값이 남아있어서)

  - 해결책 -

  del data

  코드를 넣어주면 이러한 현상을 막을 수 있음


2. output을 이용한 연산

  만약 loss += network.get_loss() 등과 같이, 이전에 텐서 연산 결과를 계속 이용하면

  loss 메모리가 계속 쌓이게됨

  - 해결책 -

  loss += network.get_loss().data[0] # or network.get_loss().data.cpu().numpy()[0]

  이러면 해결됨


3. test or validation 시 메모리 오류

  train 시에는 괜찮은데, test 시에 오류가 나는 경우

  test 시에는 기울기를 계산하지 않겠다는 선언을 해줘야함

  - 해결책 -

  Variable을 선언할 때 인자로 volatile=True를 넣어주면 됨

  ex) train code:      Variable(im_data.cuda())

       evaluate code: Variable(im_data.cuda(), volatile=True)


4. 나한테 발생했던 오류

 

class RoIPool(Module):
def __init__(self, pooled_height, pooled_width, spatial_scale):
super(RoIPool, self).__init__()

self.pooled_width = int(pooled_width)
self.pooled_height = int(pooled_height)
self.spatial_scale = float(spatial_scale)

def forward(self, features, rois):
return RoIPoolFunction(self.pooled_height, self.pooled_width, self.spatial_scale)(features, rois)

class RoIPool(Module):
def __init__(self, pooled_height, pooled_width, spatial_scale):
super(RoIPool, self).__init__()

self.pooled_width = int(pooled_width)
self.pooled_height = int(pooled_height)
self.spatial_scale = float(spatial_scale)
self.module = RoIPoolFunction(self.pooled_height, self.pooled_width, self.spatial_scale) ##

def forward(self, features, rois):
return self.module(features, rois)

로 수정함

내부적으로 forward하면서 class를 계속 생성하고 있었음.



그리고 이러한 증상을 발견할 수 있는 tip.

memory 오류 날때까지 기다리지 말고

명령창 하나 더 띄워서 nvidia-smi -l 1 입력

그러면 memory 오류 시, iter 마다 메모리 사용량이 증가하는 것을 볼 수 있음

어디서 메모리 증가가 일어나는지 보려면

중간에 return 넣어주면된다.

그럼 return 전까지 괜찮은지, 문제가 있는지 볼 수 있음

+ Recent posts