~/blog/solh3-two-stage-on-2080ti

改裝 2080 Ti 22G · part 18

[Benchmark] Two-stage MiniMax-H3 + LTX-2.5 on a 2080 Ti: 1344x768 with audio in 165s

cat --toc

TL;DR

A modified RTX 2080 Ti 22G — a 2018 card — runs the two-stage MiniMax-H3 + LTX-2.5 pipeline at 1344x768, 121 frames, 5.04 s, with audio, in 165 s warm and 178 s cold. The two stages are 53.97 GiB of weights; the card never holds more than a slice of that, and does not need to. The exact workflow is on HuggingFace, ready to download. Six things have to change from the published Blackwell workflow, two of which fail without printing anything — including one that returns status: success with a valid mp4 in which every pixel is exactly RGB(0,0,0).

Rendered on one modified RTX 2080 Ti 22G: 1344x768, 121 frames, with audio. MiniMax-H3 drafts at 672x384 and LTX-2.5 spends three steps refining it up to twice that — the whiskers, the backlit guard hairs and the dust in the light all come from those three steps. The cat is saying, in Mandarin, "this card is older than I am, but it still runs."

Preface

A freight elevator with a 500 kg limit will still get three tonnes to the tenth floor. It just goes up and down more times. The thing that decides whether the job is possible is not the size of the elevator; it is whether the loading dock is big enough to stage what is waiting.

NVIDIA calls this pipeline MiniMax H3 Super Acceleration: MiniMax-H3 produces a draft in four steps, then LTX-2.5 spends three refining it up to the target resolution. Four names are easy to mix up here: H3 Super Acceleration is the method; Sol Engine is the framework it was published under; Sol-H3 is NVIDIA's own version of that method on a DGX Spark; and Sol-Attn is the sparse-attention kernel stage 2 uses.

NVIDIA runs this configuration on one DGX Spark in 56 s. Don't compare that against the 6.852 s on the GB200 page: that figure sums two separately measured stages, and the page says model loading and warmup are excluded, so it is not a wall clock from prompt to finished file.

Part 11 proved this card can run MiniMax-H3 at all — single-stage, 864x480. Part 8 of the RTX 5090 series took the method apart, and that is where the refine sigma moved from NVIDIA's 0.909375, 0.725, 0.421875, 0 down to 0.78, 0.643, 0.546, 0.

⚠️ Worth settling up front, because the two NVIDIA pages disagree: this is NVIDIA's Spark configuration, parameter for parameter — a 672x384 draft, 124 frames, four draft steps, three refine steps, output at 1344x768, 5 seconds at 24 fps. The GB200 page lists a 896x512 draft, but that belongs to the GB200 line, not this one. The sigma schedule below was calibrated at 672x384 and the knee moves if you change the draft size.

This card has 22 GB and the elevator goes up and down a lot. The pipeline still finishes 1344x768 with audio in 165 seconds.

178 s cold, 165 s warm, and 53.97 GiB that never fits

One modified RTX 2080 Ti 22 GB, compute capability 7.5, a Turing part from 2018. Output is 1344x768, 121 frames at 24 fps, 5.04 seconds, with audio.

Cold — the models were freed beforehand and this run reads them off disk — is 178 s. Warm, with the models still resident and only the seed changed, is 165 s, the median of three runs with a 1.08 s spread between them. Model loading is 13 s of that — the cold/warm difference. The warm 165 s is all compute.

One number is higher than both, and it is the first one you will see after setting this up: 190 s, twice, to the tenth of a second. Restarting ComfyUI throws away Triton's kernel cache, which forces SageAttention's six kernels to recompile — about 12 s. You pay it once per ComfyUI process: free the models inside that same process and the next run is 178 s again.

Which gives one practical rule for the whole rest of this article: while you are iterating on parameters, do not free the models between runs. That 13 s is free.

The two stages together are 53.97 GiB of weights. A 22 GB card cannot hold that and is never asked to — ComfyUI loads models sequentially, and the H3 transformer reports as much on a run that produces a correct video:

loaded partially ... 2861 MB offloaded

So the constraint that actually decides whether this machine can do the job is not VRAM. It is fast storage plus enough system RAM to absorb the offload. This box has 128 GB.

📦 The workflow that produced these numbers is on HuggingFace, ready to download. Not a sketch, not a simplified version — the exact 32-node graph this machine runs:

hf download coolthor/H3-Super-Acceleration-Turing --local-dir . \
  workflows/minimax-h3-ltx-two-stage-turing-sm75.json TURING.md

The same repo carries the startup adapter, the conversion script, and the 13.2 GiB heretic text encoder. Full inventory and step-by-step in TURING.md.

Start from TURING.md: six departures from the Blackwell workflow, and two of them are silent

The executable version of everything below lives in TURING.md in the Hugging Face repo, along with the workflow, the startup adapter and the conversion script. Read that for the steps:

hf download coolthor/H3-Super-Acceleration-Turing --local-dir . TURING.md && cat TURING.md

This section is the part TURING.md cannot be: why each departure is mandatory. It matters because three of the six fail with no error at all. Copy the published Blackwell graph onto this card and you do not get a stack trace — you get broken output, or you get correct output at half the speed you should be getting, and nothing in the log tells you which.

1. Both repos are gated, and a 401 is easy to misread

coolthor/H3-Super-Acceleration-Turing and Lightricks/LTX-2.5 are both gated. hf download returns a 401 and the message is actually explicit (Access to model ... is restricted. You must have access to it and be authenticated), but it is easy to read as a network problem if you are running someone else's script. Accept the terms in a browser on each repo, then hf auth login.

The H3 gate is deliberate. MiniMax-H3's community licence excludes the EU, the UK, South Korea and the United States, and that restriction travels with the weights.

2. Weights: H3 from one repo, the LTX refiner as GGUF from another

Six files from coolthor/H3-Super-Acceleration-Turing, all in one call:

hf download coolthor/H3-Super-Acceleration-Turing --local-dir ComfyUI/models \
  diffusion_models/minimax_h3_fl2va_pruned_int8_convrot.safetensors \
  text_encoders/qwen3vl_32b_heretic_convrot_w4a4.safetensors \
  loras/minimax_h3_fl2v_turbo_4step_v0.1_768p_sla_comfyui_bf16.safetensors \
  vae/minimax_h3_video_vae_fp16.safetensors \
  vae/minimax_h3_audio_vae_fp32.safetensors \
  conditioning_cache/ltx_generic_refine.cond

The LTX refiner is the GGUF build, and that is not a size optimisation — see the black-video section below. The VAEs and the x2 upscaler come from Lightricks/LTX-2.5 as bf16 and get converted locally, which is departure 4.

hf download agosh/LTX-2.5-Comfy-GGUF --local-dir ComfyUI/models/diffusion_models \
  ltx-2.5-22b-distilled-transformer-bf16-Q4_K_M.gguf
hf download Lightricks/LTX-2.5 --local-dir ComfyUI/models \
  vae/ltx-2.5-video-vae-conv-bf16.safetensors \
  vae/ltx-2.5-audio-vae-bf16.safetensors \
  latent_upscale_models/ltx-2.5-latent-spatial-upscaler-x2-bf16-1.0.safetensors

Where you put these files is worth ten minutes. Storage speed shows up directly in that 13 s of loading. Measured on this machine: ext4 on NVMe at 2.3 GB/s, and an ntfs3 volume on the same box at 1.2 GB/s. The 13.2 GiB text encoder started life on the slow one. Moving it saved 5.6 s per cold run.

3. Three node packs, plus a startup adapter

git clone https://github.com/T8mars/comfyui-minimax-h3-audio-T8
git clone https://github.com/xmarre/ComfyUI-Spectrum-MiniMax-H3
git clone https://github.com/city96/ComfyUI-GGUF

The third one is needed only on this card: it provides UnetLoaderGGUF, which node 15 of the workflow uses instead of UNETLoader.

A fourth does not come from git. Node 32's LoadConditioningT lives in ComfyUI-CondCache, which ships alongside the workflow — pull the one file into custom_nodes/:

hf download coolthor/H3-Super-Acceleration-Turing --local-dir ComfyUI \
  custom_nodes/ComfyUI-CondCache/__init__.py

Miss it and the whole graph refuses to load, with an error that says the node does not exist rather than that a file is missing — so you go hunting for a weight that is already on disk.

On top of those, a startup adapter ships in the HF repo at custom_nodes/ComfyUI-LTXV-Turing-FP16/. It only acts when torch.cuda.get_device_capability() == (7, 5), so it is inert on any other GPU:

hf download coolthor/H3-Super-Acceleration-Turing --local-dir ComfyUI \
  custom_nodes/ComfyUI-LTXV-Turing-FP16/__init__.py

What it fixes, and why the obvious flag does not fix it, is the second silent failure in the deep dive.

4. Convert the LTX bf16 files to fp16, or pay for them twice

Turing has no bf16 hardware. ComfyUI upcasts bf16 to fp32, and the tensor then takes exactly twice its on-disk size in VRAM. Measured: ltx-2.5-video-vae-conv-bf16.safetensors is 1.35 GiB on disk and loads as 2769.87 MB. The x2 upscaler is 0.93 GiB on disk and loads as 1899.22 MB.

Convert all three — video VAE, audio VAE, x2 upscaler — with the script in the repo. It saves about 2.7 GB:

hf download coolthor/H3-Super-Acceleration-Turing --local-dir . scripts/bf16_to_fp16.py

I checked tensor by tensor: zero tensors exceeded the fp16 range. That claim is narrower than it sounds. It covers the numeric range of the weights themselves — not the activations flowing through at inference, not underflow, and not output quality. fp16 stores 10 fraction bits against bf16's 7, but converting hands no precision back: whatever bf16 dropped during training is gone. All you buy is that ComfyUI stops upcasting.

⚠️ The script preserves the safetensors header metadata, and it has to. save_file() drops metadata by default, and ComfyUI's VAELoader reads the config key out of that header to pick the VAE architecture. My first version dropped it. The symptom is a shape mismatch that looks like you downloaded the wrong file:

size mismatch for encoder.down_blocks.7.conv.conv.weight: copying a param with
shape [128, 1024, 3, 3, 3] ... current model is [256, 1024, 3, 3, 3]

5. SageAttention 1.0.6, and one integer inside it

Launch flags:

python main.py --use-sage-attention --reserve-vram 2 --disable-pinned-memory

The version has to be 1.0.6. Everything from 2.x on needs sm_80 or newer; SageAttention issue #137 is another 2080 Ti owner hitting Unsupported CUDA architecture: sm75.

Installing 1.0.6 is not enough on its own. At stock settings its Triton kernels request 67584 bytes of shared memory and Turing's hard limit is 65536. Triton refuses, and ComfyUI quietly falls back to PyTorch attention — which is the third silent failure, and it costs you the whole point of installing it. In all six attn_qk_int8_*.py files under site-packages/sageattention/:

num_stages=3 if head_dim == 64 else 1)

⚠️ Do not touch BLOCK_M while you are in there. It looks like a sibling scheduling knob and it is not one. quant_per_block.py's per_block_int8(BLKQ=128) produces one quantization scale per BLKQ rows, and the kernel indexes that array with its own BLOCK_M. Change one without the other and you read invalid scales, or index past the end of the array, with no error either way. num_stages only changes pipeline depth; it leaves the algorithm itself alone.

6. Three values inside the workflow

The graph is 32 nodes:

hf download coolthor/H3-Super-Acceleration-Turing --local-dir . \
  workflows/minimax-h3-ltx-two-stage-turing-sm75.json

Three things in it differ from the Blackwell version, and this table is the one to check node by node after you drag the JSON in:

NodeValueWhy
15UnetLoaderGGUF, not UNETLoaderThe big one. See the next section.
16attention_backend = dense_referenceSol-Attn's kernel is bf16-only, so this card never reaches it
7bootstrap_first_forecast: false, written explicitlyThe Spectrum node changed the default to true

Node 16 is the one where the honest setting and the useful setting are the same. Setting auto_sol_attn on this card does not enable anything; it just makes every call fall back to dense, silently. Writing dense_reference describes what the card does anyway.

Node 7 is the one that at least fails loudly. bootstrap_first_forecast: true requires degree == 1 and warmup_steps <= 1, and this graph uses 4 and 5. Leave it at the new default and node 7 raises ValueError: bootstrap_first_forecast requires degree == 1, and the whole graph stops.

The 284 s run that reported success and wrote a completely black mp4

The first full-pipeline run took 284 s and finished with status: success. The output was a valid mp4: 1344x768, 121 frames, 5.04 s, h264 and aac both present, cached=0. There was no error anywhere in the log.

I extracted three frames. All three JPEGs were exactly 6250 bytes, which is the fingerprint of a solid colour, and every pixel in them was exactly RGB(0,0,0).

That byte count is what turned a mystery into a diagnosis. An all-zero latent decoded through a VAE does not come out black — bias terms push it to a non-uniform grey. That is not a diagnosis on its own — black output can come from cropping, decoding or postprocessing — but it was enough to make me go and measure the latent itself. SaveLatent on both sides of the refine step confirmed it:

shapeNaNminmaxstd
before refine(1,128,16,24,42) fp320-6.19425.40410.9560
after refinesame2,064,384 / 2,064,384

The draft latent was healthy. The refine pass destroyed it. Swap in the GGUF Q4_K_M build of the same model and it is correct on the same card, and smaller — 11.38 GiB against 20.03. That is why node 15 is UnetLoaderGGUF.

⚠️ Be careful how far you carry that. What the comparison establishes is that this checkpoint fails and the GGUF one works on this stack — ComfyUI 0.31.0, comfy-kitchen 0.2.28, torch 2.6. It does not isolate whether the fault is in the weights, the dequantization, or the kernel, because swapping the file changes all three at once. I could not test the version axis: comfy-kitchen 0.2.31 will not import under torch 2.6 (infer_schema rejects the list[int] annotation in backends/eager/na.py), and torch 2.6 is what sageattention 1.0.6 and triton 3.2.0 are pinned against. That version set is what this card can run, so it is the set the finding is scoped to.

⚠️ The trap in this is that H3's own int8-convrot build is fine on this card. Same quantization family, same machine, one works and one does not. ComfyUI prints a line at load that reads like a green light:

Native ops: int8_tensorwise, asym_w4a8_int8, convrot_w4a4

That line means "not emulated". It does not mean "correct". Verify per model.

Dropping the draft to 544x320 saves 30% of the clock and no detail I can see

LTXVLatentUpsampler is a fixed x2, so the draft is always exactly half the output. Lowering the draft lowers the finished video with it — this is not a quality knob with a free lunch attached, it is a resolution knob.

Three points, same workflow, only the draft size and the handoff target changed. Read the last two columns against each other:

draftoutputcoldwarmdraft pixel ratiowarm time ratio
672x3841344x768179.8167.01.0001.000
544x3201088x640129.5117.30.6750.702
432x240864x48084.576.90.4020.460

Time tracks pixels almost exactly. The fit is warm seconds ≈ 16.4 + 150.6 × (draft pixels / 258,048), which predicts 118.0 s for the middle row against 117.3 measured, 0.6% off.

I expected superlinear scaling and was wrong, and the reason matters: attention cost grows with the square of token count, so I assumed attention would dominate. It does not. In this workload it is not the dominant term.

Stop at 544x320 → 1088x640. 117 s, 30% saved, and hair strands, earring detail and skin shading all look essentially intact. The next rung down is 77 s and visibly soft.

Same cat, same seed, draft dropped to 544x320 for a 1088x640 output. Put it beside the clip at the top — what changes is mostly size, not detail.

⚠️ Those three rows are three separate generations, not three quality levels of one clip. Changing the resolution changes the latent shape, so the same seed follows a different sampling trajectory and you get a different take. Compare detail density between them, not content.

The other lever, and the one that costs no spatial detail at all, is frame count. Cutting it scales close to linearly.


Deep dive: four hypotheses the measurements killed, and three ways this stack fails quietly

Reading this is optional — everything you need to run the pipeline is above. This is how the black video got diagnosed, and the three places on this card where something switches itself off and says nothing.

Four hypotheses ruled out before the right one

Out of memory. The log had a line that looked like a smoking gun: the final LTX VideoVAE reported loaded partially; 0.00 MB usable, 0.00 MB loaded, 2769.87 MB offloaded while nvidia-smi showed 4,260 MiB still free on the card. I swapped in VAEDecodeTiled; the memory behaviour changed completely and the output was still black. Later, runs that produced correct video printed the same line. Symptom, not cause.

Compute dtype falling to fp32. Side by side, the two stages disagreed:

Stage 1 (H3)   model weight dtype torch.float16,  manual cast: torch.float16
Stage 2 (LTX)  model weight dtype torch.bfloat16, manual cast: torch.float32

The convrot kernels only take FP16 or BF16, so this was a real problem. Fixing it cut the run from 266 s to 179 s, a 33% saving. The picture was still black. Necessary, not sufficient — and worth separating out, because 33% less wall-clock time is exactly the kind of result that makes you think you have found the bug.

Schedule or conditioning strength. I pushed sigma down to 0.05, 0.03, 0.01, 0, where the refine stage should barely perturb its input at all. Still black.

fp16 range overflow. I concluded this one and was wrong. The evidence looked strong: the blackness was too clean, the latent was all NaN, and it matched an overflow this same card produced with H3 back in August 2026. What killed it is that the fp32 runs were also black. A pure range problem should have made fp32 slow, not broken. Both dtypes black rules out the top-level compute dtype as the explanation. Strictly it does not rule out an overflow inside a kernel that still works in fp16 internally — establishing that would need instrumentation I did not do.

The comparison that settled it changes one thing — the refiner file — holding model, version, sigma, VAE and machine constant:

LTX refiner filedequant pathsecondsresult
...comfy-int8-convrot 20.03 GiBcomfy-kitchen convrot kernel179.1all NaN
...bf16-Q4_K_M.gguf 11.38 GiBComfyUI-GGUF (dequant→fp16→ordinary GEMM)185.0correct
sulphur-distil-ltx23av-Q4_K_M.gguf (LTX 2.3)same198.2correct but changes the face

The third row is worth a note if you are tempted to substitute an older refiner. LTX-2.3 refines perfectly well, but the face comes back as a different person. sigma 0.78 is the knee calibrated for 2.5 in the six-arm sweep from the 5090 article; a different model generation slides off it. That is a calibration problem, not a GGUF problem.

Silent failure 1: Sol-Attn never tells you it did not run

ComfyUI-SolAttn_triton's kernel is bf16-only. The eligibility check is at __init__.py:176-177:

if q.dtype != torch.bfloat16:
    return f"dtype {q.dtype} (kernel is bf16-only)"

Turing has no bf16, so that condition held on every call in this workflow. The rejection path is return None falling back to dense, not an exception. And the registry entry point attention_sol hardcodes verbose=False, so a path entered through attention_backend prints nothing whatsoever.

There is a way to check. Sol-Attn keeps its own counters: sol_attn_stats() returns a dict with sparse and dense_fallback, and sparse > 0 is what proves the kernel actually ran. That is more reliable than reading the log, because _log_once deduplicates on (shape, reason) — "no message in the log" cannot distinguish "never engaged" from "deduplicated away". The counter can.

The other two ComfyUI ports exclude Turing too, and say so in their own docs: Saganaki22/ComfyUI-sol-attn states SM89 through SM121, and quzopl/ComfyUI-SolAttn-H3 states SM89, 90, 100 and 120. Neither of the two ports I checked covers sm_75 either.

Silent failure 2: --fp16-unet does nothing for a quantized model

This is why the startup adapter exists at all.

LTXV.supported_inference_dtypes is [bfloat16, float32]. No bf16 on Turing means the compute dtype lands on fp32, which is the 33% tax from the hypothesis section above. The obvious fix is --fp16-unet. It does not work, and comfy/sd.py says why:

if model_config.quant_config is not None:
    manual_cast_dtype = unet_manual_cast(None, load_device, model_config.supported_inference_dtypes)
else:
    manual_cast_dtype = unet_manual_cast(unet_dtype, load_device, model_config.supported_inference_dtypes)

A quantized model takes the first branch, where weight_dtype is deliberately None. That is a defensible choice on its own terms: the weights are int8, and their dtype says nothing about what the compute should be. But every branch inside unet_manual_cast that inspects weight_dtype then falls through, leaving only the for dt in supported_dtypes loop — and the flag's unet_dtype is never passed in on that path. The symptom is the half-applied line from earlier:

model weight dtype torch.float16, manual cast: torch.float32

The flag reached the storage dtype and never touched the compute dtype. Three ways to fix that:

approachworksscopesurvives ComfyUI upgradevisible
edit comfy/supported_models.pyyesLTXV onlyno, gets overwrittenno
--fp16-unet flagno for quantized modelswhole serviceyesyes
startup adapter in custom_nodes/yesLTXV onlyyesyes, in the startup log

The third wins on the two columns that matter for a machine you come back to in three months: it survives an upgrade, and it announces itself in the startup log so future-you can see it is there. This box already had a kitchen_turing_int8_enable.py doing the same kind of thing, so the pattern was local precedent rather than invention. To revert, delete that one file.

Silent failure 3: SageAttention falls back, and the margin is 2048 bytes

Dozens of these in the log:

Error running sage attention: out of resource: shared memory,
Required: 67584, Hardware limit: 65536. using pytorch attention instead.

67584 − 65536 = 2048. Here is where the shared memory goes at BLOCK_M=128 / BLOCK_N=64 / HEAD_DIM=128:

num_stagesQKVtotal
4163843276865536114688
216384163843276865536
11638481921638440960

num_stages=2 lands exactly on the limit. The extra 2048 bytes that push it over are unaccounted for in my estimate — I did not chase where they come from. Dropping to 1 leaves headroom either way.

The generalisable part of this is the rule about BLOCK_M from departure 5. That constant also determines the shape of q_scale, as (qo_len + BLKQ - 1) // BLKQ. If a constant determines the shape of a tensor, it is not a scheduling parameter. That is a test you can apply to any kernel you are tempted to tune, without knowing anything about the kernel.

What SageAttention is actually worth here: not speed, feasibility

Same workflow, n=3, warm median:

configcoldwarm
SageAttention 1.0.6178165
disabled, plain pytorch SDPA213out of memory

With it disabled the cold run completes 35 s slower. The second run does not complete at all — it dies about four seconds in:

Got an OOM, unloading all loaded models

PyTorch's memory-efficient SDPA needs more VRAM than SageAttention's INT8 kernels, and on a warm run the models are still sitting on the card. So on this hardware SageAttention is not a 20% optimisation you can skip. It is the difference between a warm run and no warm run.

⚠️ One research note, because it nearly went into this article as a fact. While looking into this, two web searches fed back "SageAttention is 16.8% faster than PyTorch SDPA on a 2080 Ti" as though it were external corroboration. That number came from this site's own August article. When you are researching a topic you have written about, check that the hit is not you. It was also measured on 864x480 single-stage H3. Same card, different workload shape — and a number measured on one shape does not carry to another.

Environment

GPU            RTX 2080 Ti 22G (modified) - compute capability 7.5 (Turing)
OS             Linux - torch 2.6.0+cu124 - triton 3.2.0 - Python 3.12
ComfyUI        0.31.0 - comfy-kitchen 0.2.28 - sageattention 1.0.6
Launch flags   --use-sage-attention --reserve-vram 2 --disable-pinned-memory
Storage        ext4 NVMe measured at 2.3 GB/s - 128 GB system RAM
Weights        53.97 GiB total
Output         1344x768 - 121 frames - 24 fps - with audio
Steps          4 draft / 3 refine

The workflow JSON, the startup adapter, the conversion script and the 13.2 GiB heretic text encoder — ConvRot W4A4, the first build of it published anywhere as far as I know — are all documented in TURING.md at coolthor/H3-Super-Acceleration-Turing.

The method on a card with room to spare: MiniMax-H3 + LTX-2.5 two-stage on an RTX 5090

FAQ

Can a modded RTX 2080 Ti 22G run the two-stage MiniMax-H3 + LTX-2.5 pipeline?
Yes. One modified 2080 Ti 22 GB, compute capability 7.5, produces 1344x768, 121 frames at 24 fps, 5.04 seconds, with audio, in 178 s cold and 165 s warm. The two stages are 53.97 GiB of weights in total, far more than the card holds, but ComfyUI loads them in sequence and the machine's 128 GB of system RAM absorbs the offload. The H3 transformer itself reports `loaded partially ... 2861 MB offloaded` on a run that works.
Why does the LTX-2.5 int8-convrot checkpoint produce a completely black video on a 2080 Ti?
On this stack it computes incorrectly and the refined latent comes out 100% NaN. `SaveLatent` before the refine step shows NaN 0, min -6.1942, max 5.4041; after the refine step the same tensor is 2,064,384 NaN out of 2,064,384. ComfyUI reports `status: success` and writes a valid h264 + aac mp4 anyway. Use the GGUF build instead: `ltx-2.5-22b-distilled-transformer-bf16-Q4_K_M.gguf` from `agosh/LTX-2.5-Comfy-GGUF` is correct on the same card and is 11.38 GiB against 20.03.
Which SageAttention version works on an RTX 2080 Ti, and does it need patching?
Version 1.0.6. Anything 2.x or later requires sm_80 or newer. It also needs one edit: at stock settings its Triton kernels ask for 67584 bytes of shared memory and Turing's hard limit is 65536, so Triton refuses and ComfyUI falls back to PyTorch attention. In all six `attn_qk_int8_*.py` files under `site-packages/sageattention/`, set `num_stages=3 if head_dim == 64 else 1)`. Do not touch `BLOCK_M` — it determines the shape of the per-block quantization scale array, not just the schedule.
Does the --fp16-unet flag fix the fp32 compute fallback for quantized models?
No. In `comfy/sd.py`, a model with a `quant_config` takes a branch that calls `unet_manual_cast(None, ...)`, so the flag's dtype is never passed in. The symptom is `model weight dtype torch.float16, manual cast: torch.float32` — the flag moved the weights and not the compute. The fix that survives a ComfyUI upgrade is a startup adapter in `custom_nodes/` that only acts when `torch.cuda.get_device_capability() == (7, 5)`.
Is SageAttention worth enabling on a 2080 Ti for this pipeline?
Not for speed here, for feasibility. With SageAttention 1.0.6 the run is 178 s cold and 165 s warm. With it disabled and plain PyTorch SDPA, the cold run is 213 s and the warm run does not finish at all: it dies in about four seconds with `Got an OOM, unloading all loaded models`, because PyTorch's memory-efficient SDPA needs more VRAM than SageAttention's INT8 kernels and the models are still on the card.
What resolution should I actually run on a 2080 Ti?
A 544x320 draft refining to 1088x640, which takes 117 s warm against 167 s for the full 672x384 to 1344x768 path. That is 30% off the clock and hair strands, earring detail and skin shading look essentially intact. The next rung down, 432x240 to 864x480, is 77 s but visibly soft. Scaling is close to linear: warm seconds are about 16.4 + 150.6 x (draft pixels / 258,048).
Does Sol-Attn work on a Turing GPU?
No, and it will not tell you. The kernel in `ComfyUI-SolAttn_triton` is bf16-only and Turing has no bf16, so the eligibility check at `__init__.py:176-177` rejects every call and returns None, falling back to dense. The registry entry point hardcodes `verbose=False`, so nothing is printed. The two other ComfyUI ports state the same limit in their own docs: Saganaki22's covers SM89 to SM121 and quzopl's covers SM89, 90, 100 and 120. On this card, set `attention_backend` to `dense_reference` and describe what is actually happening.

Read next

Don't miss the next one

Subscribe, and you won't.

One-click unsubscribe anytime.