Section 01모델 파일 형식
커뮤니티는 CIVITAI 같은 사이트에 수많은 모델을 공유한다. 이 파일들은 보통 .ckpt 또는 .safetensors 형식이다. safetensors는 임의 코드 실행 위험이 있는 pickle 기반 .ckpt보다 안전하고 빠른 형식이다.
독립형 checkpoint 파일을 Diffusers 형식으로 변환해 두면 로딩이 빨라진다. 변환된 모델 폴더는 from_pretrained로 로드한다.
from diffusers.pipelines.stable_diffusion.convert_from_ckpt import \ download_from_original_stable_diffusion_ckpt pipe = download_from_original_stable_diffusion_ckpt( r"D:\temp\deliberate_v2.safetensors", from_safetensors = True, device = "cuda:0" ) pipe.save_pretrained(r"D:\temp\deliberate_v2")
from_pretrained에 safety_checker=None을 넘겨 끌 수 있다. 다만 책임 있는 사용은 사용자의 몫이다.
Section 02SDXL 2단계 파이프라인
SDXL은 Stability AI의 모델로, 이전과 다르게 2단계 모델로 설계되었다. 기본(base) 모델이 원시 이미지를 latent로 생성하고, 선택적인 리파이너(refiner) 모델이 그것을 개선한다. 최상의 품질을 위해서는 기본 모델로 4×128×128 latent를 만든 뒤 리파이너로 향상시킨다.
base_pipe.to("cuda") with torch.no_grad(): base_latents = base_pipe( prompt = prompt, negative_prompt = neg_prompt, output_type = "latent" ).images[0] base_pipe.to("cpu") # base 모델을 VRAM 밖으로 torch.cuda.empty_cache() # refiner 를 올려 latent 를 개선 refiner_pipe.to("cuda") with torch.no_grad(): image = refiner_pipe( prompt = prompt, negative_prompt = neg_prompt, image = [base_latents] ).images[0]
CUDA out of memory로 멈춘다. 위 코드처럼 base를 쓰고 나면 to("cpu")로 내려 VRAM을 비우는 것이 핵심이다.
Section 03기준선과 float16
최적화에 들어가기 전 기준선을 잡는다. RTX 3090에서 기본 설정으로 512×512 이미지를 만들면 8.4GB VRAM, 초당 7.51회 반복이다. PyTorch는 기본적으로 합성곱에 TF32, 행렬 곱셈에 FP32를 쓴다.
FP32·TF32는 역사적 유산이며 훈련에는 필요하지만, 추론이 그 정도의 수치 정밀도를 요구하는 일은 드물다. float16 또는 bfloat16 반정밀도로 가중치를 로드하면 VRAM을 아끼고 속도를 높일 수 있다.
| 형식 | 최대 양수 | 특성 |
|---|---|---|
| float16 | 약 6.55e4 | 가수 비트 풍부, 상대 정밀도 높음 |
| bfloat16 | 약 3.39e38 | 동적 범위 넓음, 심층 신경망에 유용 |
text2img_pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype = torch.bfloat16 # float16 / bfloat16
).to("cuda:0")
Section 04VAE tiling과 offload
나머지 최적화는 더 큰 이미지 생성과 VRAM 절약을 노린다. VAE tiling은 이미지를 작은 타일로 쪼개 각각 생성한 뒤 오버랩으로 엣지를 블렌딩한다 — 과도한 VRAM 없이 대형 이미지를 만든다. 한 줄이면 켜진다: pipe.enable_vae_tiling().
Xformers는 지능적인 2계층 attention으로 VRAM을 더 줄이고 속도를 높인다. PyTorch 2.0은 이 기능을 기본 제공·자동 활성화한다.
text2img_pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype = torch.float16
)
# .to("cuda") 를 제거한다
text2img_pipe.enable_model_cpu_offload() # 전체 모델 오프로드
image = text2img_pipe(prompt=prompt).images[0]
모델 CPU offload는 가중치만 옮기는 대신 전체 모델을 GPU와 CPU 사이로 통째로 이동한다. UNet처럼 여러 번 반복되는 구성 요소는 더 필요 없을 때까지 GPU에 남는다. CPU↔GPU 이동에 1~2초가 추가되지만, VRAM을 3.6GB까지 낮춘다.
Section 05Token Merging
마지막 최적화는 Token Merging(ToMe)이다. Daniel Bolya 등이 제안했다. 모델 안의 중복 토큰을 찾아 병합한다 — 두 토큰이 매우 유사하면 값을 평균 내 하나로 합친다. 모델이 처리할 토큰 수가 줄어 추론이 빨라진다.
import tomesd text2img_pipe = StableDiffusionPipeline.from_pretrained( "runwayml/stable-diffusion-v1-5", torch_dtype = torch.float16 ).to("cuda:0") tomesd.apply_patch(text2img_pipe, ratio=0.5) # 중복 토큰 병합
| 기법 | 효과 | 대가 |
|---|---|---|
| float16/bfloat16 | VRAM 절반, 속도 2배 | 미세한 정밀도 손실 |
| VAE tiling | 대형 이미지 생성 가능 | 거의 없음 |
| Xformers / PyTorch 2.0 | VRAM↓ 속도↑ | 거의 없음 |
| 순차적 CPU offload | VRAM 대폭 절약 | 추론 속도 저하 |
| 모델 CPU offload | VRAM 3.6GB까지 | CPU↔GPU 이동 1~2초 |
| Token Merging | 추론 속도 향상 | 이미지 미세 변화 (품질 영향 미미) |
CUDA out of memory는 흔한 비극이다. 이 여섯 기법을 조합하면 4GB GPU에서도 모델을 굴릴 수 있다. AI 환경은 끊임없이 진화하므로 새 솔루션이 등장하겠지만, 내부 작동 원리를 이해하면 어떤 도구든 필요에 맞게 조정할 수 있다.