Repository navigation
feat(working-memory): reserve Z-Image denoise working memory from measured lines - #9919
Merged
Pfannkuchensack merged 214 commits intoOct 29, 2026
Merged
Pfannkuchensack merged 214 commits into
Pfannkuchensack merged 214 commits into
Conversation
Runs each installed model family through a launched scratch server and compares PSNR, time and driver-level VRAM against accepted references. Graphs come from the frontend builders via an offline graph export; the generate submission plan is shared with the workbench.
VAE estimators return a WorkingMemoryEstimate built from fitted and analytic terms; model_on_device accepts it as working_memory=. The AutoencoderKL coefficients and their measured points move to backend/working_memory/data, checked by a data test; reservations are unchanged.
A probe records each estimated model_on_device window's device-level demand inside a calibration scope; results go to a per-device-class store under databases/working_memory. Admin endpoints start, inspect, reset and export runs; the reserved queue origin is refused for ordinary enqueues.
VAE estimators price a measured slope and base per conv backend, allocator and dtype instead of scaling one bf16 constant by element size; CogView4 gets its own lines. SD/SDXL nodes and their estimate share one run-dtype rule; on ROCm Windows an SDXL fp32 1024² decode reserves 6.2 instead of 14.6 GB and the UNet stays resident.
A lower second reading at a measured size no longer tilts a fitted line, and points that include cast weight growth no longer fit one; two shipped lines move by under 1 %.
…n fact Environment ids now include windows, linux or other, so calibrations from different operating systems are kept apart; the OS build string moves to soft fact os_build.
… runs start --calibrate submits each case through the calibration endpoint and saves the store export per server lifetime; scripts/working_memory/build_shipped.py turns exports into probe points and refits. Probe points bound estimates from below only, and the builder refuses data that the shared bound rule rejects.
# Conflicts: # docs/src/content/docs/development/Architecture/model-manager.mdx
…anager Adds a working-memory section to the model detail: plan, calibrate, stop and reset per GPU, with the measured, built-in and calibrated estimate per size. User fits from finished calibration attempts price VAE decodes within their measured range (+10 % + 256 MiB on the fitted part) and never below built-in values above it. New plan and summary routes; summary reports lines shared with other models and returns 404 for unknown models.
…calibration Judges allocator fragmentation per calibration attempt with one rule shared with the shipped-data builder, and moves other models off the GPU before a measured calibration lock. User fits use the shipped 5 % margin; the plan sizes cases from the capacity the cache will grant, including memory the driver keeps after earlier runs. The table marks uncounted sizes with their reason and explains each value column.
# Conflicts: # invokeai/backend/util/vae_working_memory.py # tests/app/invocations/test_flux2_working_memory.py
# Conflicts: # invokeai/backend/util/vae_working_memory.py
Main added useNsfwChecker and useWatermark to the generation project settings; exported calibration and E2E graphs run without both, as the defaults do.
…ser-calibration # Conflicts: # invokeai/frontend/webv2/performance/browser-baseline.json # invokeai/frontend/webv2/scripts/mock-backend-fixtures.test.mjs # invokeai/frontend/webv2/scripts/mock-backend.mjs
…e baseline Raises otherRawBytes to the measured 215114 B on every route; the 3791 B growth are the Model Manager working-memory strings.
…f the model page The section starts collapsed and shows the GPU with the calibration state, or the run progress, in its header; the plan loads on first open. The mock prices sizes above the measured range with the larger of the user line and built-in, as the server does.
Main added useNsfwChecker and useWatermark to the generation project settings; exported calibration and E2E graphs run without both, as the defaults do.
…sured lines Prices the Z-Image denoise through an EstimatorSpec whose per-token lines are fitted from fresh-process measurements on CUDA and ROCm, with an fp8 cast term and the legacy constants as the floor where nothing was measured. Fitted lines can now run over tokens; the builder takes measured point files, and calibration scripts share the server runtime and the probe's measurement window.
…d trusts no reused server pid Once the runner is dead, stop reads heartbeat.json again and kills and checks the server it names now. The heartbeat records the serving process with the create time captured at its start.
…n unlock A failed lock or paced continuation that drops the last pin now returns cast weights to their counted dtypes too, all in one release path. Records that are detached or about to be evicted as stale are skipped, and the docstrings state how a tied weight split across devices is re-pointed.
…r the fits lock Outcomes read from the queue are kept per run and item id, so a renumbered database cannot let one run's item decide another's attempt. The summary, the attempt check and resets judge them under the lock removals hold, so a reset cannot race a judgement.
…lan from accepts_vae The planner asks the shared rule the model loaders and Generate's picker read, latent channels and variant included, instead of restating it.
…ipelines in the plan
…e default VAE of SD mains
…ixel line Only a spec keyed by no platform trait may carry a hand-set value; a keyed spec's value off a pixel line fails the data test.
A fit-grid forward whose estimator line does not admit its features ships with in_fit false, beside the checks.
Member
Author
|
@JPPhoto Thanks, confirmed and fixed in 5b1c79d. Fit-grid point marked Test: Shipped data: all 84 |
…ibration # Conflicts: # docs/src/content/docs/development/Architecture/model-manager.mdx # invokeai/app/util/torch_cuda_allocator.py # invokeai/backend/working_memory/coefficients.py # invokeai/backend/working_memory/fit.py # invokeai/backend/working_memory/platform.py # tests/backend/model_manager/load/model_cache/test_model_cache_unlock_restores_casts.py # tests/backend/working_memory/test_fit.py # tests/backend/working_memory/test_shipped_coefficients.py
The runner checks the run is still running, spawns the server and records it in the heartbeat in one run-lock hold, so stop either sees the server or no server starts. A server whose identity cannot be recorded is killed before the lock is released. Points of estimators keyed by no platform trait name no platform in build_shipped.
…er model identity Calibrate requests carry graph_models, the hash, base, type, format and variant of every model the graph names as the client compiled it; a difference from the current records, or from a keyed repeat's run, is refused with 409 model_changed. The model manager and the family E2E tool send the identities of the records they compiled over.
# Conflicts: # invokeai/backend/working_memory/fit.py # scripts/working_memory/build_shipped.py
# Conflicts: # docs/src/content/docs/development/Architecture/model-manager.mdx # invokeai/backend/working_memory/bounds.py # invokeai/backend/working_memory/fit.py # scripts/working_memory/build_shipped.py # tests/backend/working_memory/test_fit.py # tests/backend/working_memory/test_shipped_coefficients.py
…ibration # Conflicts: # docs/src/content/docs/development/Guides/family-e2e.mdx # scripts/family_e2e/__main__.py # scripts/family_e2e/client.py # scripts/family_e2e/records.py # scripts/family_e2e/references.py # scripts/family_e2e/report.py # scripts/family_e2e/runner.py # scripts/family_e2e/server.py # tests/family_e2e/fake_invokeai_server.py # tests/family_e2e/test_cli.py # tests/family_e2e/test_references.py # tests/family_e2e/test_report.py # tests/family_e2e/test_runner.py
…king-memory-user-calibration
…king-memory-denoise
…-denoise # Conflicts: # docs/src/content/docs/development/Architecture/model-manager.mdx # docs/src/content/docs/development/Guides/family-e2e.mdx # invokeai/app/services/working_memory_calibration/working_memory_calibration_common.py # invokeai/app/services/working_memory_calibration/working_memory_calibration_default.py # invokeai/app/services/working_memory_calibration/working_memory_calibration_fits.py # invokeai/backend/working_memory/bounds.py # invokeai/backend/working_memory/fit.py # invokeai/backend/working_memory/fragmentation.py # invokeai/backend/working_memory/spec.py # invokeai/backend/working_memory/user_fit.py # invokeai/frontend/api/openapi.json # invokeai/frontend/api/schema.ts # scripts/working_memory/build_shipped.py # tests/app/services/working_memory_calibration/test_working_memory_calibration_fragmentation.py # tests/app/services/working_memory_calibration/test_working_memory_calibration_user_fits.py # tests/backend/working_memory/test_fit.py # tests/backend/working_memory/test_shipped_coefficients.py # tests/backend/working_memory/test_user_fit.py # tests/test_build_shipped_working_memory.py
Pfannkuchensack
enabled auto-merge (squash)
October 28, 2026 23:46
6 of 7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Z-Image denoise reserved a hand-set 0.25 MiB per attended token plus a fixed 1 GiB on every platform and dtype. Fresh-process measurements on an RTX 4090 and an RX 9060 XT show that this is twice what bf16 needs at 1024², and less than fp32 needs at large sizes. The denoise now runs through the working-memory estimator framework, and its per-token lines are fitted from those measurements.
cudaMallocAsyncEstimator
denoise.z_imageprices a fitted line per dtype over the attended tokens.model_on_device(working_memory=…), so calibration runs now record denoise windows.Framework
EstimatorSpec(fit.Line), so they can run over tokens as well as output pixels.unmeasured_floorkeeps every unmeasured platform at or above the previous values.legacy, i.e. hand-set; only Linux ROCm native does.scripts/working_memory/build_shipped.pytakes fresh-process point files. It replaces a legacy entry only when capping points measure every line.Measurement
scripts/calibrate_z_image_working_memory.pymeasures one forward per fresh process, with demand = max(driver, reserved, allocated) growth. The cold and warm runs both count.run_app.apply_server_runtimeshares the steps withrun_app(), and a test pins that both apply the same sequence.invokeai/backend/working_memory/measurement.py.Related Issues / Discussions
QA Instructions
Measurements
cudaMallocAsync) and RX 9060 XT (torch 2.13+rocm10.0, Windows, expandable and native, AOTriton fused).working_memory/data/denoise.json. Each sits at 1.05–1.22× its estimate.Checks of the analytic terms
In-server check with the real Z-Image Turbo, through the calibrate route: every window is below its new estimate.
cudaMallocAsync, bf16.A/B, Z-Image Turbo bf16, 8 steps, family E2E tool, interleaved runs before → after → before, 1 warm-up + 3 measured per size:
device_working_mem_gb: 3decides at ≤ 1536², so the gain shows above that, or with a lower floor.Tests
uv run --no-sync pytest -n 4: working memory, calibration services, router and runner,tests/app/invocations,tests/backend/model_manager/load, fp8, builder, calibration script andrun_appenvironment. 4848 passed.Review
Resolved findings
hipMallocAsync) had dropped to a measured card's line. They are floored at the previous values now.excluded_windowsdescription is updated, and the VAE plan's capacity input ignores denoise windows.Remaining limits
Compatibility / Rollout
openapi.jsonandschema.tsare regenerated.EstimatorSpec.lineis now a required argument; the five VAE specs passconvolution_line.Checklist
What's Newcopy (if doing a release after this PR)Need help on this PR? Tag
@codesmith-botwith what you need.