TL;DR: A sampler is the algorithm that turns noise into an image; a scheduler is the separate setting that decides the noise levels it steps through. ComfyUI and current AUTOMATIC1111 both expose them as two independent controls, even though old saved-image metadata still writes them as one combined string like "DPM++ 2M Karras." This reference cross-names every sampler across AUTOMATIC1111, ComfyUI and diffusers, and is honest about what nobody has actually benchmarked.
What does a sampler actually do?
A sampler is the numerical solver that walks a noisy latent back toward a clean image. On every step it asks the model to predict what the noise looks like, then moves the latent partway toward removing it. Different samplers take that partial step differently, and that difference is the whole reason "which sampler" is a real question.
ComfyUI's own KSampler node states the job in two separate tooltips, one per widget:
# nodes.py, class KSampler INPUT_TYPES
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, {"tooltip": "The algorithm used when sampling, this can affect the quality, speed, and style of the generated output."}),
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"tooltip": "The scheduler controls how noise is gradually removed to form the image."}),
Two widgets, two jobs. sampler_name picks the solving algorithm. scheduler picks the ladder of noise levels that algorithm walks down. Confusing the two, or worse, treating them as a single named setting, is the single most common error in every "best sampler" article on this keyword.
Is the scheduler the same thing as the sampler?
No, and the three major tools do not even agree on what to call the second half.
ComfyUI keeps the split clean at the code level. comfy/samplers.py defines SAMPLER_NAMES (45 entries as of a live fetch on September 3, 2026) and SCHEDULER_NAMES (9 entries) as two independent lists, and the KSampler node exposes them as two independent dropdown widgets.
AUTOMATIC1111 also keeps them structurally separate: a Sampling method dropdown backed by modules/sd_samplers.py, and a "Schedule type" dropdown backed by modules/sd_schedulers.py. That second name is a literal string in the source, used as an infotext key (d.get("Schedule type")). Where it gets confusing is generation metadata, covered next.
diffusers is the outlier, and it overloads the word "scheduler" to mean something else entirely. In Hugging Face's own words, from the schedulers overview doc:
"A scheduler takes a model's output (the sample which the diffusion process is iterating on) and a timestep to return a denoised sample."
That is diffusers' definition of the whole sampling algorithm, the thing ComfyUI calls a sampler. The noise-schedule choice that ComfyUI and AUTOMATIC1111 call "scheduler" is, in diffusers, just a keyword argument on that same class, most often use_karras_sigmas=True. Carrying the word "scheduler" from one tool's docs into another's UI will point you at the wrong control.
Sampler names across AUTOMATIC1111, ComfyUI and diffusers
The same algorithm gets a different string in every tool. This table cross-references the names, built from a live fetch of sd_samplers_kdiffusion.py (AUTOMATIC1111), comfy/samplers.py (ComfyUI) and the diffusers schedulers overview doc, all on September 3, 2026.
| AUTOMATIC1111 label | ComfyUI internal name | diffusers class |
|---|---|---|
| Euler | euler | EulerDiscreteScheduler |
| Euler a | euler_ancestral | EulerAncestralDiscreteScheduler |
| Heun | heun | HeunDiscreteScheduler |
| LMS | lms | LMSDiscreteScheduler |
| DPM2 | dpm_2 | KDPM2DiscreteScheduler |
| DPM2 a | dpm_2_ancestral | KDPM2AncestralDiscreteScheduler |
| DPM++ 2S a | dpmpp_2s_ancestral | not listed in the table; described as "very similar to" DPMSolverSinglestepScheduler |
| DPM++ SDE | dpmpp_sde | DPMSolverSinglestepScheduler |
| DPM++ 2M | dpmpp_2m | DPMSolverMultistepScheduler |
| DPM++ 2M SDE | dpmpp_2m_sde | DPMSolverMultistepScheduler with algorithm_type="sde-dpmsolver++" |
| DPM++ 3M SDE | dpmpp_3m_sde | not in the table |
| DPM fast | dpm_fast | not in the table |
| DPM adaptive | dpm_adaptive | not in the table |
| Restart | not a ComfyUI KSampler entry (separate node) | not in the table |
| DDIM | ddim | DDIMScheduler |
| UniPC | uni_pc / uni_pc_bh2 | UniPCMultistepScheduler |
| PLMS | no ComfyUI equivalent found | not in the table |
| LCM | lcm | not in the table |
| not in AUTOMATIC1111's k-diffusion list | ipndm, deis, res_multistep, gradient_estimation, er_sde, sa_solver and their _cfg_pp variants | DEISMultistepScheduler covers deis |
Some of ComfyUI's 45 sampler entries are not distinct algorithms. sample_dpmpp_2m_sde and sample_dpmpp_2m_sde_gpu differ, in ComfyUI's own source, by one keyword argument on the same BrownianTreeNoiseSampler call: cpu=True versus cpu=False. Same solver, different device for the noise generator. The _cfg_pp variants are a similar story: a classifier-free-guidance handling change on the same underlying step, not a new solver.
Why does old metadata write "DPM++ 2M Karras" as one name?
Because that is literally how AUTOMATIC1111 saves it, and its own code has to undo that concatenation to read the settings back. modules/sd_samplers.py defines a function whose entire job is name-splitting:
@functools.cache
def get_sampler_and_scheduler(sampler_name, scheduler_name, *, convert_automatic=True):
default_sampler = samplers[0]
found_scheduler = sd_schedulers.schedulers_map.get(scheduler_name, sd_schedulers.schedulers[0])
name = sampler_name or default_sampler.name
for scheduler in sd_schedulers.schedulers:
name_options = [scheduler.label, scheduler.name, *(scheduler.aliases or [])]
for name_option in name_options:
if name.endswith(" " + name_option):
found_scheduler = scheduler
name = name[0:-(len(name_option) + 1)]
break
...
It walks every known schedule-type label, checks whether the sampler string ends with that label plus a space, and if so, chops it off and treats the remainder as the sampler and the suffix as the schedule. That function exists because a saved image's "Sampler" field can read DPM++ 2M Karras, and the two pieces need pulling apart before the UI can populate two separate dropdowns from it. Diffusers' own mapping table documents the same pairing from the other direction, listing "DPM++ 2M Karras" against DPMSolverMultistepScheduler, "init with use_karras_sigmas=True" as a separate note, not a separate class.
Each entry in AUTOMATIC1111's sampler list also carries its own default schedule, applied only when "Schedule type" is left on Automatic. DPM++ 2M defaults to karras; DPM++ 2M SDE defaults to exponential; plain Euler and Heun carry no default at all and fall back to whatever "Automatic" resolves to for that model. Picking "DPM++ 2M" from the sampler dropdown with Schedule type on Automatic reproduces the old combined string's behavior; picking a different schedule type overrides it.
Which samplers evaluate the model more than once per step?
Heun, DPM2, DPM2 a, and the DPM++ variants with 2S, 2M or 3M in the name. This is visible directly in ComfyUI's step loop. sample_euler calls the model once per step:
denoised = model(x, sigma_hat * s_in, **extra_args)
d = to_d(x, sigma_hat, denoised)
x = x + d * dt
sample_heun's own docstring reads "Implements Algorithm 2 (Heun steps) from Karras et al. (2022)." It calls the model a second time on every step but the last:
denoised = model(x, sigma_hat * s_in, **extra_args)
d = to_d(x, sigma_hat, denoised)
dt = sigmas[i + 1] - sigma_hat
if sigmas[i + 1] == 0:
x = x + d * dt # Euler method, final step only
else:
x_2 = x + d * dt
denoised_2 = model(x_2, sigmas[i + 1] * s_in, **extra_args) # second evaluation
d_2 = to_d(x_2, sigmas[i + 1], denoised_2)
x = x + (d + d_2) / 2 * dt
Twenty Heun steps therefore cost close to forty model evaluations, not twenty. sample_dpmpp_2m, labeled in its own docstring simply "DPM-Solver++(2M)," reuses the previous step's already-computed prediction instead of taking a second evaluation on the current one, which is how multistep DPM-Solver++ variants get second-order accuracy at first-order cost. Compare model evaluations between samplers, not step counts.
Are ancestral samplers just noisier versions of the deterministic ones?
They follow a genuinely different path, not the same path with grain added on top. sample_euler_ancestral computes a sigma_up value at every step via get_ancestral_step, then adds that much freshly generated noise back into the latent through a noise_sampler call, on top of the deterministic Euler move:
d = to_d(x, sigmas[i], denoised)
dt = sigma_down - sigmas[i]
x = x + d * dt + noise_sampler(sigmas[i], sigmas[i + 1]) * s_noise * sigma_up
That injected noise means an ancestral sampler's trajectory keeps re-randomizing itself at every step, which is why two runs on the same seed and prompt do not settle toward the same image the way two deterministic-sampler runs tend to. It also means what a seed can and cannot guarantee matters more on an ancestral sampler than on a deterministic one.
Where does the Karras schedule come from, and does every tool implement it the same way?
It comes from a specific paper, and the implementations agree on the source even when their code differs. Tero Karras, Miika Aittala, Timo Aila and Samuli Laine published "Elucidating the Design Space of Diffusion-Based Generative Models" in 2022, reporting new state-of-the-art image quality "with much faster sampling (35 network evaluations per image) than prior designs." ComfyUI's own implementation credits it directly in a one-line docstring:
def get_sigmas_karras(n, sigma_min, sigma_max, rho=7., device='cpu'):
"""Constructs the noise schedule of Karras et al. (2022)."""
Karras is one scheduler among several, not a synonym for "good settings." ComfyUI ships nine scheduler handlers as of this fetch: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, normal, linear_quadratic, and kl_optimal. AUTOMATIC1111 ships eleven named schedule types plus an "Automatic" default: Uniform, Karras, Exponential, Polyexponential, SGM Uniform, KL Optimal, Align Your Steps, Simple, Normal, DDIM, and Beta.
Where does the "discard the last sigma" quirk come from?
From a mismatch between how some solvers count steps and how the noise ladder is built, and both major tools patch it, in slightly different places. ComfyUI's KSampler class keeps a named set for it:
DISCARD_PENULTIMATE_SIGMA_SAMPLERS = set(('dpm_2', 'dpm_2_ancestral', 'uni_pc', 'uni_pc_bh2'))
For any sampler in that set, ComfyUI silently asks the scheduler for one extra sigma, then drops the second-to-last value before sampling starts. Ask for 20 steps on dpm_2, and 21 get scheduled internally.
AUTOMATIC1111 solves the same class of problem with a per-sampler discard_next_to_last_sigma flag in its own sampler table, and its flagged list is not identical: DPM2, DPM2 a, and DPM++ 3M SDE all carry 'discard_next_to_last_sigma': True, but AUTOMATIC1111's UniPC entry (in a separate file, sd_samplers_timesteps.py) carries no such flag at all. The two tools agree that dpm_2 and dpm_2_ancestral need the correction and disagree on whether uni_pc and DPM++ 3M SDE do. Read this as a genuine cross-tool discrepancy in this specific fetch, not as one tool being wrong; UniPC's timestep handling in AUTOMATIC1111 goes through a different code path (sd_samplers_timesteps.py) than ComfyUI's k-diffusion-style sigma ladder, so the two are not strictly comparable implementations of "the same fix."
Is one sampler actually better than another?
Mostly, that claim is community consensus dressed up as a fact, and this article will not pretend otherwise. No vendor or paper publishes a same-prompt, same-seed image grid ranking every sampler in the lists above, and nothing here was generated to produce one; treat any specific "X looks sharper" claim you read elsewhere, including implicitly in this sentence, as unverified unless it points at a named source.
What is documented, from the papers each solver actually comes from: Lu, Zhou, Bao, Chen, Li and Zhu's DPM-Solver++ paper describes DDIM as "a first-order diffusion ODE solver that generally needs 100 to 250 steps for high-quality samples." It reports that its own solver "can generate high-quality samples within only 15 to 20 steps for guided sampling by pixel-space and latent-space DPMs." The same paper found that earlier high-order fast samplers "suffer from instability issues, and they even become slower than DDIM when the guidance scale grows large." That instability is the documented reason DPM-Solver++'s multistep variant exists at all. Zhao, Bai, Rao, Zhou and Lu's UniPC paper describes building "a unified corrector (UniC) that can be applied after any existing DPM sampler to increase the order of accuracy without extra model evaluations," aimed specifically at the very-few-step regime. Song, Meng and Ermon's original DDIM paper frames the tradeoff as choosing "non-Markovian diffusion processes that lead to the same training objective, but whose reverse process can be much faster to sample from" than the DDPM chain it replaced.
Those are step-count and stability claims, each scoped to the paper that made them. None of them is a ranking of Euler against Heun against every DPM++ variant on one prompt.
Full reference table
Read this as a cross-reference of names, families and evaluation cost, not a quality ranking.
| Sampler | Family | Order | Model evals per step | Ancestral | ComfyUI name | AUTOMATIC1111 label |
|---|---|---|---|---|---|---|
| Euler | ODE, deterministic | 1st | 1 | No | euler | Euler |
| Euler a | ODE + injected noise | 1st | 1 | Yes | euler_ancestral | Euler a |
| Heun | ODE, predictor-corrector | 2nd | ~2 | No | heun | Heun |
| DPM2 | ODE, predictor-corrector | 2nd | ~2 | No | dpm_2 | DPM2 |
| DPM2 a | ODE + injected noise | 2nd | ~2 | Yes | dpm_2_ancestral | DPM2 a |
| DPM++ 2S a | DPM-Solver++, singlestep | 2nd | ~2 | Yes | dpmpp_2s_ancestral | DPM++ 2S a |
| DPM++ SDE | DPM-Solver++, singlestep, stochastic | 2nd | ~2 | No (SDE noise, not ancestral) | dpmpp_sde | DPM++ SDE |
| DPM++ 2M | DPM-Solver++, multistep | 2nd | 1 (reuses prior step) | No | dpmpp_2m | DPM++ 2M |
| DPM++ 2M SDE | DPM-Solver++, multistep, stochastic | 2nd | 1 | No | dpmpp_2m_sde | DPM++ 2M SDE |
| DPM++ 3M SDE | DPM-Solver++, multistep, stochastic | 3rd | 1 | No | dpmpp_3m_sde | DPM++ 3M SDE |
| DDIM | Non-Markovian ODE | 1st | 1 | No | ddim | DDIM |
| UniPC | Unified predictor-corrector | variable | 1 | No | uni_pc / uni_pc_bh2 | UniPC |
| LMS | Linear multistep | variable | 1 | No | lms | LMS |
| LCM | Consistency-model shortcut | n/a | 1 | No | lcm | LCM |
Where the prompt fits
Sampler and scheduler are both settings on the generation call, not words that belong in the prompt itself. Writing "DPM++ 2M Karras, 30 steps" into a text field does nothing unless that field is actually wired to the sampler and scheduler parameters, in the same way that steps and CFG scale are separate settings from the prompt and image-to-image strength runs backwards depending on which tool you're in.
Prompt Architects builds the prompt. It does not pick your sampler, does not run your denoising loop, and will not resolve a schedule-type mismatch for you. What it can do is keep the parameter block, sampler, scheduler, steps, and the tool-specific setting name, as a reusable template, so switching from AUTOMATIC1111 to ComfyUI is a name lookup instead of a rebuild. The same discipline matters wherever a setting's name and its meaning both change between tools, which is also true of FLUX's guidance scale against classifier-free guidance elsewhere and of Midjourney's own GPU-time-based quality and speed controls.
Every fetch behind this reference was pulled fresh on September 3, 2026: comfy/samplers.py, comfy/k_diffusion/sampling.py and nodes.py from comfyanonymous/ComfyUI; modules/sd_samplers_kdiffusion.py, modules/sd_samplers.py, modules/sd_samplers_timesteps.py, modules/sd_samplers_lcm.py and modules/sd_schedulers.py from AUTOMATIC1111/stable-diffusion-webui; the schedulers overview doc from huggingface/diffusers; and the Karras, DPM-Solver++, UniPC and DDIM papers on arXiv. Tool source moves fast; re-check the sampler and scheduler lists before trusting an exact count.
Stop rewriting prompts. Start shipping.
Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 4.8★ on the Chrome Web Store.
Create An Account