Apple Silicon M1에서 스테이블 디퓨전 3.5 미디엄 메모리 최적화 가이드
25억 파라미터를 가진 스테이블 디퓨전 3.5 미디엄 모델은 T5-XXL 인코더(10.75GB, fp16 기준)로 인해 애플 실리콘 환경에서 최대 21GB의 통합 메모리를 소비할 수 있습니다. 최적화된 로딩 전략을 적용하면 피크 메모리 사용량을 단 11.6GB로 줄일 수 있어, 16GB RAM을 가진 M1 맥에서도 원활한 작동이 가능합니다. 본 가이드에서는 문제의 핵심 원인을 분석하고, 단계별 메모리 효율화 전략을 소개합니다.
메모리 급증의 주요 원인:
- 가중치 중복: 모델이 CPU에 로드된 후 MPS로 복사됨.
enable_model_cpu_offload()는 효과 없음 — CPU와 MPS가 통합 메모리를 경쟁함.- Accelerate의
device_map훅은 강한 참조를 유지해 가비지 컬렉션을 방해함.
기본 코드:
pipe = StableDiffusion3Pipeline.from_pretrained(
"stabilityai/stable-diffusion-3.5-medium",
torch_dtype=torch.float16, variant="fp16")
pipe.to("mps")
num_inference_steps와 무관하게 피크 메모리: 21.4GB.
해결책: 순차적 로딩 전략
프롬프트 인코딩(T5) → 언로드 → 생성(DiT + VAE) 단계로 분리하여 처리합니다.
1. device_map="balanced"으로 로딩
CPU 스테이징 없이 직접 MPS에 로드:
pipe = StableDiffusion3Pipeline.from_pretrained(
path, torch_dtype=torch.float16, device_map="balanced")
T5 피크 메모리: 약 11GB.
2. 올바른 훅 제거
from accelerate.hooks import remove_hook_from_submodules
for attr in list(vars(pipe)):
comp = getattr(pipe, attr, None)
if isinstance(comp, torch.nn.Module):
remove_hook_from_submodules(comp)
setattr(pipe, attr, None)
del pipe
gc.collect()
torch.mps.synchronize()
torch.mps.empty_cache()
이 단계를 생략하면 T5가 메모리에 계속 남아 있음(10.75GB).
3. 완전한 순차 워크플로우
단계 1: 인코더 로딩
enc_pipe = StableDiffusion3Pipeline.from_pretrained(path,
transformer=None, vae=None,
text_encoder=None, text_encoder_2=None,
tokenizer=None, tokenizer_2=None,
variant="fp16", torch_dtype=torch.float16,
device_map="balanced")
prompt_embeds, neg_embeds, pooled, neg_pooled = enc_pipe.encode_prompt(
prompt="a warrior with a sword",
prompt_2="a warrior with a sword",
prompt_3="a warrior with a sword",
device="mps", num_images_per_prompt=1)
이 단계 이후 즉시 언로드.
단계 2: 생성기 로딩
gen_pipe = StableDiffusion3Pipeline.from_pretrained(path,
text_encoder=None, text_encoder_2=None, text_encoder_3=None,
tokenizer=None, tokenizer_2=None, tokenizer_3=None,
variant="fp16", torch_dtype=torch.float16)
gen_pipe.to("mps")
image = gen_pipe(
prompt_embeds=prompt_embeds,
negative_prompt_embeds=neg_embeds,
pooled_prompt_embeds=pooled,
negative_pooled_prompt_embeds=neg_pooled,
num_inference_steps=40).images[0]
.to("mps")는 T5 캐시를 재사용해, DiT 메모리 사용량을 11.5GB에서 6GB로 대폭 감소시킴.
메모리 사용량 비교표
| 단계 | 최적화 전 | 최적화 후 |
|-------------------|----------------|----------------|
| T5 로드 | 15.3 GB | 11.5 GB |
| T5 언로드 후 | 10.75 GB | 0.01 GB |
| DiT + 디퓨전 | 8.9 GB | 8.9 GB |
| 피크 메모리 | 21.4 GB | 11.6 GB |
하드웨어 성능 비교
- M1 16GB: 4분 54초 (T5: 1분 6초, DiT: 3분 34초), 피크 메모리 11–13GB.
- M3 Pro 36GB: 1분 47초 (T5: 14초, DiT: 1분 27초), 피크 메모리 9–11GB.
해상도: 512x512, 추론 단계: 40회.
핵심 요약:
- T5-XXL이 전체 메모리 사용의 약 71%를 차지함.
device_map="balanced"과 훅 제거 조합이 언로드에 필수적임.- 순차적 로딩으로 피크 메모리 사용량 45% 감소.
- 스왑 없이도 M1 16GB 맥에서 안정적으로 작동.
- DiT에
.to("mps")적용 시 캐시 재사용이 효율적임.
— Editorial Team
아직 댓글이 없습니다.