comfyanonymous/ComfyUI
Sampling pipeline
What happens when you click Queue Prompt on a workflow that ends in KSampler. This page covers the journey from a checkpoint and a text prompt to a finished latent.
Purpose
The sampling pipeline takes a model, conditioning, a noise schedule, and an initial latent and runs an iterative denoising loop, optionally with classifier-free guidance, ControlNet, hooks, and per-area conditioning.
Layout
comfy/
├── samplers.py # The high-level sampling loop, CFG, sampling_function
├── sample.py # Convenience wrappers used by KSampler nodes
├── sampler_helpers.py # Conditioning preprocessing, mask sizing, area packing
├── model_sampling.py # ModelSamplingDiscrete, FlowMatch, EDM (continuous-time formulations)
├── k_diffusion/
│ ├── sampling.py # k-diffusion samplers (Euler, DPM++, Heun, …)
│ ├── deis.py # DEIS sampler
│ ├── sa_solver.py # SA solver
│ └── utils.py
└── extra_samplers/
└── uni_pc.py # UniPC + restart variantsKey abstractions
| Type / function | File | What it does |
|---|---|---|
KSampler |
comfy/samplers.py |
High-level wrapper used by KSampler and KSamplerAdvanced nodes |
sampling_function |
comfy/samplers.py |
The CFG-aware noise prediction call |
KSAMPLER |
comfy/samplers.py |
Functional wrapper around a k-diffusion sampler |
ModelSamplingDiscrete, ModelSamplingFlowMatch, … |
comfy/model_sampling.py |
Architecture-specific sampling math (eps/v/x0 prediction, schedules) |
sample_euler, sample_dpmpp_2m_sde_gpu, … |
comfy/k_diffusion/sampling.py |
One function per sampler |
sample_uni_pc_bh1, sample_restart |
comfy/extra_samplers/uni_pc.py |
Extra samplers |
prepare_noise, prepare_sampling |
comfy/sample.py |
Latent + conditioning preparation done by KSampler nodes |
pre_run_control, apply_empty_x_as_equal_area |
comfy/sampler_helpers.py |
Conds normalization and ControlNet pre-run |
Guider, CFGGuider |
comfy/samplers.py |
The "guidance object" used by the Custom Sampler family |
How a KSampler call flows
sequenceDiagram
autonumber
participant Node as KSampler node
participant Smp as comfy.sample.sample
participant Help as sampler_helpers
participant Model as ModelPatcher.model
participant KD as k_diffusion sampler
participant CFG as sampling_function
participant CN as ControlNet (if any)
participant Hook as Hooks (if any)
Node->>Smp: sample(model, noise, steps, cfg, sampler, scheduler, positive, negative, latent)
Smp->>Help: pre_run_control + prepare_noise
Smp->>Model: load_model_gpu via ModelPatcher
Smp->>KD: sampler_callable(noise, sigmas, denoise_callback)
loop each timestep
KD->>CFG: predict_noise(x, sigma, conds)
CFG->>Model: apply_model(x, t, c_concat=..., c_crossattn=...)
Model-->>CFG: noise prediction
CFG-->>KD: combined cond/uncond
KD->>KD: step from sigma_i to sigma_{i+1}
KD-->>Smp: progress callback (preview, percent)
opt
CN->>Model: residuals
end
opt
Hook->>Model: apply / unapply hooks
end
end
Smp-->>Node: sampled latentThe sampling_function is the heart of CFG: it batches conditional and unconditional noise predictions into one model call when memory allows, then mixes them by cfg_scale (with various interpolation modes for newer guidance methods).
Schedules
Schedules turn a step count into a list of sigmas:
| Scheduler | Where |
|---|---|
karras |
comfy/k_diffusion/sampling.py:get_sigmas_karras |
exponential |
comfy/k_diffusion/sampling.py |
simple, ddim_uniform, sgm_uniform, beta |
comfy/samplers.py |
linear_quadratic, kl_optimal |
comfy/samplers.py |
normal |
the model's model_sampling schedule |
The complete list of sampler names is the SAMPLER_NAMES and SCHEDULER_NAMES arrays at the top of comfy/samplers.py — those are what populate the dropdowns in the KSampler node.
Custom Sampler decomposition
The Custom Sampler family in comfy_extras/nodes_custom_sampler.py breaks the K-Sampler into reusable pieces:
BasicScheduler/KarrasScheduler/ … — produceSIGMAS(1D tensor)KSamplerSelect— produce aSAMPLER(function reference)BasicGuider/CFGGuider/ … — produce aGUIDER(something withpredict_noise)RandomNoise— produceNOISESamplerCustom— combine the above into a finished latent
This is graph-level composability: you can swap a different scheduler in without touching the sampling loop. The shared interface for GUIDER is in comfy/samplers.py.
Per-area conditioning, masks, hooks
sampler_helpers.py and samplers.py together support:
- Area — apply a conditioning to a sub-region of the latent.
- Mask — apply a soft mask to a conditioning (e.g., for inpainting + prompt blending).
- Strength scaling — boost or attenuate a conditioning's effect.
- Timestep range —
timestep_start/timestep_endinsidecondonly applies for specific timesteps. - Hooks — see LoRA and hooks. Hooks can scope LoRA application or attention modifications to specific timesteps and conditioning paths.
ControlNet integration
A cond dict can carry control — a ControlBase (from comfy/controlnet.py) that's woken up during apply_model to inject residuals into the unet. ControlNet weights live in their own ModelPatcher so they participate in the same VRAM accounting as the main model.
Latent format normalization
Different architectures use different latent statistics. comfy/latent_formats.py registers per-architecture means/stds so previewers (and any cross-model nodes) can convert latents to a normalized space. Every BaseModel subclass declares its latent_format.
Integration points
- Called by
KSampler*nodes innodes.pyand Custom Sampler nodes incomfy_extras/nodes_custom_sampler.py. - Reads from Conditioning and CLIP for the
condlists. - Calls into Model management for
load_model_gpuand offload. - Optionally invokes LoRA and hooks per timestep.
- Pushes preview frames through
latent_preview.py→WebUIProgressHandler.
Where to start a change
- New k-diffusion sampler: add to
comfy/k_diffusion/sampling.py; register the name incomfy.samplers.SAMPLER_NAMES. - New scheduler: add to
comfy/samplers.py'scalculate_sigmasand theSCHEDULER_NAMESlist. - New CFG variant: study
sampling_functionincomfy/samplers.py. Many existing variants are nodes that wrapsampling_functionwith a custom callback (e.g., PAG/SAG incomfy_extras/).
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.