programing

PyTorch에서 "CUDA 메모리 부족"을 방지하는 방법

powerit 2023. 7. 22. 10:29
반응형

PyTorch에서 "CUDA 메모리 부족"을 방지하는 방법

GPU 메모리가 낮은 PyTorch 사용자에게 매우 일반적인 메시지라고 생각합니다.

RuntimeError: CUDA out of memory. Tried to allocate X MiB (GPU X; X GiB total capacity; X GiB already allocated; X MiB free; X cached)

각 레이어를 GPU에 로드한 다음 다시 로드하여 이미지를 처리하려고 했습니다.

for m in self.children():
    m.cuda()
    x = m(x)
    m.cpu()
    torch.cuda.empty_cache()

하지만 그것은 별로 효과적이지 않은 것 같습니다.작은 GPU 메모리를 사용하면서 큰 딥 러닝 모델을 훈련시킬 수 있는 팁과 요령이 있는지 궁금합니다.

비록 ~일지라도

import torch
torch.cuda.empty_cache()

사용 중인 cuda 메모리를 지울 수 있는 좋은 대안을 제공하며 다음을 사용하여 사용하지 않는 변수를 수동으로 지울 수도 있습니다.

import gc
del variables
gc.collect()

그러나 이러한 명령을 사용한 후에도 pytorch가 실제로 메모리를 지우지 않고 대신 변수가 사용한 메모리에 대한 참조를 지우기 때문에 오류가 다시 나타날 수 있습니다.따라서 커널을 다시 시작한 후 batch_size를 줄이고 최적의 batch_size를 찾는 것이 최선의 가능한 옵션입니다(그러나 때로는 매우 실현 가능하지 않은 옵션도 있습니다).

GPU에서 메모리의 할당에 대한 더 깊은 통찰력을 얻을 수 있는 또 다른 방법은 다음과 같습니다.

torch.cuda.memory_summary(device=None, abbreviated=False)

여기서, 두 인수는 모두 선택 사항입니다.이것은 메모리 할당에 대한 읽기 쉬운 요약을 제공하며 CUDA의 메모리 부족의 원인을 파악하고 커널을 다시 시작하여 오류가 다시 발생하지 않도록 할 수 있습니다(제 경우와 마찬가지로).

데이터를 반복적으로 전달하는 것이 도움이 될 수도 있지만 네트워크 계층의 크기를 변경하거나 계층을 분해하는 것도 효과적입니다(예를 들어 전송 학습을 수행하는 동안 모델이 상당한 메모리를 차지하는 경우도 있기 때문).

배치 크기를 줄이기만 하면 됩니다.교육을 받는 동안 다음과 같은 오류가 발생했습니다.

CUDA 메모리가 부족합니다.20.00MiB 할당 시도(GPU 0, 총 용량 10.76GiB, 이미 할당된 4.29GiB, 사용 가능한 10.12MiB, PyTorch에서 총 예약된 4.46GiB)

그리고 저는 32개의 배치 크기를 사용했습니다.그래서 15로 바꿨는데 효과가 있었습니다.

배치를 반복적으로 CUDA로 보내고 배치 크기를 작게 만듭니다.처음에 모든 데이터를 CUDA에 한 번에 보내지 마십시오.대신 다음과 같이 수행합니다.

for e in range(epochs):
    for images, labels in train_loader:   
        if torch.cuda.is_available():
            images, labels = images.cuda(), labels.cuda()   
        # blablabla  

성적을 너무 끌지 마세요.

모든 배치에서 손실을 합산하려고 했을 때 동일한 오류가 발생했습니다.

loss =  self.criterion(pred, label)

total_loss += loss

그런 다음 성적이 필요한 손실 대신 loss.item을 사용하여 문제를 해결합니다.

loss =  self.criterion(pred, label)

total_loss += loss.item()

아래의 해결책은 카글 질문에서 유발레이나로 인정됩니다.

이 오류는 GPU 메모리와 관련이 있으며 일반 메모리와 관련이 없습니다. => @cjinny 설명이 작동하지 않을 수 있습니다.
텐서플로/케라스 또는 파이토치 사용 까니합?
더 작은 배치 크기를 사용해 보십시오.
Keras를 사용하는 경우 숨겨진 도면층 크기 중 일부를 줄이십시오.
:
모든 교육 데이터를 항상 GPU에 저장합니까?
끌지 .
레이어의 합니다.

대부분의 것들은 커버되지만, 여전히 약간의 추가가 될 것입니다.

토치에서 "2 MiB 할당 시도" 등의 오류가 발생하면 잘못된 메시지입니다.실제로 CUDA는 모델 교육에 필요한 총 메모리가 부족합니다.배치 크기를 줄일 수 있습니다.예를 들어, 배치 크기 1이 작동하지 않더라도(대량의 시퀀스를 사용하여 NLP 모델을 훈련할 때 발생함), 더 적은 데이터를 전달하려고 시도하면 GPU에 모델을 훈련할 메모리가 충분하지 않음을 확인하는 데 도움이 됩니다.

또한 모델을 재교육하려면 가비지 수집 및 클리닝 캐시 파트를 다시 수행해야 합니다.

다음 단계를 수행합니다.

  1. 열차, 밸브, 테스트 데이터 감소
  2. 배치 크기 {예: 16 또는 32} 축소
  3. 모델 매개 변수의 수를 줄입니다. {예:백만 미만

저의 경우, 카글 커널에서 일반적인 음성 데이터 세트를 훈련할 때 동일한 오류가 발생합니다.교육 데이터 세트를 20000으로, 배치 크기를 16으로, 모델 매개 변수를 112K로 축소하여 삭제했습니다.

교육을 마치고 이미지로만 테스트하려면 처음에 torch.no _grad()와 m.eval()을 사용하여 를 추가하십시오.

with torch.no_grad():
  for m in self.children():
    m.cuda()
    m.eval()
    x = m(x)
    m.cpu()
    torch.cuda.empty_cache()

이것은 명백해 보이지만 제 경우에는 효과가 있었습니다.저는 BERT를 사용하여 문장을 임베디드 표현으로 변환하려고 했습니다.BERT는 사전 훈련된 모델이기 때문에 모든 그레이디언트를 저장할 필요가 없었고 GPU의 메모리를 모두 사용했습니다.

피할 수 있는 방법도 있지만 GPU 메모리 크기에 따라 다릅니다.

  1. 데이터를 반복적으로 압축 해제할 때 GPU에 데이터를 로드합니다.
features, labels in batch:
   features, labels = features.to(device), labels.to(device)
  1. FP_16 또는 단일 정밀 부동형 사용.
  2. 메모리가 부족한 경우 배치 크기를 줄이십시오.
  3. 사용하다.detach()불필요한 텐서를 GPU에서 제거하는 방법.

위의 모든 것이 적절하게 사용된다면, PyTorch 라이브러리는 이미 매우 최적화되고 효율적입니다.

너무 단순해 보일 수도 있지만 저에게는 효과가 있었습니다. VS 코드를 닫았다가 다시 연 다음 다시 시작하여 모든 셀을 실행했습니다.

구현:

  1. 이미지를 배치별로 GPU 배치에 공급합니다.

  2. 교육 또는 추론 중에 작은 배치 크기를 사용합니다.

  3. 작은 이미지 크기로 입력 이미지 크기를 조정합니다.

기술적으로:

  1. 대부분의 네트워크는 매개 변수가 초과되어 학습 작업에 비해 너무 큽니다.따라서 적절한 네트워크 구조를 찾는 것이 다음과 같은 도움이 될 수 있습니다.

모델 압축, 네트워크 가지치기 및 양자화와 같은 기술로 네트워크를 압축합니다.

mobileNetv1/2/3과 같은 보다 소형의 네트워크 구조를 직접 사용합니다.

네트워크 아키텍처 검색(NAS).

동일한 오류가 발생하지만 다음 라인을 사용하여 이미지 크기를 최대 600에서 100으로 조정하여 수정합니다.

import torchvision.transforms as transforms
transform = transforms.Compose([
    transforms.Resize((100, 100)), 
    transforms.ToTensor()
])

이상하게 보이지만, 공장에서 런타임을 재설정하거나 탭을 닫더라도 백그라운드에서 공동 작업을 수행하는 세션이 많다는 것을 알게 되었습니다.메뉴에서 "Runtime"을 클릭한 다음 "Manage Sessions(세션 관리)"를 선택하여 이 문제를 해결했습니다.저는 원치 않는 세션을 모두 종료하고 기꺼이 참석했습니다.

저는 PyTorch와 혼합 정밀 교육을 사용하는 것을 추천합니다.교육 속도를 높이고 메모리 소모를 줄일 수 있습니다.

https://spell.ml/blog/mixed-precision-training-with-pytorch-Xuk7YBEAACAASJam 을 보세요.

이것을 아주 간단하게 만드는 꽤 멋진 도서관이 있습니다: https://github.com/rentruewang/koila

pip install koila

코드에서 입력을 게으르게 감싸면 됩니다.

from koila import lazy
input = lazy(input, batch=0)

당신이 32개의 배치 크기를 넘지 않는 한 당신은 괜찮을 것입니다.런타임을 새로 고치거나 재시작해야 합니다. 그렇지 않으면 배치 크기를 줄이더라도 동일한 오류가 발생합니다.배치 크기를 16으로 설정했는데, 훈련 중에 발생하는 그라데이션이 0으로 감소하고 모델이 실제 기능과 훨씬 더 잘 일치합니다.교육 손실을 변동시키는 4 또는 8의 배치 크기를 사용하는 것보다

동일한 오류가 발생하며, 제 GPU는 GTX1650으로 4g 비디오 메모리와 16g 램을 지원합니다.batch_size를 3으로 줄였을 때 효과가 있었습니다.이것이 당신에게 도움이 되기를 바랍니다.

저는 같은 문제에 직면했고 코드 11.3으로 PyTorch 버전을 1.10.1에서 1.8.1로 저하시켜 해결했습니다.저의 경우 CUDA 버전 11.3 이상에서만 작동하는 GPU RTX 3060을 사용하고 있으며, CUDA 11.3을 설치했을 때 PyTorch 1.10.1과 함께 제공되었습니다.그래서 저는 PyTorch 버전을 다운그레이드했고, 지금은 잘 작동하고 있습니다.

pip3 설치 토치==1.8.1+cu111 -f https://download.pytorch.org/whl/torch_stable.html

2 - 열차 배치 크기를 줄여 확인할 수도 있습니다.

이미지로 작업하는 경우 입력 이미지 모양을 줄이기만 하면 됩니다.예를 들어 512x512를 사용하는 경우 256x256을 사용합니다.저한테 효과가 있었어요!

쓰레기 수거 후에 기다리라는 조언은 없습니다.아무 도움이 되지 않는다면 쓰레기가 수거될 때까지 기다려 볼 수 있습니다.사용해 보십시오.

import torch
import time
import gc
from pynvml import nvmlInit, nvmlDeviceGetHandleByIndex, nvmlDeviceGetMemoryInfo

def clear_gpu_memory():
    torch.cuda.empty_cache()
    gc.collect()
    del variables

def wait_until_enough_gpu_memory(min_memory_available, max_retries=10, sleep_time=5):
    nvmlInit()
    handle = nvmlDeviceGetHandleByIndex(torch.cuda.current_device())

    for _ in range(max_retries):
        info = nvmlDeviceGetMemoryInfo(handle)
        if info.free >= min_memory_available:
            break
        print(f"Waiting for {min_memory_available} bytes of free GPU memory. Retrying in {sleep_time} seconds...")
        time.sleep(sleep_time)
    else:
        raise RuntimeError(f"Failed to acquire {min_memory_available} bytes of free GPU memory after {max_retries} retries.")

# Usage example
min_memory_available = 2 * 1024 * 1024 * 1024  # 2GB
clear_gpu_memory()
wait_until_enough_gpu_memory(min_memory_available)

가장 좋은 방법은 배치 크기를 줄이는 것입니다.보통 효과가 있습니다.그렇지 않으면 다음을 시도합니다.

import gc

del variable #delete unnecessary variables 
gc.collect()

언급URL : https://stackoverflow.com/questions/59129812/how-to-avoid-cuda-out-of-memory-in-pytorch

반응형