- Published on
Stable Diffusion VRAM 부족? ComfyUI 타일링·오프로딩 최적화
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버나 데스크톱 GPU가 8GB 이하이거나, SDXL·고해상도 업스케일·ControlNet을 동시에 쓰는 순간 Stable Diffusion은 쉽게 CUDA out of memory로 멈춥니다. 특히 ComfyUI는 워크플로우가 유연한 대신, 노드 조합에 따라 VRAM 사용량이 급격히 튀는 구간이 존재합니다.
이 글은 “왜 OOM이 나는지”를 감으로 때우지 않고, ComfyUI에서 타일링(tiling) 과 오프로딩(offloading) 을 중심으로 VRAM을 줄이는 방법을 재현 가능하게 정리합니다. 목표는 두 가지입니다.
- VRAM이 부족한 환경에서도 원하는 해상도/기능을 가능한 한 유지하기
- 속도·품질·안정성 사이의 트레이드오프를 이해하고 선택하기
VRAM은 어디서 터지나: 병목 지점 4가지
ComfyUI에서 VRAM을 크게 잡아먹는 구간은 보통 아래 4가지입니다.
- UNet 추론 단계: 스텝마다 큰 텐서가 오가며, 해상도에 거의 정비례로 메모리가 증가합니다.
- VAE 디코드/인코드: 최종 이미지 디코드에서 순간 피크가 발생하기 쉽습니다.
- ControlNet/Adapter/LoRA 다중 적용: 모델 추가 로딩 + 중간 피처 증가.
- 고해상도 업스케일(Hires fix, Ultimate SD Upscale 등): “원본 생성 + 업스케일 + 재디테일”로 사실상 2~3번 일을 합니다.
OOM이 “항상 같은 지점”에서 난다면, 그 지점이 피크입니다. ComfyUI는 실행 중 콘솔/로그에서 대략적인 메모리 상황을 확인할 수 있고, OS 레벨에서 nvidia-smi로도 관찰 가능합니다.
watch -n 0.5 nvidia-smi
기본 전제: 먼저 줄여야 할 것들(가성비 순)
타일링/오프로딩 전에, VRAM을 가장 싸게 줄이는 순서를 먼저 정리합니다.
1) 해상도와 배치부터
batch_size는 VRAM에 직격입니다. 먼저1로 고정하세요.- 해상도는 면적 기준으로 증가합니다. 예:
1024x1024는768x768보다 훨씬 큽니다.
2) 샘플러/스텝은 VRAM보다 시간에 영향
스텝 수는 대체로 시간을 늘리지만, 특정 구현에서는 버퍼/캐시로 피크에 영향을 줄 수 있습니다. 그래도 OOM의 1차 원인은 보통 해상도·모델·부가 네트워크입니다.
3) VAE를 바꾸는 것도 효과적
일부 VAE는 메모리 피크가 더 큽니다. “속도는 조금 느려져도 안정적으로”가 목표라면, VAE를 바꾸거나 디코드 타이밍을 조절하는 쪽이 도움이 됩니다.
ComfyUI 타일링(tiling)로 VRAM 줄이기
타일링은 큰 이미지를 한 번에 처리하지 않고, 작은 타일로 쪼개서 순차 처리하는 방식입니다. VRAM 피크를 낮추는 대신, 경계(시접) 처리와 시간이 관건입니다.
ComfyUI에서 타일링이 흔히 쓰이는 지점은 다음입니다.
- 업스케일/리파인 단계(특히 고해상도)
- VAE 디코드/인코드
- Ultimate SD Upscale 계열 워크플로우
타일링의 핵심 파라미터
tile_size: 타일 한 변 크기. 작을수록 VRAM 절약, 느려짐.overlap: 타일 간 겹침. 경계 이음새(seam) 방지.blend또는feather: 겹침 영역을 부드럽게 섞는 정도.
권장 출발점(경험치 기반):
- VRAM
6GB대:tile_size를256또는384,overlap32~64 - VRAM
8GB대:tile_size512,overlap32~64 - VRAM
12GB이상: 타일링 없이도 가능하나, 초고해상도면 타일링이 여전히 유리
예시: 업스케일 타일링 워크플로우 개념
아래는 “저해상도 생성 후 타일 업스케일”의 전형적인 흐름입니다(노드 이름은 설치된 커스텀 노드에 따라 다를 수 있습니다).
Load Checkpoint
-> (optional) Load LoRA(s)
-> KSampler (low-res, batch 1)
-> VAE Decode
-> Upscale (ESRGAN/4x)
-> Tiled Diffusion / Ultimate SD Upscale (tile_size, overlap)
-> VAE Decode (final)
-> Save Image
여기서 VRAM이 부족한 환경이라면, “타일링은 업스케일 단계에만”이 아니라 VAE 디코드도 타일링하는 구성이 안정적일 때가 많습니다.
타일 경계 이슈(줄무늬/이음새) 줄이는 팁
overlap을 늘리면 seam이 줄지만 시간이 늘어납니다.- 디테일이 강한 프롬프트(텍스처, 머리카락, 패턴)는 seam이 더 잘 보입니다.
- 업스케일 후 재디테일 단계에서
denoise를 너무 낮게 잡으면 경계가 고착될 수 있습니다.
실무적으로는 다음 조합이 무난합니다.
tile_size512,overlap64,denoise0.25~0.45
오프로딩(offloading)으로 VRAM 피크 낮추기
오프로딩은 GPU에 올려둔 모델/텐서를 CPU RAM으로 내려 VRAM을 확보하는 전략입니다. VRAM은 절약되지만, PCIe 전송과 CPU 연산 때문에 속도가 느려질 수 있습니다.
ComfyUI에서 오프로딩은 크게 두 층위로 이해하면 쉽습니다.
- 모델 오프로딩: UNet/CLIP/VAE 같은 큰 덩어리를 필요할 때만 GPU에 올림
- 연산 오프로딩: 일부 연산을 CPU로 수행하거나, 더 작은 정밀도로 수행
실행 옵션(예시)과 의미
환경에 따라 옵션은 조금씩 다르지만, 일반적으로 아래 계열을 조합합니다.
--lowvram: VRAM을 아끼는 대신, 더 자주 스왑/오프로딩--medvram: 중간 타협--cpu: 가능한 것을 CPU로(매우 느릴 수 있음)
예시:
python main.py --medvram
VRAM이 6GB 이하인데 SDXL을 억지로 돌려야 한다면, 현실적으로 --lowvram이 필요할 때가 많습니다. 다만 속도 하락이 크므로, 아래의 “타일링 + 부분 오프로딩” 조합으로 타협점을 찾는 것이 좋습니다.
오프로딩이 특히 잘 먹히는 케이스
- ControlNet을 여러 개 붙여 VRAM이 간당간당한 경우
- 업스케일/리파인 단계에서 VAE 디코드가 피크를 만드는 경우
- “처음 몇 스텝은 되다가 중간에 터지는” 케이스(캐시/버퍼 누적으로 피크 상승)
VRAM 절약의 치트키: 정밀도와 어텐션 최적화
타일링/오프로딩과 별개로, VRAM을 크게 줄이는 옵션이 있습니다.
FP16 / BF16 사용
가능하면 가중치와 연산을 fp16 또는 bf16로 유지하면 VRAM이 줄어듭니다. 다만 GPU 아키텍처에 따라 안정성이 다릅니다.
xFormers / SDP 어텐션
어텐션 구현을 메모리 효율적인 것으로 바꾸면 피크가 줄어듭니다. ComfyUI 환경/파이토치 버전에 따라 지원 방식이 달라 “된다/안 된다”가 갈릴 수 있으니, 설치된 빌드에서 실제로 VRAM 피크가 줄었는지 nvidia-smi로 확인하세요.
상황별 추천 레시피(워크플로우 처방전)
아래는 “자주 터지는” 상황별로, 우선순위대로 적용할 처방입니다.
케이스 A: SDXL 1024 기본 생성에서 OOM
batch_size1확인--medvram또는--lowvram- 불필요한 ControlNet/LoRA 제거(특히 다중 ControlNet)
- 해상도를
896x896또는832x1216등으로 약간 낮추고 후처리 업스케일
케이스 B: 생성은 되는데 VAE 디코드에서 터짐
- VAE 디코드 타일링(가능한 노드 사용)
- 업스케일/후처리를 타일 기반으로 변경
- 오프로딩을 켜서 디코드 직전 VRAM을 확보
케이스 C: Ultimate SD Upscale에서 터짐
tile_size를512에서384로 낮춤overlap은32~64유지- 업스케일 배율을 낮추고 2단 업스케일로 분리(예:
2x두 번)
디버깅 체크리스트: “왜 내 것만 터지지?”를 줄이는 방법
VRAM 이슈는 재현이 어려워 보이지만, 체크리스트로 줄일 수 있습니다.
- 같은 워크플로우에서 해상도만 바꿔도 피크가 달라지는가
- ControlNet/LoRA를 하나씩 제거했을 때 피크가 얼마나 떨어지는가
- OOM이 항상 같은 노드에서 나는가(특히 VAE 디코드)
tile_size를 절반으로 줄였을 때 OOM이 사라지는가- 오프로딩 옵션을 바꿨을 때 “완주”는 하는가(속도는 느려져도)
이 과정은 쿠버네티스 장애에서 원인을 단계적으로 좁히는 방식과 유사합니다. 원인 후보를 한 번에 다 바꾸면 무엇이 효과였는지 알 수 없습니다. 장애 진단 접근은 Kubernetes CrashLoopBackOff 원인 8가지 진단 같은 글에서 다루는 방식처럼 “가설을 세우고 한 번에 하나씩”이 가장 빠릅니다.
또한 설정 변경이 누적되면 캐시나 실행 상태가 꼬여 “어제 되던 게 오늘 안 되는” 일이 생기는데, 이런 류의 캐시/상태 문제를 다루는 관점은 Next.js App Router 캐시 꼬임·재검증 버그 해결에서의 접근법과도 통합니다(원인 분리, 재현 최소화, 관측 지표 고정).
실전: ComfyUI 실행 스크립트 예시
환경별로 다르지만, “VRAM 부족 환경에서 안정성 우선”으로 시작할 때의 예시입니다.
# 1) 가장 무난한 타협
python main.py --medvram
# 2) 정말 빡빡할 때(속도 저하 감수)
python main.py --lowvram
여기에 더해, 워크플로우에서 업스케일/디코드 구간을 타일링으로 바꾸면 “완주율”이 크게 올라갑니다.
품질·속도·안정성 트레이드오프 정리
- 타일링: VRAM 절약 효과 큼, 속도 감소, seam 관리 필요
- 오프로딩: VRAM 절약 효과 중~큼, 속도 감소(특히 CPU RAM과 PCIe 영향)
- 정밀도/어텐션 최적화: VRAM 절약 효과 큼, 환경 의존성 있음
권장 결론은 단순합니다.
- 생성(UNet) 단계는 가능한 한 단순하게: 배치
1, 불필요한 네트워크 제거 - 고해상도는 타일링으로: 업스케일/디코드에 타일 적용
- 간당간당하면 오프로딩으로 완주율 확보:
--medvram부터, 안 되면--lowvram
마무리: “VRAM 부족”은 설정 문제가 아니라 설계 문제
VRAM OOM은 단순히 “GPU가 약해서”가 아니라, 워크플로우가 한 번에 너무 많은 텐서를 들고 있으려는 설계 문제인 경우가 많습니다. ComfyUI의 강점은 이 설계를 사용자가 직접 바꿀 수 있다는 점입니다.
- 고해상도는 한 번에 하지 말고 타일로 쪼개기
- 순간 피크를 만드는 VAE/업스케일 구간을 분리하기
- 오프로딩으로 VRAM 상주량을 줄여 완주율을 올리기
위 원칙대로 조합하면, 8GB급 GPU에서도 SDXL과 업스케일을 “느리지만 안정적으로” 굴리는 구성이 충분히 가능합니다.