WaveCut commited on
Commit
b9dcf01
verified
1 Parent(s): 0c9aa3f

Add detailed generation timing summary

Browse files
Files changed (3) hide show
  1. .DS_Store +0 -0
  2. app.py +97 -8
  3. sefi/runner.py +3 -0
.DS_Store DELETED
Binary file (6.15 kB)
 
app.py CHANGED
@@ -339,6 +339,49 @@ def _format_seconds(seconds: float) -> str:
339
  return f"{secs}s"
340
 
341
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  def model_defaults(model_key: str):
343
  preset = MODEL_PRESETS[model_key]
344
  return (
@@ -429,14 +472,27 @@ def generate(
429
  torch.backends.cuda.matmul.allow_tf32 = True
430
 
431
  progress(0, desc=f"Loading {preset.label}")
 
 
432
  pipe = _load_pipe(model_key)
433
- denoise_started_at = time.monotonic()
434
- progress(0, desc=f"Denoising 0/{steps} steps")
 
 
 
435
 
436
  def report_step(step: int, total: int) -> None:
 
437
  total = max(1, int(total))
438
  step = min(max(0, int(step)), total)
439
- elapsed = time.monotonic() - denoise_started_at
 
 
 
 
 
 
 
440
  remaining = 0.0
441
  if step > 0:
442
  remaining = (elapsed / step) * (total - step)
@@ -456,6 +512,7 @@ def generate(
456
  seed=int(seed),
457
  progress_callback=report_step,
458
  )
 
459
  progress(1, desc="Finalizing image")
460
  except Exception as exc:
461
  traceback.print_exc()
@@ -464,12 +521,27 @@ def generate(
464
  if not images:
465
  return None, "Generation finished without an image.", seed
466
 
 
 
 
 
 
 
467
  return (
468
  images[0],
469
- (
470
- f"Generated with `{preset.repo_id}` at {width}x{height}, "
471
- f"{steps} steps, guidance {guidance_scale}, seed {seed}. "
472
- f"Total time: {_format_seconds(time.monotonic() - request_started_at)}."
 
 
 
 
 
 
 
 
 
473
  ),
474
  seed,
475
  )
@@ -506,6 +578,22 @@ APP_CSS = """
506
  white-space: normal;
507
  line-height: 1.35;
508
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509
  """
510
 
511
 
@@ -570,7 +658,8 @@ guidance-1.0 setting, and 5B RL is the reinforced-learning checkpoint.
570
  f"Selected `{MODEL_PRESETS[DEFAULT_MODEL].repo_id}`. Defaults: "
571
  f"{MODEL_PRESETS[DEFAULT_MODEL].steps} steps, "
572
  f"guidance {MODEL_PRESETS[DEFAULT_MODEL].guidance}."
573
- )
 
574
  )
575
 
576
  examples = gr.Dataset(
 
339
  return f"{secs}s"
340
 
341
 
342
+ def _format_timing(seconds: float) -> str:
343
+ seconds = max(0.0, float(seconds))
344
+ if seconds < 10:
345
+ return f"{seconds:.1f}s"
346
+ return _format_seconds(seconds)
347
+
348
+
349
+ def _format_generation_summary(
350
+ *,
351
+ preset: ModelPreset,
352
+ width: int,
353
+ height: int,
354
+ steps: int,
355
+ guidance_scale: float,
356
+ seed: int,
357
+ total_seconds: float,
358
+ model_load_seconds: float,
359
+ model_was_loaded: bool,
360
+ setup_seconds: float,
361
+ denoise_seconds: float,
362
+ decode_seconds: float,
363
+ ) -> str:
364
+ if denoise_seconds > 0 and steps > 0:
365
+ speed = f"{steps / denoise_seconds:.2f} steps/s ({denoise_seconds / steps:.2f}s/step)"
366
+ else:
367
+ speed = "n/a"
368
+ load_note = "already in memory" if model_was_loaded else "download/load/switch"
369
+
370
+ return (
371
+ "### Generation summary\n\n"
372
+ f"`{preset.repo_id}` 路 {width}x{height} 路 {steps} steps 路 "
373
+ f"guidance {guidance_scale} 路 seed {seed}\n\n"
374
+ "| Phase | Time |\n"
375
+ "| --- | ---: |\n"
376
+ f"| Total backend time | {_format_timing(total_seconds)} |\n"
377
+ f"| Model {load_note} | {_format_timing(model_load_seconds)} |\n"
378
+ f"| Prompt + latent setup | {_format_timing(setup_seconds)} |\n"
379
+ f"| Raw denoising | {_format_timing(denoise_seconds)} |\n"
380
+ f"| Decode + output | {_format_timing(decode_seconds)} |\n"
381
+ f"| Raw denoising speed | {speed} |\n"
382
+ )
383
+
384
+
385
  def model_defaults(model_key: str):
386
  preset = MODEL_PRESETS[model_key]
387
  return (
 
472
  torch.backends.cuda.matmul.allow_tf32 = True
473
 
474
  progress(0, desc=f"Loading {preset.label}")
475
+ model_was_loaded = _LOADED_PIPE is not None and _LOADED_MODEL_KEY == model_key
476
+ load_started_at = time.monotonic()
477
  pipe = _load_pipe(model_key)
478
+ load_finished_at = time.monotonic()
479
+ pipe_started_at = load_finished_at
480
+ denoise_started_at: float | None = None
481
+ last_denoise_step_at: float | None = None
482
+ progress(0, desc="Preparing prompt and latents")
483
 
484
  def report_step(step: int, total: int) -> None:
485
+ nonlocal denoise_started_at, last_denoise_step_at
486
  total = max(1, int(total))
487
  step = min(max(0, int(step)), total)
488
+ now = time.monotonic()
489
+ if step == 0:
490
+ denoise_started_at = now
491
+ if denoise_started_at is None:
492
+ denoise_started_at = now
493
+ if step > 0:
494
+ last_denoise_step_at = now
495
+ elapsed = now - denoise_started_at
496
  remaining = 0.0
497
  if step > 0:
498
  remaining = (elapsed / step) * (total - step)
 
512
  seed=int(seed),
513
  progress_callback=report_step,
514
  )
515
+ pipe_finished_at = time.monotonic()
516
  progress(1, desc="Finalizing image")
517
  except Exception as exc:
518
  traceback.print_exc()
 
521
  if not images:
522
  return None, "Generation finished without an image.", seed
523
 
524
+ request_finished_at = time.monotonic()
525
+ if denoise_started_at is None:
526
+ denoise_started_at = pipe_started_at
527
+ if last_denoise_step_at is None:
528
+ last_denoise_step_at = denoise_started_at
529
+
530
  return (
531
  images[0],
532
+ _format_generation_summary(
533
+ preset=preset,
534
+ width=width,
535
+ height=height,
536
+ steps=steps,
537
+ guidance_scale=guidance_scale,
538
+ seed=seed,
539
+ total_seconds=request_finished_at - request_started_at,
540
+ model_load_seconds=load_finished_at - load_started_at,
541
+ model_was_loaded=model_was_loaded,
542
+ setup_seconds=denoise_started_at - pipe_started_at,
543
+ denoise_seconds=last_denoise_step_at - denoise_started_at,
544
+ decode_seconds=pipe_finished_at - last_denoise_step_at,
545
  ),
546
  seed,
547
  )
 
578
  white-space: normal;
579
  line-height: 1.35;
580
  }
581
+
582
+ #generation_status table {
583
+ width: 100%;
584
+ margin-top: 0.5rem;
585
+ }
586
+
587
+ #generation_status th,
588
+ #generation_status td {
589
+ padding: 6px 8px;
590
+ }
591
+
592
+ #generation_status th:last-child,
593
+ #generation_status td:last-child {
594
+ text-align: right;
595
+ white-space: nowrap;
596
+ }
597
  """
598
 
599
 
 
658
  f"Selected `{MODEL_PRESETS[DEFAULT_MODEL].repo_id}`. Defaults: "
659
  f"{MODEL_PRESETS[DEFAULT_MODEL].steps} steps, "
660
  f"guidance {MODEL_PRESETS[DEFAULT_MODEL].guidance}."
661
+ ),
662
+ elem_id="generation_status",
663
  )
664
 
665
  examples = gr.Dataset(
sefi/runner.py CHANGED
@@ -678,6 +678,9 @@ class SEFIInferenceRunner:
678
  u_sem_raw_schedule=u_sem_raw_schedule,
679
  )
680
 
 
 
 
681
  for step in range(num_inference_steps):
682
  u_sem_raw_cur = torch.full(
683
  (batch_size,),
 
678
  u_sem_raw_schedule=u_sem_raw_schedule,
679
  )
680
 
681
+ if progress_callback is not None:
682
+ progress_callback(0, num_inference_steps)
683
+
684
  for step in range(num_inference_steps):
685
  u_sem_raw_cur = torch.full(
686
  (batch_size,),