본문으로 건너뛰기
5분 AI.
GITHUB TRENDING C++ MONTHLY #1 딥다이브 · 2026-10-23 분석

stable-diffusion.cpp 딥다이브
— 문장을 그림으로 바꾸는 C++ 추론 엔진의 내부

추론 라이브러리·서버

빠른 판단

무엇
확산 모델을 CPU·GPU에서 실행하며 CLI·HTTP 서버·C API를 제공하는 C/C++ 로컬 생성 엔진
이럴 때
이미지·영상 모델을 네이티브 앱에 내장하거나 로컬 명령·서버로 연결해 추론 파이프라인을 구성할 때
입력
지원 모델 가중치·프롬프트·생성 설정과 참조 입력
결과
선택한 모델이 생성한 이미지·영상
그림 한 장이 나올 때까지 컴퓨터 안에서는 어떤 일이 벌어질까요? stable-diffusion.cpp는 SD·Flux·Wan·Qwen Image·Z-Image 같은 생성 모델을 C/C++로 실행하는 프로젝트입니다. 문장을 숫자로 바꾸고, 잡음에서 이미지를 만들어 내고, GPU 메모리를 나눠 쓰는 과정을 실제 함수까지 따라갑니다. C/C++ 자체 코드 약 10만 8천 줄에서 배우는 추론 파이프라인·메모리 관리·크로스 플랫폼 설계. 저장소 leejet/stable-diffusion.cpp · 스타 7,764 · 포크 890 · MIT (2026-10-23 GitHub 기준) · 커밋 fd21ecf 기준.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

학습된 생성 모델을 내 컴퓨터에서 실행하는 엔진

stable-diffusion.cpp는 이미 학습된 확산 계열 모델의 가중치를 읽어 이미지나 영상을 생성하는 C/C++ 라이브러리입니다. 이 저장소의 핵심은 모델을 새로 학습하는 일이 아니라, 학습된 모델을 여러 하드웨어에서 효율적으로 실행하는 일입니다.

사용 방법은 세 가지입니다. 터미널에서 sd-cli를 실행하거나, sd-server의 웹 화면·HTTP API를 이용하거나, include/stable-diffusion.h의 C API를 다른 프로그램에 연결할 수 있습니다. 세 입구가 별도의 생성 엔진을 갖는 것은 아닙니다. CLI와 서버도 같은 라이브러리를 호출합니다.

전체를 이해하는 비유

모델은 악보, 엔진은 연주자, GPU는 악기

가중치 파일은 수많은 숫자가 적힌 악보에 가깝습니다. 파일만 있다고 그림이 나오지는 않습니다. 엔진은 악보의 구조를 해석하고, 계산 순서를 정하고, CPU나 GPU에 계산을 맡기는 연주자입니다.

같은 악보도 악기와 연주 방식에 따라 비용과 결과가 달라집니다. 모델 파일·수치 정밀도·난수·샘플러·백엔드를 함께 기록해야 생성 실험을 제대로 비교할 수 있습니다.

용어 먼저
추론과 가중치
추론은 학습이 끝난 모델로 결과를 계산하는 과정입니다. 가중치는 모델이 학습한 규칙을 담은 숫자입니다. 실행 파일과 가중치 파일은 별도로 준비하며, 코드의 MIT 라이선스와 모델의 이용 조건도 별개입니다.

문장 한 줄이 그림 한 장이 되는 기본 경로

  1. 모델 로딩: 가중치 파일의 형식·텐서 이름·모델 종류를 확인합니다.
  2. 문장 인코딩: 토크나이저와 텍스트 인코더가 프롬프트를 조건 벡터로 바꿉니다.
  3. 반복 계산: 난수로 만든 초기 상태를 모델과 샘플러가 여러 단계에 걸쳐 갱신합니다.
  4. 이미지 복원: 일반적인 잠재 확산 경로에서는 VAE가 잠재 표현을 픽셀로 바꿉니다.
  5. 결과 전달: C API가 이미지 배열을 반환하고, CLI·서버가 파일이나 응답으로 바꿉니다.

이것은 SD 계열을 이해하기 위한 기본 지도입니다. 저장소는 flow 계열과 영상 모델도 다루므로, 모든 모델이 동일한 잡음 예측식·잠재 채널 수·VAE 구조를 쓰는 것으로 일반화하면 안 됩니다. 실제 차이는 src/model/과 src/pipeline/request.cpp의 분기에서 확인할 수 있습니다.

이 글의 학습 목표
수학 전체를 몰라도 함수 사이의 계약은 읽을 수 있다

처음에는 행렬 연산의 모든 식을 이해하려고 하지 않아도 됩니다. 각 함수가 무엇을 받고 무엇을 돌려주는지, 실패하면 누가 자원을 정리하는지부터 표시해 보세요. 이 관점만으로도 생성 AI를 실제 제품에 넣는 시스템 설계를 배울 수 있습니다.

2왜 주목받는가

로컬 생성 AI를 배포 가능한 소프트웨어로 만드는 기술

2026-10-23 GitHub Trending C++ Monthly 1위로 선정된 프로젝트입니다. 순위가 오른 정확한 원인은 순위만으로 알 수 없습니다. 다음은 README의 최근 소식과 구현 구조에 근거해 해석한 기술적 관심 요인입니다.

관심 요인확인 근거개발자에게 생기는 가치
빠른 모델 대응README는 2026-10-16 FLUX.3·MOSS-Image의 공개 당일 지원을 알림새 모델을 기존 로컬 추론 도구로 다룰 가능성
구현 범위 확대src/model/diffusion/flux3.hpp, moss_image.hpp, wan.hpp 등 실제 구현 파일이미지·편집·영상의 공통점과 차이를 한 코드베이스에서 비교
C/C++ 통합C API, sd-cli, sd-server가 함께 제공됨다른 언어 바인딩이나 네이티브 앱의 엔진으로 연결
메모리 관리GGMLRunner, DeviceResidencyManager, 자동 가중치 배치·분할 계산 경로장치 메모리가 부족할 때의 설계 대안을 공부

README의 “공개 당일 지원”은 유지관리자의 발표입니다. 구현 파일의 존재는 확인되지만, 모든 기능의 품질·속도·하드웨어 조합까지 검증되었다는 뜻은 아닙니다. 이 구분은 오픈소스의 홍보 문구를 읽을 때도 유용합니다.

다른 도구와 비교하면 역할이 선명해진다

아래는 제품의 우열이나 속도 순위가 아니라 어떤 작업에 중심을 두는지의 비교입니다. Diffusers와 ComfyUI의 성격은 각 공식 저장소 설명을 기준으로 합니다.

도구중심 작업이 레포에서 얻는 비교 관점
stable-diffusion.cppC/C++·ggml 기반 추론, CLI·C API·서버Python 추론 환경 없이 네이티브 라이브러리로 통합하는 경로를 제공
DiffusersPyTorch 기반 파이프라인 구성, 추론 최적화·학습 안내Python으로 실험할 때와 C++로 배포할 때의 계층 차이를 비교
ComfyUI노드·그래프로 생성 작업을 구성하는 GUI와 API사용자가 연결하는 작업 그래프와 엔진 내부 계산 그래프의 차이를 비교

비교 근거: Diffusers 공식 저장소, ComfyUI 공식 저장소. 세 도구 모두 로컬 활용 경로가 있으므로, 로컬 실행 자체만으로 차별점을 설명하는 것은 부족합니다.

이 프로젝트의 강점은 생성 기능을 C API와 장치별 계산 계층으로 나누어, 다른 프로그램 안에 넣을 수 있게 만든 구조에 있습니다.

비유로 구별하기

Diffusers를 조립 가능한 실험 키트, ComfyUI를 작업 순서를 연결하는 편집실로 본다면, stable-diffusion.cpp에서는 편집실 아래에 들어갈 수 있는 엔진의 구조를 배웁니다. 목적이 다르므로 어느 쪽이 항상 더 빠르거나 더 쉽다고 결론 내릴 수는 없습니다.

“가볍다”를 정확하게 읽는 법

README는 외부 의존성이 없는 매우 가벼운 구현이라고 소개합니다. 소스의 CMakeLists.txt는 ggml·Threads·Oniguruma·utf8proc 등을 연결하고, 서버 웹 UI를 빌드할 때에는 pnpm도 사용합니다. 따라서 이 문구는 의존성이 문자 그대로 0개라는 뜻보다, 추론 코어가 Python·PyTorch 런타임을 필수로 요구하지 않는 구조로 이해하는 편이 정확합니다.

네이티브 실행 파일이 작아도 모델 가중치와 계산 중간값은 클 수 있습니다. 배포 편의성, 디스크 사용량, RAM·VRAM 사용량, 생성 속도는 각각 따로 평가해야 합니다.

3기술 스택 전체 지도

추론 코어, 선택적인 웹 화면, 재현 가능한 빌드 경계

3-1. 백엔드: C++17 위에 쌓은 모델 실행 계층

루트 CMakeLists.txt는 최소 CMake 버전을 3.12, C 표준을 C11, C++ 표준을 C++17로 선언합니다. C++ 내부 구현은 클래스를 쓰지만, 공개 진입점은 C 호환 API입니다. 최상위 package.json·Cargo.toml·pyproject.toml·go.mod로 관리하는 프로젝트는 아닙니다.

구성요소실제 버전·고정 기준역할과 근거 파일
컴파일 규격C11 / C++17 / CMake 최소 3.12CMakeLists.txt의 표준·최소 버전 선언
ggml서브모듈 커밋 c1f80e5텐서 연산·장치 백엔드. .gitmodules는 leejet/ggml 포크를 가리킴
cpp-httplib0.28.0thirdparty/httplib.h의 버전 매크로. 서버의 HTTP 처리
nlohmann/json3.11.2thirdparty/json.hpp의 버전 매크로. 요청·메타데이터·설정 해석
Oniguruma6.9.10thirdparty/oniguruma/README.md. UTF-8 정규표현식에 필요한 부분을 포함
utf8proc2.10.0 / Unicode 16.0.0thirdparty/utf8proc/README.md. Unicode 정규화·문자 처리
stb 이미지 도구읽기 2.28 / 쓰기 1.16 / 크기 조정 0.90thirdparty/stb_image*.h 파일 머리말에 명시
libwebp서브모듈 커밋 0c9546fWebP 입출력과 WebM용 VP8 프레임 인코딩
libwebm서브모듈 커밋 5bf1226WebM 컨테이너 출력. SD_WEBM은 SD_WEBP를 요구
시스템 스레드고정 패키지 버전 없음find_package(Threads REQUIRED)로 운영체제 구현 연결

서브모듈의 고정 커밋은 패키지 버전 번호와 다른 식별자입니다. ggml 버전을 비교할 때에도 이 커밋 식별자를 함께 확인해야 합니다. cmake/ggml.cmake는 ggml-impl.h 같은 비공개 헤더도 요구하므로, 시스템에 설치된 아무 ggml이나 교체하면 된다고 생각해서는 안 됩니다.

의존성 읽기
벤더링과 서브모듈
벤더링은 외부 라이브러리 소스를 저장소 안에 포함하는 방식입니다. 서브모듈은 다른 Git 저장소의 특정 커밋을 가리킵니다. 전자는 파일을 바로 읽을 수 있지만, 후자는 포인터만 있고 실제 내용이 없는 상태일 수 있습니다.

3-2. 프론트엔드: 별도 저장소에서 빌드한 화면을 서버에 포함

웹 화면은 examples/server/frontend/ 서브모듈이며, 주소는 leejet/sdcpp-webui, 고정 커밋은 34e5ad6입니다. 이 커밋의 본체 소스 트리에는 해당 서브모듈의 package.json과 잠금 파일 내용이 포함되어 있지 않습니다. 프레임워크와 프런트엔드 패키지 버전은 웹 UI 저장소의 해당 커밋을 기준으로 확인해야 합니다.

대신 연결 방식은 examples/server/CMakeLists.txt에서 직접 읽을 수 있습니다. SD_SERVER_BUILD_FRONTEND 기본값은 ON이고, pnpm을 발견하면 다음 세 작업을 순서대로 실행하도록 빌드 타깃을 만듭니다.

# examples/server/CMakeLists.txt의 빌드 순서 — 저장소 루트 기준 경로
pnpm --ignore-workspace -C examples/server/frontend install
pnpm --ignore-workspace -C examples/server/frontend run build
pnpm --ignore-workspace -C examples/server/frontend run build:header
# 결과: examples/server/frontend/dist/gen_index_html.h

헤더를 포함하는 빌드에서는 HAVE_INDEX_HTML이 정의됩니다. pnpm이 없더라도 미리 생성된 헤더가 있으면 사용할 수 있고, 둘 다 없으면 웹 화면 포함이 비활성화됩니다. examples/server/routes_index.cpp의 register_index_endpoints()는 내장 HTML 또는 serve_html_path로 지정된 파일을 루트 경로에서 응답합니다.

추론에 필요한 런타임과 웹 화면을 만드는 빌드 도구를 구분하면, 의존성 목록을 훨씬 정확하게 읽을 수 있습니다.

3-3. 인프라·빌드: 장치에 맞춰 같은 코어를 조립한다

영역확인한 설정해석
라이브러리SD_BUILD_SHARED_LIBS=OFF 기본값기본은 정적 라이브러리. 옵션으로 공유 라이브러리 생성
예제 타깃단독 빌드에서 SD_BUILD_EXAMPLES=ONexamples/CMakeLists.txt가 CLI와 서버를 모두 추가
장치 선택SD_CUDA·SD_METAL·SD_VULKAN 등은 기본 OFF켜면 대응하는 GGML_* 설정으로 연결
일반 DockerUbuntu 24.04, Node.js 20 계열, pnpm 10.15.1docker/Dockerfile에서 빌드 단계에 화면 도구 설치
CUDA DockerCUDA 12.6.3, Ubuntu 24.04docker/Dockerfile.cuda의 이미지 인수. 모든 GPU의 최소 요구 버전을 뜻하지 않음
CINode 20, pnpm 10.15.1, 재귀 서브모듈 체크아웃.github/workflows/build.yml의 빌드 설정

Docker는 빌드 단계와 실행 단계를 나눕니다. 일반 이미지의 실행 단계에는 빌드한 bin/과 libgomp1을 가져오고, 진입점은 /sd-cli로 설정합니다. 웹 화면 제작에 Node가 필요하다는 사실과, C++ 추론 프로세스가 Node로 실행된다는 주장은 다릅니다.

docs/build.md는 WebP·WebM을 기본 활성화로 소개하지만, 실제 CMake 기본값은 해당 서브모듈 소스의 존재 여부와 시스템 라이브러리 사용 설정에 따라 결정됩니다. 문서의 일반적인 설치 경로와 빌드 설정의 조건부 동작을 함께 읽어야 하는 사례입니다.

또한 기본 ggml은 수정된 포크입니다. SD_USE_UPSTREAM_GGML=ON을 켜는 호환 모드는 INT8 tensorwise/convrot을 비활성화하고, 일부 FP8 가중치를 로딩 시 F16으로 바꿉니다. 같은 파일이라도 선택한 ggml 모드에 따라 메모리 사용과 지원 연산이 달라질 수 있습니다.

4아키텍처 심화 분석

한 번의 요청이 어디로 들어와 어떤 계층을 통과하는가

4-1. 시스템 구조도

사용자 / 외부 프로그램
   |
   +--- sd-cli -----------------------+
   |    examples/cli/main.cpp         |
   |                                  v
   +--- 브라우저 / HTTP ---> sd-server ---> 공개 C API
        화면은 선택적       라우트·큐       include/stable-diffusion.h
                            잠금           src/stable-diffusion.cpp
                                             |
                                             v
                                     StableDiffusionGGML
                                     설정·모델·실행 수명 관리
                                             |
                     +-----------------------+---------------------+
                     |                       |                     |
                     v                       v                     v
              ModelLoader         src/pipeline/image.cpp  src/pipeline/video.cpp
              파일 형식 판별          생성 요청·샘플 계획       영상 생성 경로
              텐서 목록 구성                 |
                     |                       v
                     |              Conditioner: 문장 조건
                     |                       |
                     |              초기 잡음 + 조건 벡터
                     |                       |
                     +------------> StableDiffusionGGML::sample()
                                    반복 샘플링 / guidance
                                    모델 예측: DiffusionModelRunner::compute()
                                             |
                                             v
                                       VAE 복원 경로
                                             |
                                             v
                                      sd_image_t 배열

  공통 실행 기반: GGMLRunner / ComputeWorkspace / ModelManager
                   |
       계산 그래프 + 가중치 배치·전송·분할
                   |
                   v
         ggml 백엔드: CPU / CUDA / Metal / Vulkan 등

  가중치 파일: GGUF / safetensors / Torch 체크포인트
  파일 저장·응답 인코딩: examples/common/media_io.cpp 등

위 도식은 주요 역할과 흐름을 요약한 것입니다. 모든 모델이 같은 클래스나 같은 잠재 공간을 쓰는 것은 아닙니다. 핵심은 사용자 입구, 생성 절차, 모델 구현, 하드웨어 실행을 서로 다른 층으로 읽는 것입니다.

4-2. 이미지 한 장을 만드는 실제 호출 흐름

단계파일·함수읽어야 할 책임
컨텍스트 생성src/stable-diffusion.cpp / new_sd_ctx()StableDiffusionGGML 생성과 초기화, 실패 시 정리
실행 진입같은 파일 / generate_image()출력 초기화·인수 검사·ExecutionScope 확보
요청 정리src/pipeline/image.cpp / sd::pipeline::generate_image()GenerationRequest·SamplePlan 생성, 전처리·LoRA 적용
잠재 상태 준비같은 파일 / prepare_image_generation_latents()초기 이미지·마스크·참조 이미지에 따른 상태 준비
조건 준비같은 파일 / prepare_image_generation_embeds()프롬프트·부정 프롬프트·참조 이미지 조건 계산
반복 생성StableDiffusionGGML::sample()모델·잡음·조건·sigma 일정·guidance로 상태 갱신
결과 복원decode_image_outputs() / decode_first_stage()최종 상태를 이미지로 변환하고 출력 개수 전달

image.cpp는 요청의 seed로 난수 생성기를 초기화한 뒤, 배치마다 sd::randn_like<float>()로 잡음을 준비하고 sd->sample(...)을 호출합니다. sd_img_gen_params_init()의 기본값은 512×512, 20단계, 배치 1개, seed -1입니다. request.cpp는 음수 seed를 실제 값으로 바꾸므로 재현 실험에서는 seed를 명시해야 합니다.

4-3. 설계 패턴 ① 파사드와 불투명 핸들

include/stable-diffusion.h에는 내부 클래스 대신 sd_ctx_t 핸들이 노출됩니다. 실제 struct sd_ctx_t는 src/stable-diffusion.cpp에서 StableDiffusionGGML*을 보관합니다. 복잡한 내부 구현에 작은 사용 창구를 제공하는 파사드로 읽을 수 있습니다.

다음은 공개 API를 연결한 교육용 C++ 예시입니다. 이미지 인코딩·파일 저장은 생략하고, 반환 메모리의 소유권에 집중합니다.

#include "stable-diffusion.h"

bool generate_one(const char* model_path) {
    sd_ctx_params_t ctx_params;
    sd_ctx_params_init(&ctx_params);
    ctx_params.model_path = model_path;

    sd_ctx_t* ctx = new_sd_ctx(&ctx_params);
    if (ctx == nullptr) return false;

    sd_img_gen_params_t params;
    sd_img_gen_params_init(&params);
    params.prompt = "a small lighthouse by the sea";
    params.seed = 42;

    sd_image_t* images = nullptr;
    int count = 0;
    bool ok = generate_image(ctx, &params, &images, &count);
    // 필요한 픽셀 복사·저장은 메모리를 해제하기 전에 수행
    free_sd_images(images, count);
    free_sd_ctx(ctx);
    return ok;
}

generate_image()는 성공 여부를 bool로, 결과 포인터와 개수를 출력 인수로 전달합니다. 헤더 끝에는 호출자가 free_sd_images()로 결과를 해제해야 한다고 명시되어 있습니다. C API의 공부 포인트는 함수 이름보다 누가 메모리를 소유하는지입니다.

4-4. 설계 패턴 ② 모델 조합을 만드는 팩터리

src/pipeline/model_builders.cpp의 build_core_runners()는 모델 버전에 맞는 텍스트 조건기와 확산 실행기를 함께 만듭니다. SD3 경로는 SD3CLIPEmbedder와 MMDiTRunner를, Flux 경로는 조건에 맞는 인코더와 Flux::FluxRunner를 조합합니다.

이것을 팩터리 역할의 함수로 읽으면 모델을 추가할 위치가 보입니다. 파일을 읽는 코드와 신경망 클래스를 고르는 코드를 분리해, 하나의 로딩 함수에 모든 모델의 생성 절차를 넣지 않습니다. 다만 분기는 길기 때문에 새 모델이 늘어날수록 조합 조건의 검토 비용도 커집니다.

src/model_loader.cpp의 ModelLoader::parse_file()는 다른 책임을 맡습니다. 디렉터리·GGUF·safetensors 인덱스·safetensors·Torch ZIP·legacy 형식을 분기합니다. 파일 형식의 판별과 신경망 구조의 선택은 서로 다른 문제라는 점을 기억하세요.

4-5. 설계 패턴 ③ 바꿔 끼우는 계산 전략

src/model/diffusion/model.hpp의 DiffusionModelRunner는 compute(int n_threads, const DiffusionParams&)를 순수 가상 함수로 선언합니다. 호출자는 공통 인터페이스를 사용하고, 실제 계산은 각 모델 구현이 맡습니다. 이것은 같은 역할의 구현을 교체하는 전략 패턴 관점으로 이해할 수 있습니다.

src/runtime/denoiser.hpp에도 같은 사고방식이 보입니다. SigmaScheduler::get_sigmas()는 단계별 잡음 수준을 만드는 계약이고, DiscreteScheduler·ExponentialScheduler 등이 이를 구현합니다. 샘플링 쪽은 enum 분기로 sample_euler() 등 별도 함수를 고릅니다.

헷갈리기 쉬운 둘
스케줄러와 샘플러
스케줄러는 “어떤 잡음 수준을 차례로 방문할까”를 정합니다. 샘플러는 “현재 상태에서 다음 상태를 어떻게 계산할까”를 정합니다. 둘을 바꾸면 같은 단계 수·seed라도 결과가 달라질 수 있습니다.

4-6. 설계 패턴 ④ RAII로 실행 범위와 정리를 묶는다

src/pipeline/image.cpp의 ImageVaeAxesGuard는 생성자에서 원래 축 설정을 기억하고, 소멸자에서 복구합니다. 여러 실패 지점에서 일찍 반환하더라도 범위를 벗어날 때 복구됩니다. src/core/ggml_runner.cpp의 GGMLRunner::compute() 안에는 RunnerEndGuard와 GraphEndGuard도 있습니다.

이들은 실행 종료·작업 공간 정리·상태 복구를 함수의 성공 경로에만 맡기지 않습니다. examples/common/resource_owners.hpp의 SDCtxPtr는 std::unique_ptr와 전용 deleter로 같은 원리를 C API 핸들에 적용합니다.

추론 엔진을 읽을 때는 계산식과 함께, 중간에 실패해도 상태와 메모리가 제자리로 돌아오는 경로를 추적해야 합니다.

4-7. 메모리와 동시성: 계산 바깥의 핵심 설계

GGMLRunner는 단순한 모델 호출 포장지가 아닙니다. compute()가 그래프 실행의 수명을 관리하고, execute_segment()가 실제 장치 계산을 수행합니다. 스케줄러가 있으면 ggml_backend_sched_graph_compute()로, 없으면 sd_backend_graph_compute_with_eval_callback() 경로로 실행합니다.

전체 계산이 메모리에 들어갈 때
  [가중치 + 전체 그래프 작업 공간] ---> 한 번의 그래프 실행

메모리가 부족하고 그래프에 분할 지점이 있을 때
  [구간 1 가중치] ---> 계산 ---> [구간 2 가중치] ---> 계산
         필요한 동안 고정          다음 구간 전송·재사용

  보관 위치: CPU RAM / 장치 메모리 / disk
  계산 위치: 선택한 런타임 백엔드
  두 위치를 따로 정할 수 있다

--backend는 계산 위치, --params-backend는 가중치 보관 위치를 고릅니다. 예를 들어 GPU에서 계산하면서 CPU에 가중치를 보관할 수 있습니다. 분할 실행은 그래프 절단 지점·장치 지원·예산 조건을 따르며, 모델이 크면 무조건 실행된다는 보장은 아닙니다. src/core/segment_weight_pipeline.cpp와 src/model_manager_prefetch.cpp를 함께 읽으면 계산과 가중치 전송을 나누는 설계를 더 깊게 볼 수 있습니다.

서버에서도 HTTP 요청 수와 동시 추론 수는 구분됩니다. examples/server/routes_openai.cpp의 execute_sync_img_gen_request()는 sd_ctx_mutex를 잠근 뒤 생성합니다. async_jobs.cpp의 async_job_worker()는 조건 변수로 대기하다 큐에서 작업을 꺼냅니다.

접수 한도는 대기·생성 중 작업을 합쳐 64개이며, 완료·실패·취소 결과의 기본 보관 시간은 600초입니다. 이는 examples/server/async_jobs.h의 설정값입니다. 엔진의 ContextOperation도 실행 중 재진입을 거절하므로, “비동기 API가 있으니 한 컨텍스트로 무제한 병렬 생성 가능하다”고 해석하면 안 됩니다.

5디렉토리 구조 해부

파일 이름을 외우기보다 책임의 경계를 먼저 찾는다
stable-diffusion.cpp/
+-- CMakeLists.txt             라이브러리·백엔드·표준·설치 설정
+-- include/
|   +-- stable-diffusion.h     외부 프로그램이 사용하는 공개 C API
+-- src/
|   +-- stable-diffusion.cpp   C API 구현과 내부 엔진 연결
|   +-- model_loader*.cpp     파일 해석·텐서 목록·형식 변환
|   +-- model_manager*.cpp    가중치 관리·전송·prefetch
|   +-- pipeline/             이미지·영상 생성 절차와 모델 조합
|   +-- core/                 텐서·ggml 실행·장치·그래프·스레드
|   +-- model/
|   |   +-- diffusion/        UNet·DiT·Flux·Wan 등 생성 모델
|   |   +-- te/               CLIP·T5·LLM 계열 텍스트 인코더
|   |   +-- vae/              이미지·영상·오디오 복원 모듈
|   |   +-- adapter/          LoRA·IP-Adapter 등 확장
|   |   +-- common/           공통 블록·위치 표현
|   |   +-- detector/         객체 검출 모듈
|   |   +-- upscaler/         이미지 확대 모델
|   |   +-- audio/            오디오 인코더
|   +-- model_io/             GGUF·safetensors·Torch 형식별 읽기
|   +-- runtime/              샘플러·guidance·캐시·전처리
|   +-- tokenizers/           문자열을 토큰 ID로 바꾸는 구현
|   |   +-- vocab/            내장 어휘·병합 데이터
|   +-- conditioning/         프롬프트·참조 이미지 조건 구성
|   +-- extensions/           PhotoMaker·PuLID 등 생성 확장
+-- examples/
|   +-- cli/                  sd-cli 진입점
|   +-- server/               sd-server·라우트·작업 큐·모델 목록
|   |   +-- frontend/         별도 웹 UI 서브모듈
|   |   +-- recipes/          내장 모델 구성 JSON
|   +-- common/               인수 처리·로그·미디어·자원 소유권
+-- ggml/                     수정된 ggml 서브모듈
+-- thirdparty/               포함된 외부 라이브러리와 서브모듈
+-- docs/                     모델별·빌드·성능 안내
+-- cmake/                    ggml 연결·패키지 설정
+-- docker/                   장치별 이미지 빌드 정의
+-- scripts/                  변환·포맷 등 보조 도구
+-- .github/workflows/        빌드·릴리스 등 자동화

코드 규모를 숫자로 읽기

커밋 fd21ecf의 텍스트 파일을 개행 수로 집계한 값입니다. C/C++에는 .cpp·.h·.hpp 등을 함께 넣었으며, 빈 줄·주석도 포함합니다. 생성된 실행 코드만의 크기나 복잡도 점수는 아닙니다.

분류파일 수대략적인 줄 수
C/C++와 헤더227107,928줄
Python 보조 도구81,550줄
Shell 스크립트279줄
CMake 설정5597줄

집계에서 ggml/·thirdparty/·웹 UI 서브모듈·src/tokenizers/vocab/· 모델 파일·빌드 결과는 제외했습니다. 따라서 위 수치는 의존성을 모두 합친 전체 배포물의 크기가 아니라, 본체 코드 중심의 규모입니다. 프런트엔드 언어별 규모는 별도 웹 UI 저장소를 기준으로 집계해야 합니다.

특히 src/pipeline/diffusion_engine.cpp는 3,377줄, src/conditioning/conditioner.hpp는 3,922줄입니다. 큰 파일을 처음부터 끝까지 읽기보다 generate_image()에서 호출되는 이름을 따라 좁혀 읽으세요.

6학습 포인트 (기술별)

문법 지식이 실제 추론 시스템 설계로 이어지는 지점

6-1. C/C++: 경계 밖으로 나가는 메모리의 주인은 누구인가

sd_image_t*는 이미지 구조체 배열을 가리키며, 각 원소의 data 필드가 픽셀 메모리를 가리킵니다. 생성에 성공했다고 소유권 문제가 끝나는 것은 아닙니다. free_sd_images()는 각 이미지 데이터와 배열을 해제하고, SDCtxPtr 같은 소유자 타입은 컨텍스트 해제를 자동화합니다.

작은 실습

반환 경로마다 소유자 표시하기

examples/common/resource_owners.hpp에서 SDImageOwner와 SDImageVec를 찾고, 복사·이동·adopt·release가 소유권을 어떻게 바꾸는지 표로 그려 보세요. 포인터 값의 복사와 픽셀 데이터의 복사는 서로 다릅니다.

완료 기준: “어느 줄 이후에 누가 해제하는가”를 성공·실패 경로 각각에서 설명할 수 있습니다.

6-2. 생성 AI: 텍스트·잡음·조건의 역할 나누기

텍스트 인코더는 그림을 직접 그리지 않습니다. Conditioner::get_learned_condition()이 반환한 조건을 생성 모델이 사용합니다. src/runtime/guidance.cpp는 guidance 관련 인수 해석과 일정을 다루고, denoiser.hpp는 잡음 일정과 상태 갱신 알고리즘을 담습니다.

# 일반적인 CFG의 개념식 — 전체 구현을 대체하는 식은 아님
guided = uncond + scale * (cond - uncond)

# 일반적인 잠재 확산 경로의 역할 분리
prompt --> tokenizer --> text encoder --> condition
noise + condition --> 반복 상태 갱신 --> VAE --> pixels

여기서 cond와 uncond는 조건을 달리한 모델 예측을 뜻합니다. 모든 모델이 이 기본 CFG 경로를 그대로 쓰지는 않습니다. prepare_image_generation_embeds()에는 모델별 무조건부 조건 처리 분기가 실제로 있습니다.

실습 아이디어: 샘플러와 스케줄러를 고정한 채 CFG만 바꾸는 실험 계획을 작성하고, 이미지 변화와 계산 비용을 각각 어떤 지표로 기록할지 정해 보세요.

6-3. 텐서·GPU: 모양과 연속 메모리의 관계

배열보다 한 단계 넓은 개념
텐서의 shape와 layout
텐서는 다차원 숫자 배열입니다. shape는 각 축의 크기이고, layout은 실제 메모리에 배치하는 순서입니다. 이 저장소의 sd::Tensor는 0번 축이 가장 연속적인 낮은 차원이며, PyTorch의 축 순서를 그대로 대입하면 안 됩니다.

src/pipeline/image.cpp의 ensure_image_tensor_channels()는 4차원 이미지 텐서의 shape()[2]를 채널 수로 읽습니다. 같은 함수의 alpha 텐서는 {width, height, 1, batch} 모양으로 만듭니다. 이 실제 사용례로 축의 의미를 확인할 수 있습니다.

실습 아이디어: 폭 2·높이 3·RGB 채널 3·배치 1인 텐서를 종이에 그리고, 채널 축으로 이어 붙이는 연산과 폭 축으로 이어 붙이는 연산이 어떻게 다른지 설명해 보세요. src/core/tensor.hpp와 tensor_ggml.hpp를 이어 읽으면 자체 텐서와 ggml 사이의 경계가 보입니다.

6-4. 파일 형식·양자화: 숫자를 작게 저장하는 비용

src/model_loader.cpp의 convert_tensor()는 입력·출력 자료형이 같으면 복사하고, F32·F16·양자화 자료형 조합에 따라 다른 변환 경로를 탑니다. 파일 확장자와 내부 정밀도는 별개입니다. .gguf라고 해서 항상 4비트인 것은 아닙니다.

실습 아이디어: 동일한 가중치 개수에 대해 F32·F16·4비트의 이상적인 저장량을 계산하고, 블록별 보정값·정렬·미양자화 텐서 때문에 실제 크기가 다른 이유를 적어 보세요. 추론 전체 메모리가 그 비율대로 줄지 않는 이유도 함께 설명하면 좋습니다.

6-5. 동시성: 작업 큐와 공유 자원의 잠금 범위

async_job_worker()는 큐 잠금 안에서 작업을 꺼내고 상태를 바꾼 뒤, 잠금 범위를 벗어나 실제 생성을 실행합니다. 큐의 상태를 보호하는 mutex와 추론 컨텍스트를 보호하는 mutex는 역할이 다릅니다.

실습 아이디어: 요청 접수·큐 대기·생성 시작·완료·취소를 시간축에 표시하고, AsyncJobStatus의 상태 전이를 그리세요. “작업을 비동기로 접수한다”와 “같은 모델을 동시에 계산한다”가 왜 다른지 설명할 수 있어야 합니다.

6-6. 최신 커밋으로 배우는 멀티모달 입력 표현

커밋 fd21ecf의 주제는 LLM 입력에서 이미지마다 자리표시자 토큰 하나를 사용하는 정리입니다. src/conditioning/conditioner.hpp의 LLMEmbedder::expand_vision_marker()는 <|image_pad|> 위치를 찾고, 앞선 이미지가 실제로 차지하는 토큰 수를 더해 임베딩 시작 위치를 계산합니다.

// expand_vision_marker()의 위치 보정 핵심 발췌
int index = static_cast<int>(prefix_tokens.size());
for (const auto& image_embed : image_embeds) {
    index += static_cast<int>(image_embed.second.shape()[1]) - 1;
}

문자열에는 자리표시자가 하나여도, 실제 시각 특징은 여러 토큰 공간을 차지할 수 있습니다. src/model/te/llm.hpp의 그래프 구성도 이미지 임베딩의 길이에서 1을 뺀 만큼 전체 토큰 길이에 더합니다. 이는 문자열 위치·토큰 위치·임베딩 위치가 서로 다른 좌표계라는 좋은 사례입니다.

모델을 호출하는 법을 넘어서, 입력 표현과 실행 자원의 계약을 읽는 것이 이 저장소에서 얻을 수 있는 가장 큰 학습입니다.

7하드웨어 / 시스템 요구사항

실행 파일의 크기보다 모델과 계산 작업 공간이 중요하다

CPU만으로도 실행할 수 있지만, 실제 대기 시간과 메모리 요구량은 모델·해상도·단계 수·정밀도에 따라 달라집니다. Linux·macOS·Windows 지원은 README 기준이며, Android는 Termux와 관련 앱 경로가 안내됩니다. 장치 백엔드가 존재한다는 사실은 모든 GPU에서 같은 기능과 속도를 보장한다는 뜻이 아닙니다.

환경필요한 구성확인할 경계
CPUC/C++ 툴체인·CMake·ggml 소스GPU 없이 추론 가능. 가중치와 중간 계산을 담을 RAM이 필요
NVIDIACUDA 툴킷과 호환 드라이버, SD_CUDA=ON빌드 문서는 VRAM 4GB 이상을 권장하지만 모든 모델의 최소 사양은 아님
AMDROCm/HIP 환경, SD_HIPBLAS=ON운영체제·GPU 아키텍처·툴킷 조합별 지원 확인
Apple GPUMetal 빌드 환경, SD_METAL=ON통합 메모리는 운영체제·다른 앱과 공유. 큰 행렬의 성능 주의는 빌드 문서 기준
VulkanVulkan 개발 도구·드라이버, SD_VULKAN=ON연산·정밀도·장치별 경로를 따로 확인
선택적 백엔드SYCL·OpenCL·MUSA 등OpenCL은 빌드 문서에서 Adreno 중심으로 안내. MUSA 검증 예시는 SDK 5.2.0
서버 웹 화면 제작프런트엔드 서브모듈·Node·pnpmDocker·CI의 기준은 Node 20 / pnpm 10.15.1
디스크모델 구성요소와 변환 결과 저장 공간텍스트 인코더·VAE가 별도 파일인 모델은 모두 합산

공식 문서의 메모리 수치는 범위를 붙여 읽는다

docs/quantization_and_gguf.md는 SD 1.x, txt2img, 512×512에 대해 다음 근삿값을 제시합니다. 측정 장치·전체 소프트웨어 조건이 충분히 명시된 비교 벤치마크는 아니므로, 현재 환경의 보장값이나 대형 모델의 사양으로 쓰면 안 됩니다.

정밀도문서 표의 메모리 표기Flash Attention 사용 시 문서 표기
F32약 2.8G약 2.4G
F16약 2.3G약 1.9G
Q8_0약 2.1G약 1.6G
Q4_0약 2.0G약 1.5G

원문은 단위를 G로 표기합니다. 특히 F32에서 Q4로 바꿔도 전체 메모리가 8분의 1이 되지 않는다는 점에 주목하세요. 중간 텐서·텍스트 인코더·VAE·캐시 등은 가중치 비트 수와 다른 요인으로 크기가 정해집니다.

메모리 계산의 비유

가중치는 요리 재료이고 계산 작업 공간은 조리대입니다. 재료를 압축 포장해도 조리대를 없앨 수는 없습니다. VAE 타일링은 큰 요리를 여러 구역으로 나눠 조리하는 방법이고, CPU로 가중치를 내리는 방식은 재료를 창고에서 가져오는 대신 이동 비용을 지불하는 방법입니다.

# 개념적인 예산 분해 — 모든 값이 동시에 최대가 되는 것은 아님
총 메모리 요구량 ≈ 상주 가중치 + 계산 작업 공간 + 캐시
                  + 입출력 버퍼 + 드라이버·운영체제 여유분

# 가중치만의 이상적인 계산 예시
10억 개 × 2바이트(F16) = 20억 바이트 ≈ 1.86 GiB
10억 개 × 0.5바이트(4비트) ≈ 0.47 GiB
# 실제 양자화에는 블록 보정값·정렬 등의 추가 공간이 필요

모델 파일이 VRAM보다 작다는 사실만으로 생성 가능 여부를 판단할 수는 없으며, 중간 계산과 전송에 필요한 여유 공간까지 봐야 합니다.

--max-vram은 관리 대상 가중치·작업 공간·캐시의 장치별 예산입니다. docs/backend.md는 드라이버나 관리 범위 밖 할당을 제외하므로 물리적인 절대 상한이 아니라고 설명합니다. GGMLRunner::execute_graph()의 계획 여유분은 128 MiB이며, 실제 적합성 판단에는 장치 여유 메모리와 다른 실행기의 상주 자원도 영향을 줍니다.

8직접 해볼 수 있는 실습 과제

입문에서 고급까지, 관찰할 변수와 완료 기준을 함께 정한다

명령은 저장소 루트와 그 아래 models/를 기준으로 쓴 예시입니다. 실제 모델은 해당 모델 문서의 파일 구성·이용 조건을 확인해 준비하세요. 처음에는 구성요소가 단순한 SD 1.5 계열로 시작하고, 큰 영상 모델은 뒤로 미루는 편이 학습 범위를 줄여 줍니다.

과제 1 · 입문

실행하지 않고 요청의 길 찾기

include/stable-diffusion.h에서 generate_image() 선언을 찾은 뒤, 구현·파이프라인·샘플링·결과 복원까지 호출 지도를 만드세요.

완료 기준: 함수 6개 이상을 파일 경로와 연결하고, 입력·출력·실패 표시를 한 줄씩 적습니다. bool 반환과 이미지 포인터 출력이 왜 분리되어 있는지도 설명합니다.

rg -n 'generate_image|new_sd_ctx|free_sd_images' include src examples
rg -n 'prepare_image_generation|decode_image_outputs' src/pipeline/image.cpp
rg -n 'execute_segment|execute_graph' src/core/ggml_runner.cpp
과제 2 · 입문

한 장을 만들고 재현 조건 기록하기

재귀 서브모듈이 준비된 소스와 C++ 툴체인에서 CLI를 빌드하거나 공식 릴리스의 실행 파일을 사용합니다. 아래는 웹 UI와 WebP·WebM을 제외한 CPU CLI 빌드 예시입니다.

완료 기준: 출력 이미지와 함께 커밋·실행 파일 버전·가중치 파일명·seed·정밀도· 샘플러·스케줄러·해상도·백엔드를 기록합니다. 같은 seed만으로 모든 환경의 픽셀이 같다고 가정하지 않습니다.

cmake -S . -B build-study -DCMAKE_BUILD_TYPE=Release \
  -DSD_SERVER_BUILD_FRONTEND=OFF -DSD_WEBP=OFF -DSD_WEBM=OFF
cmake --build build-study --config Release --target sd-cli

./build-study/bin/sd-cli \
  -m models/v1-5-pruned-emaonly.safetensors \
  -p "a small lighthouse by the sea" \
  --width 512 --height 512 --steps 20 --seed 42 \
  --sampling-method euler --cfg-scale 7 \
  --backend cpu --rng cpu -o lighthouse.png

위 실행 파일 경로는 단일 구성 빌드의 예시입니다. Windows의 다중 구성 생성기에서는 Release 하위 디렉터리와 .exe 확장자를 확인하세요. CUDA 빌드를 원하면 해당 툴킷을 준비하고 별도 빌드 디렉터리에서 -DSD_CUDA=ON을 사용합니다.

과제 3 · 중급

타일링의 메모리 절약과 추가 계산 비교하기

모델·seed·해상도·정밀도를 고정하고 기본 실행과 아래 옵션을 추가한 실행을 비교합니다. 문서상 타일 크기는 잠재 좌표가 아닌 이미지 픽셀 단위입니다.

완료 기준: 첫 로딩 시간과 생성 시간을 나눠 기록하고, VAE 복원 구간의 메모리·시간·경계 품질 변화를 비교합니다. VAE 타일링이 확산 모델 전체의 메모리도 같은 비율로 줄인다고 결론 내리지 않습니다.

# 과제 2의 생성 명령에 추가할 옵션
--vae-tiling --vae-tile-size 256x256 --vae-tile-overlap 0.5

docs/performance.md 기준으로 512×512 입력·256픽셀 타일·50% 겹침은 3×3 타일입니다. 겹치는 영역을 다시 계산하므로 메모리를 줄이는 대신 시간이 늘 수 있습니다. 실제 타일 규칙은 src/runtime/tiling.cpp와 src/model/vae/vae.hpp를 연결해 읽어 보세요.

과제 4 · 중급

C API 예제를 자원 소유자 타입으로 바꾸기

4장의 generate_one()을 독립적인 학습용 프로그램으로 옮기고, examples/common/resource_owners.hpp의 설계를 참고해 컨텍스트·이미지 배열을 자동 정리하도록 바꿉니다.

완료 기준: 모델 초기화 실패·생성 실패·성공 후 조기 반환의 세 경로에서 해제 책임이 남지 않도록 합니다. 결과 메모리가 해제된 뒤에는 픽셀 포인터를 사용하지 않습니다.

과제 5 · 고급

가중치 보관 위치와 계산 위치를 분리해 관찰하기

지원되는 GPU 빌드에서 동일한 모델을 사용하고, 기본 배치와 CPU 가중치 보관을 비교합니다. src/core/ggml_runner.cpp의 그래프 분할 판단과 src/model_manager_prefetch.cpp의 전송 경로를 연결하세요.

완료 기준: peak compute buffer·전체 장치 메모리·RAM·실행 시간을 구분해 표로 남깁니다. 메모리 부족이 나면 어떤 자원에서 실패했는지 기록하고, 무조건 예산을 키우는 대신 원인을 분류합니다.

# 같은 생성 인수에 다음 장치 배치 옵션을 사용
--backend cuda0 --params-backend cpu --max-vram -1
# 지원 장치 이름은 sd-cli --list-devices로 확인

실습의 성공 기준은 이미지 한 장이 나왔다는 사실보다, 바꾼 조건과 관찰한 결과를 소스의 어느 경로로 설명할 수 있느냐에 있습니다.

9관련 기술 심화 학습 로드맵

6주 동안 한 장의 이미지에서 시스템 전체로 범위를 넓힌다

C++ 기초 문법을 막 배웠다면 매주 한 가지 질문에 답하는 방식으로 접근하세요. 수학·GPU·웹 서버를 동시에 끝내려 하기보다, 이번 주의 설명이 다음 주의 파일을 읽는 발판이 되도록 구성합니다.

주차배울 개념과 읽을 코드남길 결과물
1주차C API, 포인터, 구조체, 소유권.
include/stable-diffusion.h와 examples/common/resource_owners.hpp
컨텍스트·이미지의 생성/해제 책임표와 호출 지도
2주차토큰화·조건 벡터·잠재 표현.
src/tokenizers/tokenizer.h, src/conditioning/conditioner.hpp, src/pipeline/image.cpp
텍스트·참조 이미지가 숫자 입력으로 바뀌는 과정 설명
3주차스케줄러·샘플러·CFG.
src/runtime/denoiser.hpp, src/runtime/guidance.cpp, src/pipeline/request.cpp
seed·단계 수·CFG 중 한 변수씩 바꾼 비교표
4주차텐서 layout·그래프·메모리 생명주기.
src/core/tensor.hpp, src/core/ggml_runner.cpp, src/core/compute_workspace.cpp
하나의 그래프가 예약·계산·정리되는 순서도
5주차양자화·가중치 보관·분할 실행.
src/model_loader.cpp, src/device_residency_manager.h, src/model_manager_prefetch.cpp
가중치·작업 공간·캐시를 구분한 메모리 분석
6주차HTTP 요청·작업 큐·상태 전이·빌드.
examples/server/async_jobs.cpp, examples/server/routes_openai.cpp, CMakeLists.txt
취소·오류·완료를 포함하는 작은 서비스 설계서

매주 결과물에는 “코드에서 확인한 사실”과 “아직 설명하지 못한 부분”을 나눠 적으세요. 설명하지 못한 부분이 다음 탐색의 구체적인 질문이 됩니다.

기초 지식이 부족할 때
돌아갈 개념을 작은 단위로 정한다

포인터와 참조가 헷갈리면 1주차를 두 주로 나누세요. 행렬 연산이 낯설면 2주차에서 shape·행렬 곱·정규화만 먼저 익히면 됩니다. CUDA 커널을 직접 작성하기 전에도 API 경계와 메모리 흐름은 충분히 분석할 수 있습니다.

매주 읽은 코드를 입력·출력·소유권·실패 처리의 네 문장으로 설명할 수 있으면, 큰 저장소를 스스로 탐색할 기반이 생깁니다.

10핵심 키워드 사전

정의 하나마다 이 저장소에서 관찰할 대상을 붙인다
용어쉬운 설명
추론학습된 가중치로 결과를 계산하는 과정. 이 프로젝트의 주된 목적
체크포인트학습된 가중치 등을 저장한 파일. 확장자만으로 모든 내부 구성을 알 수는 없음
텐서여러 축을 가진 숫자 배열. 이미지·문장 특징·모델 가중치의 공통 표현
shape / layout축별 크기와 실제 메모리 배치. 이 레포에서는 낮은 인덱스 축이 더 연속적
토크나이저문자열을 모델이 아는 토큰 ID 배열로 바꾸는 도구
텍스트 인코더토큰 ID를 문맥을 반영한 숫자 특징으로 바꾸는 모델
conditioning생성 방향을 정하는 조건 입력. 텍스트뿐 아니라 참조 이미지 등도 포함
잠재 표현픽셀을 직접 다루는 대신 사용하는 내부 숫자 표현. 일반적인 잠재 확산에서 VAE와 연결
VAE이미지와 잠재 표현 사이를 오가는 오토인코더 계열. 생성 마지막의 복원에 사용
UNet / DiT대표적인 생성 모델 구조. 공간 해상도를 오가는 망과 Transformer 기반 망의 차이
샘플러모델 예측을 이용해 현재 상태에서 다음 상태를 계산하는 알고리즘
sigma / 스케줄러잡음 수준을 나타내는 값과 그 값을 어떤 순서로 사용할지 정하는 규칙
CFG조건을 달리한 모델 예측의 차이를 이용해 생성 방향을 조절하는 방식
seed / RNG난수의 시작 조건과 난수를 만드는 알고리즘. 재현 조건의 일부
ggml텐서 계산과 장치 백엔드를 제공하는 기반 라이브러리. 이 레포는 기본적으로 수정된 포크 사용
백엔드계산을 실제 CPU·GPU 장치에서 수행하는 구현
계산 그래프텐서와 연산의 의존 관계. 사용자 화면에서 잇는 작업 노드와는 계층이 다름
작업 공간모델 가중치 외에 중간 계산을 수행하기 위해 확보하는 메모리
양자화숫자를 더 적은 비트로 표현하는 방법. 공간 절약과 오차·지원 연산을 함께 고려
GGUF / safetensors텐서와 관련 정보를 저장하는 파일 형식. 확장자와 정밀도는 별개
LoRA기본 모델에 비교적 작은 추가 가중치를 적용하는 적응 기법
Flash Attention어텐션 계산의 메모리 접근·중간 저장을 개선하는 구현 방식. 효과는 장치·모양에 의존
VAE 타일링이미지 영역을 겹치는 조각으로 나눠 VAE를 실행하는 방법
offload / prefetch가중치를 다른 메모리에 두거나, 다음 계산에 필요한 가중치를 미리 가져오는 전략
RAII객체의 생성·소멸과 자원의 확보·반납을 묶어 조기 반환에도 정리를 보장하는 C++ 기법
불투명 핸들내부 구조를 숨긴 채 API로만 다루게 하는 참조. 여기서는 sd_ctx_t
mutex / 조건 변수공유 자원의 접근을 보호하는 잠금과, 작업이 생길 때까지 기다리는 동기화 도구

11참고 링크

움직이는 최신 문서와 커밋에 고정된 코드 근거를 구분한다

공식 저장소·빌드·모델 문서

본문의 핵심 코드 근거

관련 기술과 비교 대상

현재 상태 (2026-10-23 확인)

항목내용
선정GitHub Trending C++ Monthly #1 · 분석일 2026-10-23
스타 / 포크7,764 / 890 · 2026-10-23 GitHub 기준
주 언어C++
생성일2023-08-13
최근 push2026-10-22 · GitHub 날짜 기준
최신 릴리스master-995-fd21ecf · 2026-10-22
최근 커밋fd21ecf · 2026-10-23 +0800 · LLM 입력에 이미지당 자리표시자 토큰 하나를 사용하도록 정리 (#2191)
C/C++ 코드 규모227파일 / 107,928줄 · 주석·빈 줄 포함, 외부 코드·어휘 데이터·서브모듈 제외
기타 코드Python 1,550줄 / Shell 79줄 / CMake 597줄 · 같은 제외 기준
라이선스MIT · 외부 라이브러리와 모델 이용 조건은 각각 확인

커밋 시각은 2026-10-23 00:45:33 +0800으로, UTC로 바꾸면 2026-10-22 16:45:33입니다. 최근 push·릴리스의 날짜와 커밋 날짜가 하루 달라 보일 수 있으므로 시간대를 함께 읽으세요. 프로젝트 소개 문구는 SD·Flux·Wan·Qwen Image·Z-Image 등을 C/C++로 추론하는 프로젝트라는 뜻입니다.

활용 전에 알아둘 한계
커밋에 고정된 분석과 실제 장치의 결과는 구분해야 한다

API와 CLI 옵션은 활발한 개발로 바뀔 수 있습니다. 본문의 함수·기본값·경로는 커밋 fd21ecf 기준입니다. 최신 브랜치에서 같은 이름과 동작이 유지되는지는 해당 버전 문서를 확인하세요.

메모리 표는 공식 문서의 특정 SD 1.x 조건에 대한 근삿값이며, 다른 모델·드라이버·백엔드의 최소 사양이나 생성 속도를 보증하지 않습니다. 속도 비교에는 같은 모델·설정·하드웨어에서 측정한 결과가 필요합니다.

프런트엔드 패키지의 세부 버전은 본체 소스의 서브모듈 포인터만으로 확인할 수 없습니다. 코드 규모도 외부 코드·내장 어휘·서브모듈을 뺀 범위이므로 전체 제품 크기와 같지 않습니다.

MIT는 이 엔진의 코드 라이선스입니다. 가중치·추가 어댑터·외부 라이브러리의 조건을 대신하지 않으며, 지원 모델 목록이 모든 기능과 하드웨어 조합의 검증을 뜻하지도 않습니다.