@@ -256,43 +256,49 @@ def put_data_on_devices(x, sharding):
256256 prompt_embeds_jax = put_data_on_devices (prompt_embeds_jax , data_sharding )
257257
258258 # ---------------------------------------------------------------------
259- # PHASE B: Denoising Loop (Flux Transformer)
259+ # PHASE B: Denoising Loop (Flux Transformer - Fused JAX fori_loop )
260260 # ---------------------------------------------------------------------
261261 max_logging .log (
262262 f"[PHASE B] Running { num_inference_steps } -step E2E Denoising Loop on a batch of { batch_size } images..."
263263 )
264264 t0 = time .perf_counter ()
265265
266- guidance_vec_val = None
267- vec_val = None
268-
269- for step_idx in range (num_inference_steps ):
270- timestep = scheduler_state .timesteps [step_idx ]
271- t_vec = jnp .array ([timestep / 1000.0 ] * batch_size )
272-
273- # Execute transformer forward pass step
274- model_output = self ._jitted_transformer_step (
275- params , latents_jax , img_ids_val , prompt_embeds_jax , txt_ids_val , vec_val , t_vec , guidance_vec_val
276- )
277-
278- # Update latents using FlowMatch step
279- latents_jax = self .scheduler .step (
280- state = scheduler_state ,
281- model_output = model_output .sample ,
282- timestep = scheduler_state .timesteps [step_idx ],
283- sample = latents_jax ,
284- ).prev_sample
285-
286- # Print progress
287- sigma_val = scheduler_state .sigmas [step_idx ]
288- max_logging .log (
289- f" -> Step { step_idx } : Timestep = { scheduler_state .timesteps [step_idx ]:.4f} , Sigma = { sigma_val :.4f} "
290- )
291-
266+ timesteps_array = scheduler_state .timesteps
267+ sigmas_array = scheduler_state .sigmas
268+
269+ @jax .jit
270+ def denoise_loop (t_params , latents , prompt_embeds , txt_ids , img_ids , timesteps , sigmas ):
271+ def step_fn (step_idx , current_latents ):
272+ t_val = timesteps [step_idx ] / 1000.0
273+ t_vec = jnp .full ((batch_size ,), t_val , dtype = current_latents .dtype )
274+ out = self .transformer .apply (
275+ {"params" : t_params },
276+ hidden_states = current_latents ,
277+ img_ids = img_ids ,
278+ encoder_hidden_states = prompt_embeds ,
279+ txt_ids = txt_ids ,
280+ pooled_projections = None ,
281+ timestep = t_vec ,
282+ guidance = None ,
283+ ).sample
284+ dt = sigmas [step_idx + 1 ] - sigmas [step_idx ]
285+ return current_latents + dt * out
286+
287+ return jax .lax .fori_loop (0 , num_inference_steps , step_fn , latents )
288+
289+ latents_jax = denoise_loop (
290+ params ,
291+ latents_jax ,
292+ prompt_embeds_jax ,
293+ txt_ids_val ,
294+ img_ids_val ,
295+ timesteps_array ,
296+ sigmas_array ,
297+ )
292298 latents_jax .block_until_ready ()
293299
294- trace ["denoise_loop" ] = time .perf_counter () - t0
295- max_logging .log (f" -> [TIMING] Denoising Loop (Flux): { trace ['denoise_loop' ]:.4f} seconds ⏱️" )
300+ trace ["denoise_loop" ] = time .perf_counter () - t0
301+ max_logging .log (f" -> [TIMING] Denoising Loop (Flux): { trace ['denoise_loop' ]:.4f} seconds ⏱️" )
296302
297303 # ---------------------------------------------------------------------
298304 # PHASE C: Decode Latents (VAE Decoder)
0 commit comments