Skip to content

Optimizing flux2klein - #458

Open
amepas wants to merge 1 commit into
mainfrom
optimizing-flux2klein
Open

Optimizing flux2klein#458
amepas wants to merge 1 commit into
mainfrom
optimizing-flux2klein

Conversation

@amepas

@amepas amepas commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Building off of PR 456 (so some overlapping code changes)

Summary

This PR improves inference speeds for Flux2 Klein Models. ~2.58x overall speedup compared to the original implementation and outperform the standard SGLang GB200 baseline.


Performance Benchmarks

  • Resolution: 1024 × 1024 (Batch=1)
  • Hardware: Single Chip (GB200 vs TPU v7-2)
Implementation Total Latency Latency (Excl. Image Saving) vs. Original
Original Implementation 1131.20 ms/img 765.28 ms/img 1.0x (Baseline)
SGLang GB200 Baseline 563.90 ms/img 406.40 ms/img ~2.01x faster
Flux2Klein 9B (PR) 438.00 ms/img 329.77 ms/img ~2.58x faster

--

Optimizations

1. Tokenizer Caching Outside Warmup & Inference Loops

Instantiated and cached self.tokenizer once in FlaxFlux2KleinPipeline.__init__. String inputs are tokenized directly into contiguous PyTorch/NumPy arrays prior to device placement.


2. Early-Stopping Qwen3 Text Encoder Execution at Layer 27 (max_layer_to_run=27)

Standard Qwen3 contains 28+ layers, but Flux.2-Klein only extracts cross-attention text embedding representations from intermediate layers 9, 18, and 27. Running layers 28+ performed pure wasted matrix multiplication compute.


3. Dedicated dot_product Attention Backend for Qwen3 (Backend Isolation)

Passing shared global attention arguments into both Qwen3 and Flux caused Qwen3 to attempt loading ring Ulysses Splash kernels (ulysses_ring_custom), which are slow on the short 512-token text prompts.


4. Fusing 4 Denoising Steps into jax.lax.scan (_jitted_fused_denoise_loop)

Switching from a standard for loop to compile as a single graph.


5. Internal Denoising Loop Optimizations

  1. Eliminated Redundant put_data_on_devices inside Denoising Loop (~4.2 ms saved)
  2. Pre-Staged Timesteps Array on TPU Device Mesh (~0.9 ms saved). Migrated scheduler_state.timesteps and scheduler_state.sigmas sharding onto the device mesh outside the iterative loop.
  3. Direct Step Indexing in Flow Match Euler Scheduler (~0.6 ms saved). Added step_index: Optional[int] = None in scheduling_flow_match_flax.py so the denoising loop passes the exact loop index directly (step_idx) to avoid _find_timestep_id searches (jnp.argmin(jnp.abs(...))) during every step.

6. Optimal Configuration Settings:

  • attention="ulysses_ring_custom_fixed_m":
  • ici_context_parallelism=2 & ulysses_shards=2
  • ulysses_attention_chunks=1: Single-chunk ring stream execution.
  • flash_block_sizes='{"block_q": 4608, "block_kv": 1024, "block_kv_compute": 1024}'.

7. Image Saving (uint8) Matching SGLang implementation

Implemented vector clamping and conversion directly on TPU arrays to uint8 ([0, 255]) before copying buffers to CPU for PNG encoding.


8. 4D Spatial Vectorization in VAE Decoding (_jitted_vae_decode)

The VAE decoder previously packed and flattened latents into intermediate 3D spaces, requiring multiple transpose and reshape operations. Refactored _jitted_vae_decode (donate_argnums=(1,)) to operate directly on 4D spatial tensors (batch_size, 32, height // 8, width // 8) using direct 4D convolution blocks.

Correctness

All smoke tests pass

@amepas
amepas requested a review from entrpn as a code owner August 11, 2026 18:02
@github-actions

Copy link
Copy Markdown

@amepas
amepas marked this pull request as draft August 11, 2026 18:02

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a unified end-to-end inference pipeline for Flux.2-klein models (4B and 9B) on JAX+TPU, including configurations, entry point scripts, and optimizations such as concurrent AOT compilation and memory-efficient resizing. Feedback on the changes highlights several critical issues: several duplicate files were added in incorrect directories and should be removed; Qwen3 attention needs to correctly handle causal and padding masks when using non-dot_product kernels; step_index should not be a static argument in the scheduler to avoid JIT recompilation; potential index errors when text_encoder_max_layer is less than 27 should be addressed; and fractional per_device_batch_size in the smoke test should be fixed to prevent JAX sharding errors.

Comment thread src/maxdiffusion/models/qwen3_flax.py Outdated
Comment thread src/maxdiffusion/schedulers/scheduling_flow_match_flax.py Outdated
Comment thread src/maxdiffusion/flux2klein_pipeline.py Outdated
Comment thread src/maxdiffusion/models/generate_flux2klein.py Outdated
Comment thread src/maxdiffusion/models/flux/transformers/generate_flux2klein.py Outdated
Comment thread src/maxdiffusion/tests/generate_flux2klein_smoke_test.py
Comment thread src/maxdiffusion/pipelines/flux/flux2klein_pipeline.py
@amepas
amepas force-pushed the optimizing-flux2klein branch from 64a64aa to d78a39e Compare August 11, 2026 21:05
@amepas
amepas marked this pull request as ready for review August 11, 2026 21:08
Comment thread src/maxdiffusion/configs/base_flux2klein.yml Outdated
@amepas
amepas force-pushed the optimizing-flux2klein branch from 3daea67 to 9dbca46 Compare August 13, 2026 06:57
…weight loading, and end-to-end optimizations

- Implemented Flax NNX Transformer architecture (NNXFlux2KleinTransformer2DModel) with support for both 4B (5 double / 20 single layers) and 9B (8 double / 24 single layers) configurations.
- Integrated Flax Qwen3 text encoder with 3-layer intermediate hidden states extraction (layers 9, 18, 27) and custom splash/dot-product attention.
- Implemented FlaxAutoencoderKL VAE decoder with fused batch normalization unscaling and channel re-layout.
- Added fused end-to-end denoising loop scan with Flow Match Euler scheduler.
- Added concurrent AOT XLA compilation across Qwen3, Flux transformer, and VAE.
- Implemented fast host-memory streaming weight converter for safetensors shards directly into NNX State PyTree.
- Optimized splash attention block sizes and Ulysses context parallelism sharding.
- Added comprehensive unit tests and end-to-end smoke test suite (generate_flux2klein_smoke_test.py).
@amepas
amepas force-pushed the optimizing-flux2klein branch from 9dbca46 to 9162a46 Compare August 13, 2026 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants