- 브라우저에서 직접 실행되는 Stable Diffusion 이미지 생성 데모로, 별도 서버 없이 WebGPU와 WebAssembly 기반으로 동작
- 최신 Chrome에서 "Experimental WebAssembly" 와 "Experimental WebAssembly JavaScript Promise Integration (JSPI)" 플래그를 활성화해야 사용 가능
- Prompt, Negative Prompt, inference step 수를 입력받아 이미지를 생성하며, 모델 파일은 캐싱되어 매번 다시 다운로드할 필요 없음
- 4GB를 초과하는 메모리 할당을 위해 onnxruntime, emscripten, binaryen을 패치하고 Python의 StableDiffusionPipeline을 JS로 포팅한 결과물
- 멀티스레딩 미지원과 WebGPU 연산 미구현 등으로 현재는 속도가 느리지만, 향후 JS 커널 구현과 memory64 지원으로 개선 가능성 제시
실행 요구 사항
- 최신 Chrome 브라우저에서 Experimental WebAssembly 및 Experimental WebAssembly JavaScript Promise Integration (JSPI) 플래그 활성화 필요
- Model files는 캐싱되어 재방문 시 재다운로드 불필요
입력 및 동작 방식
- 입력 항목으로 Prompt, Negative Prompt, inference step 수 제공
- PNDM Scheduler 사용으로 실제 step은 입력값 i에서 i+1로 처리
- 각 step은 약 1분 소요, 이미지 생성을 위한 VAE decoder 실행에 추가로 약 10초 소요
- DevTools를 열어둔 상태에서는 전체 속도가 약 2배 느려짐
- UNET은 CPU에서만 실행되며, GPU보다 10% 빠르고 GPU에서는 올바른 결과를 내지 못해 브라우저 탭이 멈춤
- 수용 가능한 결과를 얻기 위한 최소 step 수는 20이며, 데모 목적으로는 3 step도 무방
FAQ
-
protobuf parsing failed 오류
- DevTools에서 Application → Storage로 이동 후 "Clear site data" 실행
-
sbox_fatal_memory_exceeded 오류
- SD 실행에 필요한 RAM 부족 상태로, 탭 또는 브라우저 재로드로 해결 시도
-
구현 방식
- Python의 StableDiffusionPipeline을 JS로 포팅
- onnxruntime과 emscripten+binaryen(WebAssembly 컴파일러 툴체인)을 패치해 4GB 초과 메모리 할당 및 사용 지원
- 관련 pull request가 릴리스에 반영되면 누구나 브라우저에서 4GB 초과 메모리를 사용하는 코드 컴파일·실행 가능
-
느린 속도의 원인
- 아직 멀티스레딩 미지원으로 CPU 코어 하나만 사용
- WebAssembly.Memory 생성자를 통한 SharedArrayBuffer로 64비트 메모리 생성이 불가능
- "memory64" 플래그 사양 변경을 제안했으며, 채택 후 V8 엔진을 패치해 지원 예정
-
GPU 실행 여부
- GPU에서 실행되지만 onnxruntime의 WebGPU가 초기 단계라 다수 연산이 미구현
- 데이터가 JS를 통해 CPU와 지속적으로 전송됨
- 대부분 연산에 JS 커널이 구현되면 속도 대폭 향상 가능
-
로컬 실행 가능 여부
- 가능하며, 해당 페이지 코드는 stable-diffusion-webgpu-minimal 저장소에서 제공
-
transformers.js로 대형 LLM 실행 가능 여부
- 패치된 onnxruntime 패키지(@aislamov/onnxruntime-web64) 사용 가능하나 모든 경우 동작 보장은 없음
- 해당 빌드는 8GB 메모리로 제한되어 약 4GB 가중치까지 로드 가능
-
onnxruntime 저장소 pull request 계획
- 진행 예정이며, 이전에 node.js 바인딩에 GPU 가속을 추가한 데 이은 두 번째 작업