- Published on
Stable Diffusion 4K 생성, VRAM OOM 피하는 실전법
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
Stable Diffusion으로 4K 이미지를 바로 뽑으려 하면 가장 흔하게 마주치는 문제가 VRAM OOM(out of memory)입니다. 특히 8GB~12GB GPU에서 3840x2160 같은 해상도를 한 번에 생성하려는 순간, 샘플링 중간에 메모리가 터지거나 속도가 급격히 느려져 작업이 끊깁니다.
이 글은 “4K를 꼭 얻되, OOM 없이”를 목표로 합니다. 핵심은 한 방에 4K를 만들지 않고, 메모리 사용량이 폭증하는 구간을 분해하는 것입니다. 즉, (1) 저해상도에서 구도를 확정하고 (2) 업스케일과 디테일을 단계적으로 올리며 (3) 타일링 또는 오프로딩으로 피크 VRAM을 제어합니다.
왜 4K에서 VRAM이 터질까
Stable Diffusion의 메모리 사용량은 단순히 픽셀 수에만 비례하지 않습니다. 대략적으로는 다음 요소들이 곱해지며 피크가 생깁니다.
- 해상도 증가: 픽셀 수가 커지면 U-Net의 feature map 텐서가 커져 VRAM이 급증
- 배치 크기:
batch size가 2만 되어도 텐서가 거의 2배 - 샘플러/스텝: 스텝이 늘면 시간은 늘지만, 피크 VRAM은 주로 텐서 크기와 attention 구현에 좌우
- ControlNet/LoRA/ADetailer: 추가 네트워크가 붙으면 activation/attention 캐시가 증가
- VAE 디코드: 큰 해상도를 한 번에 디코드할 때도 메모리 스파이크가 생김
실무적으로는 3840x2160을 “직접 생성”하는 순간 U-Net 추론 텐서가 너무 커져 OOM이 발생합니다. 따라서 전략은 두 가지 중 하나로 수렴합니다.
- 타일링: 큰 이미지를 여러 타일로 쪼개 처리(피크 VRAM 제한)
- 업스케일 파이프라인: 저해상도 생성 후 업스케일 + 부분 디테일링(피크 VRAM 완화)
권장 파이프라인: 1K 생성 + 2단 업스케일 + 타일 디테일
가장 안정적인 4K 루트는 아래 조합입니다.
- 베이스 생성:
1024x576또는1280x720 - 1차 업스케일: 2배(예:
2048x1152) - 2차 업스케일: 2배에 가깝게(최종 4K 근접)
- 마지막 디테일: 타일 기반 img2img 또는 타일 디퓨전으로 질감만 보강
이 방식은 “한 번에 4K U-Net”을 피하므로, 8GB~12GB에서도 성공률이 높습니다.
해상도 선택 팁(비율 고정)
- 16:9 4K는
3840x2160 - 베이스는 같은 비율로
1280x720또는1024x576추천 - SDXL 계열이면 베이스
1024근처가 품질 대비 효율이 좋음
Automatic1111에서 OOM 줄이는 설정 체크리스트
Automatic1111(WebUI)를 기준으로, “OOM 확률을 확 낮추는” 옵션들을 정리합니다.
1) xFormers 또는 SDP attention
- Settings에서 xFormers를 활성화하거나 PyTorch의 SDP가 켜져 있는지 확인
- attention 메모리 최적화는 체감이 큼
2) Medvram / Lowvram
--medvram은 속도 손해를 감수하고 VRAM을 절약- 정말 빡빡한 환경이면
--lowvram도 가능하지만 속도 저하가 큼
3) VAE 타일링(가능한 경우)
- 큰 해상도에서 VAE 디코드가 OOM을 유발하는 경우가 있어, VAE 타일 디코드를 지원하는 확장이나 옵션을 활용
4) 배치 크기/하이레스 단계 조정
batch size는 1로 고정- Hires.fix를 쓰면 “2단계 생성”이 되므로, 업스케일 배율과 denoise를 낮추면 피크 VRAM이 줄어듦
4K를 만드는 3가지 실전 레시피
아래는 환경별로 바로 적용 가능한 레시피입니다.
1) Hires.fix로 4K를 노리되, 실패 확률을 낮추는 법
Hires.fix는 편하지만, 설정을 공격적으로 잡으면 4K에서 OOM이 잘 납니다. 포인트는 “업스케일 배율을 욕심내지 않고, denoise를 낮춰 2차 U-Net 부담을 줄이는 것”입니다.
권장 예시(16:9 기준):
- 1차:
1280x720 - Hires.fix:
1.5x또는1.7x정도로만(예:2176x1224근처) - 이후 별도 업스케일러로 4K까지
이렇게 하면 Hires.fix 단계에서의 피크 VRAM이 줄고, 마지막은 ESRGAN류 업스케일러로 마무리합니다.
예시 프롬프트 세팅(개념)
- Steps: 25~35
- CFG: 5~7
- Sampler: DPM++ 2M Karras 계열
- Hires steps: 기본 steps의 30~60%
- Hires denoise: 0.25~0.45
2) 타일 기반 img2img로 4K 디테일만 채우기(추천)
4K를 “픽셀 단위로 새로 그리기”가 아니라, 업스케일된 4K 이미지에 대해 타일 단위로 img2img를 돌려 질감만 보강하면 VRAM 피크를 강하게 제한할 수 있습니다.
개념적으로는 다음 순서입니다.
- 베이스 생성(1K)
- 업스케일(4K 도달)
- 타일 img2img로 디테일 강화(타일 크기 512 또는 768)
타일링에서 중요한 파라미터:
- Tile size:
512또는768 - Overlap:
64~128(경계 이음새 방지) - Denoise:
0.15~0.35(너무 높이면 원본 구도 붕괴)
이 방식은 VRAM이 타일 크기에 의해 상한이 생겨, 4K 전체를 한 번에 처리하지 않습니다.
3) ComfyUI에서 메모리 오프로딩으로 안정성 확보
ComfyUI는 노드 기반이라 파이프라인을 명확히 쪼개고, CPU 오프로딩이나 메모리 전략을 조합하기 좋습니다. 특히 ControlNet을 여러 개 쓰거나, SDXL + 디테일러까지 붙는 복잡한 워크플로에서 유리합니다.
핵심은 “최종 4K는 업스케일러와 타일 디퓨전으로 처리”하고, U-Net이 가장 큰 텐서를 들고 있는 구간을 피하는 것입니다.
VRAM OOM 디버깅: 어디서 터지는지부터 확인
OOM은 원인이 다를 수 있습니다.
- 샘플링 시작 직후 OOM: 해상도/배치/ControlNet 조합이 과함
- 샘플링 끝나고 VAE decode에서 OOM: VAE 타일 디코드 또는 더 작은 중간 해상도 필요
- Hires 단계에서 OOM: Hires 배율/denoise/steps를 줄이거나 2단 업스케일로 분리
이런 “증상 기반 원인 추적”은 인프라 장애를 파고들 때와 비슷합니다. 문제가 재현될 때 로그와 조건을 쪼개 원인을 좁히는 접근이 중요합니다. 비슷한 디버깅 사고방식은 K8s CrashLoopBackOff 원인별 로그·Probe 디버깅 글의 흐름도 참고할 만합니다.
코드로 파이프라인 구성하기(diffusers)
WebUI가 아니라 Python으로 돌릴 때는 Hugging Face diffusers에서 메모리 최적화 옵션을 적극적으로 켜야 합니다. 아래 예시는 SDXL 계열에서 “저해상도 생성 후 업스케일”을 염두에 둔 최소 예시입니다.
주의: 아래 코드 블록의 제네릭/부등호는 MDX 빌드 이슈를 피하기 위해 모두 백틱 처리합니다.
import torch
from diffusers import StableDiffusionXLPipeline
model_id = "stabilityai/stable-diffusion-xl-base-1.0"
dtype = torch.float16
pipe = StableDiffusionXLPipeline.from_pretrained(
model_id,
torch_dtype=dtype,
variant="fp16",
)
# 메모리 절약 1: attention 최적화
pipe.enable_xformers_memory_efficient_attention()
# 메모리 절약 2: VAE slicing/tiling (환경에 따라 효과 큼)
pipe.vae.enable_slicing()
pipe.vae.enable_tiling()
# 메모리 절약 3: CPU 오프로딩 (속도는 느려질 수 있음)
pipe.enable_model_cpu_offload()
prompt = "cinematic landscape, ultra detailed, sharp focus"
# 1) 베이스는 1024 근처로 생성
image = pipe(
prompt=prompt,
width=1280,
height=720,
num_inference_steps=30,
guidance_scale=6.0,
).images[0]
image.save("base_1280x720.png")
이후 업스케일은 전용 업스케일러(Real-ESRGAN 등)를 쓰거나, diffusers의 업스케일 파이프라인을 별도로 붙일 수 있습니다. 중요한 건 “U-Net이 4K 텐서를 들고 샘플링하는 상황”을 피하는 것입니다.
타일 디퓨전의 경계 이음새(seam) 줄이는 요령
타일 접근은 OOM을 해결하지만, 타일 경계가 티 나는 문제가 생길 수 있습니다. 아래 조합이 실전에서 자주 통합니다.
- Overlap을 충분히 준다:
64~128 - Denoise를 낮춘다:
0.15~0.35 - 타일 크기를 너무 작게 하지 않는다: 가능하면
768(VRAM이 허용하면) - 프롬프트를 “질감 중심”으로 바꾼다: 구도/객체를 다시 그리게 하는 단어를 줄임
예를 들어 디테일 단계에서는 wide shot, full body, composition 같은 단어를 빼고, texture, fine details, film grain, micro contrast 같은 표현을 남기는 편이 안정적입니다.
ControlNet/LoRA를 쓰면서 4K를 안전하게 만드는 법
ControlNet과 LoRA는 품질을 올리지만 VRAM을 잡아먹습니다. 4K 파이프라인에서는 다음 원칙이 안전합니다.
- ControlNet은 베이스 구도 확정 단계(1K) 에서만 적극 사용
- 4K 디테일 단계(타일 img2img)에서는 ControlNet을 끄거나 1개만 유지
- LoRA는 여러 개를 동시에 쓰기보다, 가중치를 낮추고 필요한 것만 남김
실제로 OOM은 “마지막에 뭔가 하나 더 얹었더니” 발생하는 경우가 많습니다. 이런 상황에서 재시도 전략을 자동화하고 싶다면, 과부하/실패를 다루는 패턴 관점에서 Claude 3 API 529/503 과부하 재시도·백오프 설계 글의 백오프 설계 아이디어를 응용할 수 있습니다. 예를 들어 해상도나 타일 크기를 단계적으로 낮추는 “파라미터 백오프”를 구현하는 식입니다.
실패 없는 4K를 위한 권장 설정 템플릿
아래는 8GB~12GB에서도 비교적 성공률이 높은 방향의 템플릿입니다.
단계 1: 베이스 생성
- 해상도:
1280x720 - Steps: 28~35
- CFG: 5~7
- ControlNet: 필요 시 1~2개까지(과하면 단계 2에서 끄기)
단계 2: 업스케일
- 업스케일러: 2배(예:
2560x1440) - 샤픈/노이즈: 과하게 주지 않기
단계 3: 최종 4K 도달
- 업스케일러:
3840x2160맞춤 - 크롭 없이 비율 유지
단계 4: 타일 디테일(img2img)
- Tile size:
512또는768 - Overlap:
96 - Denoise:
0.2전후 - Steps: 15~25
마무리
Stable Diffusion에서 4K를 OOM 없이 만들려면, “한 번에 4K 생성” 집착을 버리고 업스케일과 타일링으로 피크 VRAM을 통제하는 게 정답에 가깝습니다. 베이스는 1K 근처에서 구도를 확정하고, 업스케일로 픽셀을 늘린 뒤, 타일 img2img로 디테일만 채우면 4K도 충분히 실용적인 속도와 안정성으로 뽑을 수 있습니다.
추가로 자동화(예: 실패 시 타일 크기/denoise/ControlNet 수를 줄이는 재시도)를 붙이면 “가끔 되는” 수준에서 “항상 되는” 파이프라인으로 올라갈 수 있습니다. 이는 운영 환경에서 장애를 다루는 방식과도 닮아 있으며, 재처리/복구 설계 관점은 Saga 보상 트랜잭션 실패 재처리 설계 가이드 같은 글의 접근을 참고해도 좋습니다.