ML 연구를 위한 GPU · KYC 없는 크립토 결제
IteraGPU
방법 01 · 추정에서 측정으로

메모리 피크가 추정치를 초과하는 이유는 무엇인가요?

가중치 공식은 파라미터의 저장량을 설명하고, 피크는 입력과 임시 할당을 포함한 실행을 설명합니다. 차이를 설명하려면 단위를 동일하게 유지하고, 각 단계를 측정하며, 할당된 메모리, 예약된 메모리, 카드 점유량을 구분하세요. IteraGPU Lab v1 패키지는 재현 가능한 계산과 계측된 소규모 연습을 제공합니다. 아래의 예시 숫자는 계산일 뿐, 공개된 GPU 측정값이 아닙니다.

01 /

카운터를 고르기 전에 부하를 정의하기

「7B 모델」이라는 표현은 가중치의 표현 방식도, 수행할 작업도 명시하지 않습니다. 해당 리비전, 프레임워크, 확장 버전, 실제로 로드된 형식, 그리고 학습·적응·생성 중 어떤 작업인지 기록하세요. 텍스트라면 입력 및 출력 길이를, 비전이라면 해상도와 이미지 수를 적습니다. 멀티모달 모델은 이 두 차원을 모두 유지해야 합니다.

평소 쓰는 입력, 길지만 예상되는 입력, 기능적 한계에 가까운 입력을 준비하세요. 비교하는 동안 이들을 유지합니다. 토큰화, 패딩, 그룹화, 리사이즈 후의 형상을 확인하세요. 설정에 적힌 값이 실제로 처리된 형상을 보장하지는 않습니다.

또한 동시에 메모리에 남는 것도 정하세요. 하나의 시퀀스인지, 마이크로배치인지, 여러 요청인지, 아니면 학습 후 실행되는 평가인지 말입니다. 그러면 질문을 검증할 수 있게 됩니다. 이 전체 부하가 가장 부담이 큰 단계에서도 사용하는 각 장치에 들어가는가?

  • 실험 식별 정보: 모델 또는 코드, 리비전, 입력 집합 및 해당되는 경우 시드.
  • 차원: 배치, 컨텍스트, 생성된 토큰, 해상도 또는 동시 요청 수.
  • 환경: 선택한 GPU, 드라이버, Python, PyTorch, CUDA 또는 HIP/ROCm 백엔드 및 할당자 설정.
  • 범위: 로딩, 연산, 전송, 평가, 내보내기; 최초 패스 또는 워밍업 이후 패스.
02 /

GB와 GiB를 섞지 않고 가중치 계산하기

1GB는 1,000,000,000바이트이고 1GiB는 1,073,741,824바이트입니다. 여기에 사용된 PyTorch 카운터는 바이트를 반환합니다. 이 원시 값을 결과 파일에 보관한 다음, 행을 비교하기 위해 한 번만 변환을 적용하세요. 카드의 상업적 명칭은 장치가 실제로 선언한 용량을 대체하지 않습니다.

각각 2바이트로 저장된 70억 개의 파라미터로 구성된 밀집 집합의 경우, 가중치는 14,000,000,000바이트, 즉 14GB 또는 약 13.04GiB를 차지합니다. 이 계산에는 활성화, 그래디언트, KV 캐시 또는 옵티마이저 상태가 포함되지 않습니다. 여기에 4GiB의 여유분을 추가하면 준비 가설로 약 17.04GiB가 되지만, 이는 작업 부하가 이 범위 안에 들어간다는 것을 증명하지는 않습니다.

4비트 이론적 나누기는 균일한 압축 저장을 가정합니다. 실제 양자화 로딩은 스케일 및 기타 정보를 추가하고 일부 모듈을 다른 정밀도로 유지할 수 있습니다. 따라서 가중치 저장 형식과 계산 형식은 문서에 별도로 명시해야 합니다.

Gio 단위 추정 가중치 = 파라미터 수 × 파라미터당 비트 수 ÷ 8 ÷ 1,073,741,824
7,000,000,000개 파라미터에 대한 예시 계산이며, 실행 결과가 아닙니다.
저장 가정계산된 바이트대략적인 GiB
균일 32비트28 000 000 00026,08
균일 16비트14 000 000 00013,04
4비트 압축, 메타데이터 제외3 500 000 0003,26

기술 출처: NIST — 이진 접두사 및 GB/GiB 비교 · Hugging Face — bitsandbytes를 사용한 양자화 형식 및 모듈

03 /

학습에서는 전체 스텝을 측정하세요

가중치는 다른 객체들과 공존합니다. 그래디언트, 옵티마이저 상태, 역전파에 필요한 활성화, 임시 텐서 등입니다. 이들의 크기는 학습 루프, 정밀도, 워크로드의 차원에 따라 달라집니다. 파라미터당 바이트라는 보편적인 상수는 특히 마이크로배치와 입력의 영향을 가릴 수 있습니다.

순전파, 손실 계산, 역전파, 업데이트를 계측하세요. 옵티마이저가 실제로 생성하는 상태를 관찰하려면 모델 로딩 단계에서 멈추지 마세요. 최초 전체 스텝에 대한 측정값도 보관하세요. 성공적인 워밍업이 이미 시작 시 메모리로 감당할 수 있어야 하는 초기화를 수행했을 수 있습니다.

프로젝트에 필요한 평가와 내보내기도 추가하세요. 평가 중에 실패가 발생한다면 학습 배치만 줄이는 것으로는 해당 단계가 해결되지 않습니다. 적은 수의 파라미터만 학습하는 적응 방식도 여전히 대형 기본 모델과 대용량 활성화를 유지할 수 있습니다.

기술 출처: Hugging Face — 학습 중 메모리 범주

04 /

추론에서는 컨텍스트와 동시성을 추적하세요

어텐션을 사용하는 자기회귀 생성에서 KV 캐시는 토큰과 연관된 상태를 유지합니다. 균일한 밀집 캐시의 크기는 레이어 수, KV 헤드 수, 헤드 차원, 유지되는 토큰 수, 동시에 존재하는 시퀀스 수에 따라 달라집니다. 모델의 KV 헤드를 사용하고, 쿼리 헤드를 자동으로 사용하지 마세요.

산술 예시: 32개 레이어, 8개 KV 헤드, 128 차원, 8,192 토큰, 값당 2바이트, 시퀀스 1개는 1,073,741,824바이트, 즉 K와 V를 합쳐 1GiB를 산출합니다. 동일한 시퀀스 4개는 이 항목만으로 4GiB를 산출합니다. 이 계산은 처리량이나 전체 GPU 점유율을 측정하지 않습니다.

실제로 사용하는 캐시에 맞게 수식을 조정하세요. 슬라이딩 윈도우는 전체 이력을 반드시 유지하지는 않으며, 정적 캐시는 최대 용량을 미리 할당할 수 있습니다. 양자화 캐시와 오프로드 캐시도 문제를 바꿉니다. 입력의 최초 처리와 생성 단계를 각각 따로 측정하고, 그 차이를 자동으로 전부 캐시 탓으로 돌리지 마세요.

밀집 KV 바이트 ≈ 2 × 레이어 수 × KV 헤드 수 × 헤드 차원 × 유지되는 토큰 수 × 시퀀스 수 × 값당 바이트

기술 출처: Hugging Face — 캐시 전략, 정적 할당 및 윈도우

05 /

Allocated와 reserved: 더해서는 안 되는 두 가지 수치

memory_allocated는 PyTorch가 장치에서 추적하는 텐서가 차지한 바이트를 나타냅니다. memory_reserved는 캐시가 있는 할당자가 관리하는 메모리를 나타내며, 여기에는 이미 해당 텐서에 사용된 메모리도 포함됩니다. 둘을 더하면 메모리의 일부를 두 번 계산하게 됩니다. 두 값을 별도의 열로 유지하세요.

각각의 max 변형은 추적 시작 이후 또는 마지막 초기화 이후의 최고치를 기록합니다. 이는 해당 기간의 절대적 최고치로, 시작 시점에 이미 존재하던 할당량까지 포함합니다. 따라서 그 결과가 자동으로 해당 단계에서 생성된 객체만을 나타내는 것은 아닙니다.

시스템 수준의 판독은 더 넓은 범위를 가질 수 있습니다. 예를 들어 일부 NCCL 통신처럼 CUDA 라이브러리가 직접 수행하는 할당은 PyTorch 할당자에서 모두 보이지 않습니다. 따라서 시스템 도구와의 차이만으로 누수가 있다고 단정할 수는 없습니다.

동일한 장치에서 확인해야 할 네 가지 카운터, 모두 바이트 단위입니다.
카운터그것이 답하는 질문피해야 할 오류
memory_allocated이 판독 시점에 텐서가 차지하는 용량은 얼마인가?이를 그래픽카드 전체 점유량으로 간주하는 것.
memory_reserved이 판독 시점에 할당자가 관리하는 용량은 얼마인가?이를 allocated에 더하는 것.
max_memory_allocated해당 기간 동안 추적된 텐서의 최고치는 얼마인가?이를 단계 종료 시점의 값과 혼동하는 것.
max_memory_reserved할당자가 보고하는 예약 최고치는 얼마인가?이것이 다른 최고치와 동일한 시점에 발생한다고 가정하는 것.

기술 출처: PyTorch — memory_allocated · PyTorch — memory_reserved · PyTorch — max_memory_allocated · PyTorch — 자체 할당자 밖의 할당

06 /

두 최고치의 차이가 캐시를 측정하지 않는 이유

표의 두 가상 시점만 살펴봅시다. allocated 최고치는 8GiB이고 reserved 최고치는 12GiB입니다. 그 차이인 4GiB는 이 두 시점 중 어느 곳에서도 관측되는 차이가 아닙니다. 각 시점의 차이는 각각 2GiB와 6GiB입니다. 두 개의 최댓값이 반드시 동일한 상태를 나타내는 것은 아닙니다.

특정 시점에서 두 값의 차이를 연구하려면 동기화 후 판독 사이에 의도적인 추가 연산 없이 동일한 체크포인트에서 allocated와 reserved를 기록하세요. 그러면 해당 시점의 카운터 차이를 얻을 뿐, 모델의 KV 캐시를 측정하거나 그 차이 전체가 다음 할당을 충족할 수 있다는 보장을 얻는 것은 아닙니다.

보고서에 할당자 백엔드도 함께 남기세요. PyTorch 2.14 문서에 따르면 cudaMallocAsync를 사용할 경우 max_memory_reserved가 두 풀의 최고 수준을 결합하여 동시 최고치의 상한을 제공할 수 있습니다. 이는 카운터의 이름과 범위를 유지해야 할 필요성을 더욱 강화합니다.

계산을 설명하기 위해 만들어낸 두 상태이며, 이 표는 GPU 트레이스가 아닙니다.
예시 시점AllocatedReserved해당 시점의 Reserved − allocated
A8GiB10GiB2GiB
B6GiB12GiB6GiB

기술 출처: PyTorch — max_memory_reserved의 정의와 한계

07 /

최고치를 측정하기 전에 각 단계를 구획하기

GPU 연산은 완료되기 전에 큐에 들어갈 수 있습니다. 단계별 측정을 위해서는 최고치를 초기화하기 전에 이전 작업을 끝내고, 판독 전에 해당 단계의 종료를 기다리세요. torch.cuda.synchronize는 선택한 장치의 모든 스트림에서 커널을 기다립니다. 이 선택이 이 프로토콜에 명확한 경계를 정의합니다.

reset_peak_memory_stats는 현재 상태를 기준으로 최고치 추적을 초기화하며, 프로그램의 텐서를 해제하지는 않습니다. 먼저 시작 수준을 기록하세요. 마지막에는 두 절대 최고치와 두 현재 수준을 보존하세요. 시작 수준을 뺀 값을 모든 임시 텐서의 정확한 용량으로 제시하지 마세요. 이전 객체들도 단계 중에 해제되었을 수 있습니다.

이 계측은 단계들의 평소 겹침을 바꿀 수 있습니다. 문제를 국소화하는 데 사용한 다음, 실제 스케줄링으로 전체 루프도 검증하세요. 멀티카드 환경에서는 각 장치마다 판독을 반복하세요. cuda:0에서의 측정은 다른 GPU를 설명하지 못합니다.

  • 1. 단계에 이름을 붙이고 정확한 입력을 기록합니다.
  • 2. 장치를 동기화한 다음 시작 allocated와 reserved를 기록합니다.
  • 3. 동일한 장치에서 reset_peak_memory_stats를 호출합니다.
  • 4. 이후에 필요한 출력을 보존하면서 정의된 단계를 실행합니다.
  • 5. 동기화하고 최고치와 종료 수준을 기록한 다음 성공 또는 오류를 남깁니다.
  • 6. 원시 결과, 크기 및 구성을 유지하고, 누락된 측정값을 0으로 채우지 마세요.

기술 출처: PyTorch — 장치 동기화 · PyTorch — 최고 통계 초기화

08 /

첫 번째 패스와 워밍업 이후 패스 구분하기

첫 번째 시도와 이미 준비된 반복 루프는 서로 다른 질문에 답합니다. 로딩과 첫 번째 통과에 대한 기록을 남기고, 반복 전 워밍업 이터레이션 횟수를 문서화하세요. 이후 통과가 더 가벼웠을 것이라는 이유로 초기화 실패를 삭제하지 마세요.

IteraGPU 스크립트는 model_load, inputs, cold_forward, warmup, warm_forward를 구분합니다. cold_forward는 장치 초기화 후 소형 모델의 첫 번째 통과입니다. 서버, 드라이버 또는 서비스의 전체 시작 시간을 측정하지 않습니다. warm_forward 반복은 동일 프로세스 내에서 이루어지며 기존 상태를 활용합니다.

여러분의 모델의 경우, 이전 객체나 예약을 남길 수 있는 조건을 변경할 때는 새 프로세스에서 새로운 시리즈를 시작하세요. 시도 순서와 워밍업 정책을 기록하세요. 동일한 루프를 다섯 번 재실행하는 것과 다섯 개의 프로세스를 실행하는 것은 동일한 프로토콜이 아닙니다.

09 /

노트북과 IteraGPU Lab v1 스크립트 사용하기

README부터 시작한 다음, 자립형 노트북이나 Python 스크립트를 다운로드하세요. estimate 계산은 표준 라이브러리를 사용합니다. 측정에는 호환되는 GPU 백엔드와 접근 가능한 장치가 설치된 PyTorch가 필요하며, 모델이나 패키지를 다운로드하지 않습니다. 노트북은 ipynb 파일을 읽을 수 있는 환경을 요구합니다.

측정 실습은 독자적인 소형 밀집 네트워크와 합성 입력을 사용합니다. batch, context, width 옵션은 해당 텐서를 설명하며, 여기서 context는 KV 캐시가 있는 실제 LLM의 길이가 아닙니다. 이 자료는 측정 방법을 검토하고 하나의 차원을 변화시키는 데 사용됩니다. 여러분의 연구 모델에 대한 카드의 성능을 입증하지는 않습니다.

스크립트가 있는 폴더에서 아래 명령을 실행하세요. 먼저 environment 보고서를 확인하세요. PyTorch나 GPU가 없으면 measure는 코드 2와 함께 명시적으로 중단되어야 하며, CPU 결과를 GPU 측정으로 해석해서는 안 됩니다. 성공적인 측정의 출력 JSON은 여러분의 환경에서 생성됩니다. 각 시리즈마다 새로운 파일 이름을 선택하세요: 스크립트는 기존 결과를 덮어쓰기를 거부합니다.

첫 번째 명령은 가중치와 가상의 4GiB 예약을 다시 계산합니다. 이후 명령의 경우, 사용 권한이 있는 장치를 사용하고 처음에는 적당한 크기를 유지하세요. 실제로 사용된 PyTorch 버전을 기록하세요: 이 페이지의 기술 참조는 특히 버전 2.14를 설명하지만, 여러분의 환경에 해당 버전이 설치되어 있어야 한다고 강제하지는 않습니다.

스크립트의 작동은 작은 사례로 확인되었습니다: 카탈로그에 없는 로컬 RTX 5070, 드라이버 610.62, Python 3.14.6 및 PyTorch 2.11.0+cu128. 테스트는 배치 1, 컨텍스트 16, 너비 64, float32, 워밍업 1회 및 반복 2회를 사용했습니다. 이는 해당 실행 경로를 검증할 뿐, LLM이나 학습 또는 임대 제공되는 GPU를 규정하지는 않습니다. 노트북은 출력 없이 제공되며 비교 표에는 결과가 없고, PyTorch 부재 가드는 별도 환경에서도 확인되었습니다.

shell
python mesure_memoire.py estimate --parameters 7000000000 --bits 16 --reserve-gib 4
python mesure_memoire.py environment --device cuda:0
python mesure_memoire.py measure --device cuda:0 --batch 2 --context 128 --width 1024 --dtype float32 --warmup 3 --repeats 5 --output mesures.json
10 /

카드를 교체하기 전에 장애 해석하기

불완전한 시도도 유용한 관찰입니다. 단계, 요청된 차원, 오류 메시지 및 마지막으로 사용 가능한 값을 보존하세요. 포화 전의 부분적 피크는 전체 실행의 메모리 요구량이 아닙니다. 성공하는 사례를 만들기 위해 하나의 차원만 줄인 다음, 성공과 실패의 경계를 찾으세요.

empty_cache는 할당자 캐시에서 사용되지 않는 블록을 해제하지만, 아직 살아 있는 텐서는 해제하지 않습니다. 지나치게 큰 부하에 대한 범용 해결책이 아닙니다. 매 반복 사이에 호출하면 조건이 달라지므로, 이런 시도를 캐시를 유지하는 시도와 섞지 말고 그 선택을 문서화하세요.

단순한 카운터로 상황이 설명되지 않는다면, 메모리 트레이스가 시간에 따른 할당을 식별하는 데 도움이 될 수 있습니다. 그 범위는 PyTorch가 볼 수 있는 할당에 한정됩니다. 따라서 allocated 피크가 낮다고 해서 외부 할당이나 카드의 다른 사용자가 없다는 뜻은 아닙니다.

증상을 다음 확인 사항에 연결하며, 자동 진단은 하지 않습니다.
관찰유용한 확인다음 시도
로딩 중 실패로드된 포맷, 가중치 배치, 이미 점유된 메모리.새 프로세스에서 로딩만 단독으로 재현합니다.
로딩은 성공, 역방향 패스 불가마이크로배치, 입력, 유지된 활성값, 루프 상태.한 차원을 줄인 뒤 전체 스텝을 다시 수행합니다.
평가만 단독으로 실패평가 배치, 유지된 출력, 계산 컨텍스트.평가를 자체 한계와 함께 측정합니다.
반복할 때마다 allocated가 증가리스트, 애플리케이션 캐시 또는 그래프에 유지된 참조.할당자를 탓하기 전에 이들의 수명을 확인합니다.
계산 후에도 reserved가 높게 유지아직 살아 있는 텐서와 캐시 정책.카운터를 더하지 않고 현재 값들을 비교합니다.
시스템 도구가 더 많은 값을 표시도구의 범위, GPU 컨텍스트, 다른 프로세스와 라이브러리.부하를 격리하고 같은 시점에 수집한 측정값과 비교합니다.

기술 출처: PyTorch — empty_cache가 해제하는 것 · PyTorch — 메모리 트레이스와 가시성 한계

11 /

비교 가능한 부하를 바탕으로 여유분 설정하기

보편적인 여유 비율을 제시하는 것은 피하세요. 여유분은 확인된 변동을 감당해야 합니다: 더 긴 입력, 허용된 배치, 평가, 내보내기, 라이브러리 버전, 또는 카드의 다른 점유. 예상되는 경계 사례를 테스트한 뒤 범위 밖에 남는 것을 기록하세요. 작은 입력 하나에서 성공한 실행이 최대 부하를 검증하지는 않습니다.

한 번에 하나의 변수만 바꾸세요: 컨텍스트를 고정하고 배치 1에서 2로, 또는 배치를 고정하고 컨텍스트 2 048에서 4 096으로. 동일한 내용과 동일한 준비 규칙을 유지하세요. 필요한 정보를 제거하는 잘라내기는 피크를 줄이더라도 작업을 다른 것으로 만듭니다.

가중치가 지배적이라면 품질을 통제하면서 다른 포맷을 검토하세요. 활성값이 지배적이라면 마이크로배치나 활성값 체크포인팅이 하나의 방안이 될 수 있습니다. 후자는 메모리를 재계산과 맞바꾸므로 소요 시간도 측정하고 결과도 확인하세요. KV 캐시가 지배적이라면 컨텍스트, 동시성, 캐시 전략을 살펴보세요. 비교 자료는 공통 품질 규칙과 함께 이 접근을 보완합니다.

기술 출처: PyTorch — 활성값 체크포인팅과 재계산

12 /

트레이스에서 구성 결정으로 넘어가기

목표 산출물은 짧은 요약 문서입니다: 가중치 추정치, 테스트한 최대 부하, 성공 또는 실패한 단계, 단위를 포함한 네 가지 카운터, 환경, 그리고 선택한 결정. 이 요약에 원시 결과를 첨부하세요. 계산한 것, 관찰한 것, 아직 가정하는 것을 구분하세요.

그다음 소프트웨어 제약을 유지한 채 필요량과 각 카드의 용량을 비교하세요. 여러 GPU는 작업과 데이터의 분할을 요구하며, 그 존재가 애플리케이션을 위한 단일 메모리 풀을 자동으로 만들어 주지는 않습니다. 한 카드에서의 실패는 다른 카드에 여유 메모리가 있어도 지속될 수 있습니다.

PyTorch 프로토콜은 torch.cuda 인터페이스를 사용하며, PyTorch의 HIP/ROCm 빌드도 이 이름을 재사용합니다. 두 하드웨어 계열을 비교하기 전에 실제로 설치된 백엔드를 확인하세요. 같은 Python 함수를 사용한다고 해서 커널, 정밀도 또는 결과가 동등하다는 것이 입증되지는 않습니다.

사이저를 통해 초기 가정을 다시 불러올 수 있고, GPU 요약 정보를 통해 용량을 비교할 수 있습니다. 그다음 동일한 작업 사례로 돌아가 선택을 검증하세요. 다운로드의 작은 네트워크는 계측 연습일 뿐이며, 문서화된 환경에서 여러분의 부하를 실행하는 것만이 여러분 자신의 여유분을 검증할 수 있습니다.

기술 출처: NVIDIA — 여러 GPU에 걸친 작업 분할 · PyTorch — HIP/ROCm 빌드에서의 torch.cuda 인터페이스