CUDA 메모리 부족 솔루션

원래 링크는 https://www.zhihu.com/question/274635237 , 텍스트 감지 테스트 중에 CUDA 메모리 부족이 발생했으며 torch.no_grad () 및 torch.cuda.empty_cache ()를 사용하여 사용을 줄였습니다. 비디오 메모리 효과는 분명합니다.

일반적으로 점유 비디오 메모리는 세 부분으로 나뉩니다.

  1. 네트워크 모델의 자체 매개 변수가 차지하는 비디오 메모리입니다.
  2. 모델 계산 중에 생성 된 중간 변수 또는 매개 변수 (앞 / 뒤 / 최적화 포함)도 비디오 메모리를 차지합니다.
  3. 프로그래밍 프레임 워크 자체에는 약간의 추가 오버 헤드가 있습니다.

네트워크 구조 변경

  1. batch_size 줄이기 ...

  2. 계산 속도를 희생하여 메모리 사용량을 줄이고, 계산을 두 부분으로 나누고, 먼저 모델 절반의 결과를 계산하고 중간 결과를 저장 한 다음 모델의 후반부를 계산합니다.

    # 输入
    input = torch.rand(1, 10)
    # 假设我们有一个非常深的网络
    layers = [nn.Linear(10, 10) for _ in range(1000)]
    model = nn.Sequential(*layers)
    output = model(input)
    
    ### 可进行如下更改
    # 首先设置输入的input=>requires_grad=True
    # 如果不设置可能会导致得到的gradient为0
    
    input = torch.rand(1, 10, requires_grad=True)
    layers = [nn.Linear(10, 10) for _ in range(1000)]
    
    
    # 定义要计算的层函数,可以看到我们定义了两个
    # 一个计算前500个层,另一个计算后500个层
    
    def run_first_half(*args):
        x = args[0]
        for layer in layers[:500]:
            x = layer(x)
        return x
    
    def run_second_half(*args):
        x = args[0]
        for layer in layers[500:-1]:
            x = layer(x)
        return x
    
    # 我们引入新加的checkpoint
    from torch.utils.checkpoint import checkpoint
    
    x = checkpoint(run_first_half, input)
    x = checkpoint(run_second_half, x)
    # 最后一层单独调出来执行
    x = layers[-1](x)
    x.sum.backward()  # 这样就可以了
    
  3. 풀링을 사용하여 기능 맵의 크기 줄이기

  4. 완전 연결 레이어 사용 감소

네트워크 구조를 수정하지 마십시오

  1. 가능한 한 inplace 연산을 사용합니다. 예를 들어 relu는 inplace = True를 사용할 수 있습니다. 사용하는 간단한 방법은 다음과 같습니다.

    def inplace_relu(m):
        classname = m.__class__.__name__
        if classname.find('Relu') != -1:
            m.inplace=True
    model.apply(inplace_relu)
    
  2. 각주기가 끝날 때 손실을 삭제하면 비디오 메모리를 거의 절약 할 수 있지만 아무것도없는 것보다 낫습니다.

  3. float16 정밀도 혼합 계산을 사용하면 비디오 메모리의 거의 50 %를 절약 할 수 있지만 평균 및 합계, 오버플로 fp16과 같은 일부 안전하지 않은 작업에주의하십시오.

  4. 검증, 테스트 사용과 같은 Forward bp가 필요하지 않습니다 torch.no_grad().주의 model.eval()는 다음과 같지 않습니다.torch.no_grad()

    • model.eval()모든 레이어는 평가 모드에 있다는 알림을 받게되므로 배치 노름 또는 드롭 아웃 레이어가 훈련 모드 대신 평가 모드에서 작동합니다.
    • torch.no_grad()autograd에 영향을 미치고 비활성화합니다. 메모리 사용량을 줄이고 계산 속도를 높이며 역 전파 할 수 없습니다 (평가 스크립트에서는 필요하지 않음).
  5. torch.cuda.empty_cache ()는 del의 고급 버전입니다.

  6. 옵티 마이저 변환의 사용, 이론적으로 sgd <momentum <adam, 추가 중간 변수가 있음을 계산 공식에서 볼 수 있습니다.

  7. Depthwise Convolution

  8. 데이터를 한 번에로드하지 말고 부분적으로 읽어야 기본적으로 메모리 부족 문제가 발생하지 않습니다.

추천

출처blog.csdn.net/m0_38007695/article/details/108085949