Spaces:
Sleeping
Sleeping
Merge main into ja: apply Experimental-Turbo changes to Japanese space
Browse files- app.py +43 -6
- static/mode_toggle.js +1 -1
- templates/app.html +2 -2
app.py
CHANGED
|
@@ -4,6 +4,9 @@ import time
|
|
| 4 |
import threading
|
| 5 |
import traceback
|
| 6 |
|
|
|
|
|
|
|
|
|
|
| 7 |
import gradio as gr
|
| 8 |
import numpy as np
|
| 9 |
import spaces
|
|
@@ -34,6 +37,33 @@ print("torch.__version__ =", torch.__version__, flush=True)
|
|
| 34 |
print("Using device:", device, flush=True)
|
| 35 |
print(f"CUDA device_count={torch.cuda.device_count()}, is_available={torch.cuda.is_available()}", flush=True)
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
# TF32 matmul: ~10-15% free speedup on Ampere/Hopper (bfloat16 accumulation paths benefit too)
|
| 38 |
torch.backends.cuda.matmul.allow_tf32 = True
|
| 39 |
torch.backends.cudnn.allow_tf32 = True
|
|
@@ -70,7 +100,7 @@ _hb = _start_heartbeat("transformer")
|
|
| 70 |
_transformer = QwenImageTransformer2DModel.from_pretrained(
|
| 71 |
"prithivMLmods/Qwen-Image-Edit-Rapid-AIO-V23",
|
| 72 |
torch_dtype=dtype,
|
| 73 |
-
device_map="
|
| 74 |
)
|
| 75 |
_hb.set()
|
| 76 |
print(f"[startup] transformer loaded in {time.perf_counter()-_t0_load:.1f}s", flush=True)
|
|
@@ -82,7 +112,7 @@ pipe = QwenImageEditPlusPipeline.from_pretrained(
|
|
| 82 |
"FireRedTeam/FireRed-Image-Edit-1.1",
|
| 83 |
transformer=_transformer,
|
| 84 |
torch_dtype=dtype,
|
| 85 |
-
)
|
| 86 |
_hb.set()
|
| 87 |
print(f"[startup] pipeline loaded in {time.perf_counter()-_t1_load:.1f}s", flush=True)
|
| 88 |
|
|
@@ -372,11 +402,15 @@ def _infer_gpu(pil_images, prompt, seed, guidance_scale, steps, width, height, m
|
|
| 372 |
print(f"[infer] GPU: {p.name}, total={p.total_memory/1024**3:.1f}GB, cap={p.major}.{p.minor}")
|
| 373 |
torch.cuda.reset_peak_memory_stats()
|
| 374 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
print(f"[infer] {_gpu_mem_str(_cuda_ok)} — t={time.perf_counter()-t0:.1f}s")
|
| 376 |
|
| 377 |
-
torch.cuda.empty_cache()
|
| 378 |
-
print(f"[infer] cache cleared — {_gpu_mem_str(_cuda_ok)}")
|
| 379 |
-
|
| 380 |
print(f"[infer] {len(pil_images)} image(s) pre-decoded, output={width}x{height}, seed={seed}")
|
| 381 |
|
| 382 |
generator = torch.Generator(device=device).manual_seed(seed)
|
|
@@ -418,6 +452,9 @@ def _infer_gpu(pil_images, prompt, seed, guidance_scale, steps, width, height, m
|
|
| 418 |
timer.print_timings()
|
| 419 |
raise
|
| 420 |
finally:
|
|
|
|
|
|
|
|
|
|
| 421 |
gc.collect()
|
| 422 |
torch.cuda.empty_cache()
|
| 423 |
print(f"[infer] ===== END t={time.perf_counter()-t0:.1f}s =====")
|
|
@@ -432,7 +469,7 @@ with gr.Blocks() as demo:
|
|
| 432 |
guidance_scale = gr.Slider(minimum=1.0, maximum=10.0, step=0.1, value=1.0, elem_id="gradio-guidance", elem_classes="hidden-input", container=False)
|
| 433 |
steps = gr.Slider(minimum=1, maximum=50, step=1, value=4, elem_id="gradio-steps", elem_classes="hidden-input", container=False)
|
| 434 |
mode = gr.Textbox(value="fast", elem_id="gradio-mode", elem_classes="hidden-input", container=False)
|
| 435 |
-
gpu_duration = gr.Slider(minimum=10, maximum=120, step=5, value=
|
| 436 |
result = gr.Image(elem_id="gradio-result", elem_classes="hidden-input", container=False, format="png")
|
| 437 |
|
| 438 |
example_idx = gr.Textbox(value="", elem_id="example-idx-input", elem_classes="hidden-input", container=False)
|
|
|
|
| 4 |
import threading
|
| 5 |
import traceback
|
| 6 |
|
| 7 |
+
# cudaMallocAsync bypasses NVML memory queries that fail on MIG GPU instances
|
| 8 |
+
os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "backend:cudaMallocAsync")
|
| 9 |
+
|
| 10 |
import gradio as gr
|
| 11 |
import numpy as np
|
| 12 |
import spaces
|
|
|
|
| 37 |
print("Using device:", device, flush=True)
|
| 38 |
print(f"CUDA device_count={torch.cuda.device_count()}, is_available={torch.cuda.is_available()}", flush=True)
|
| 39 |
|
| 40 |
+
|
| 41 |
+
def _log_env():
|
| 42 |
+
import importlib.metadata as _meta
|
| 43 |
+
if torch.cuda.is_available():
|
| 44 |
+
p = torch.cuda.get_device_properties(0)
|
| 45 |
+
print(f"[env] GPU: {p.name}, VRAM={p.total_memory/1024**3:.1f}GB, cap={p.major}.{p.minor}", flush=True)
|
| 46 |
+
print(f"[env] CUDA (torch build): {torch.version.cuda}", flush=True)
|
| 47 |
+
print(f"[env] cuDNN: {torch.backends.cudnn.version()}", flush=True)
|
| 48 |
+
for pkg in ["spaces", "diffusers", "transformers", "gradio", "accelerate", "peft", "torchvision"]:
|
| 49 |
+
try:
|
| 50 |
+
print(f"[env] {pkg}=={_meta.version(pkg)}", flush=True)
|
| 51 |
+
except Exception as e:
|
| 52 |
+
print(f"[env] {pkg}==? ({e})", flush=True)
|
| 53 |
+
try:
|
| 54 |
+
mem = {}
|
| 55 |
+
with open("/proc/meminfo") as f:
|
| 56 |
+
for line in f:
|
| 57 |
+
k, v = line.split(":", 1)
|
| 58 |
+
mem[k.strip()] = v.strip()
|
| 59 |
+
total_gb = int(mem["MemTotal"].split()[0]) / 1024**2
|
| 60 |
+
avail_gb = int(mem["MemAvailable"].split()[0]) / 1024**2
|
| 61 |
+
print(f"[env] RAM: {total_gb:.0f}GB total, {avail_gb:.0f}GB available", flush=True)
|
| 62 |
+
except Exception as e:
|
| 63 |
+
print(f"[env] RAM: unavailable ({e})", flush=True)
|
| 64 |
+
|
| 65 |
+
_log_env()
|
| 66 |
+
|
| 67 |
# TF32 matmul: ~10-15% free speedup on Ampere/Hopper (bfloat16 accumulation paths benefit too)
|
| 68 |
torch.backends.cuda.matmul.allow_tf32 = True
|
| 69 |
torch.backends.cudnn.allow_tf32 = True
|
|
|
|
| 100 |
_transformer = QwenImageTransformer2DModel.from_pretrained(
|
| 101 |
"prithivMLmods/Qwen-Image-Edit-Rapid-AIO-V23",
|
| 102 |
torch_dtype=dtype,
|
| 103 |
+
device_map="cpu",
|
| 104 |
)
|
| 105 |
_hb.set()
|
| 106 |
print(f"[startup] transformer loaded in {time.perf_counter()-_t0_load:.1f}s", flush=True)
|
|
|
|
| 112 |
"FireRedTeam/FireRed-Image-Edit-1.1",
|
| 113 |
transformer=_transformer,
|
| 114 |
torch_dtype=dtype,
|
| 115 |
+
)
|
| 116 |
_hb.set()
|
| 117 |
print(f"[startup] pipeline loaded in {time.perf_counter()-_t1_load:.1f}s", flush=True)
|
| 118 |
|
|
|
|
| 402 |
print(f"[infer] GPU: {p.name}, total={p.total_memory/1024**3:.1f}GB, cap={p.major}.{p.minor}")
|
| 403 |
torch.cuda.reset_peak_memory_stats()
|
| 404 |
|
| 405 |
+
# Sequential offload: only the component currently doing work (text_encoder,
|
| 406 |
+
# then transformer, then vae — see model_cpu_offload_seq) sits on GPU at a
|
| 407 |
+
# time, instead of the full ~37GB pipeline resident simultaneously. Needed
|
| 408 |
+
# to fit on smaller MIG slices (e.g. the 47GB 2g.48gb partition) without OOM.
|
| 409 |
+
if getattr(pipe.transformer, "_hf_hook", None) is None:
|
| 410 |
+
pipe.enable_model_cpu_offload(device=device)
|
| 411 |
+
print(f"[infer] enabled sequential cpu offload on {device}")
|
| 412 |
print(f"[infer] {_gpu_mem_str(_cuda_ok)} — t={time.perf_counter()-t0:.1f}s")
|
| 413 |
|
|
|
|
|
|
|
|
|
|
| 414 |
print(f"[infer] {len(pil_images)} image(s) pre-decoded, output={width}x{height}, seed={seed}")
|
| 415 |
|
| 416 |
generator = torch.Generator(device=device).manual_seed(seed)
|
|
|
|
| 452 |
timer.print_timings()
|
| 453 |
raise
|
| 454 |
finally:
|
| 455 |
+
# No manual pipe.to("cpu") — that fights the offload hooks' own device
|
| 456 |
+
# bookkeeping. Hooks already return each component to CPU after its
|
| 457 |
+
# forward; empty_cache() just reclaims the freed GPU blocks.
|
| 458 |
gc.collect()
|
| 459 |
torch.cuda.empty_cache()
|
| 460 |
print(f"[infer] ===== END t={time.perf_counter()-t0:.1f}s =====")
|
|
|
|
| 469 |
guidance_scale = gr.Slider(minimum=1.0, maximum=10.0, step=0.1, value=1.0, elem_id="gradio-guidance", elem_classes="hidden-input", container=False)
|
| 470 |
steps = gr.Slider(minimum=1, maximum=50, step=1, value=4, elem_id="gradio-steps", elem_classes="hidden-input", container=False)
|
| 471 |
mode = gr.Textbox(value="fast", elem_id="gradio-mode", elem_classes="hidden-input", container=False)
|
| 472 |
+
gpu_duration = gr.Slider(minimum=10, maximum=120, step=5, value=30, elem_id="gradio-gpu-duration", elem_classes="hidden-input", container=False)
|
| 473 |
result = gr.Image(elem_id="gradio-result", elem_classes="hidden-input", container=False, format="png")
|
| 474 |
|
| 475 |
example_idx = gr.Textbox(value="", elem_id="example-idx-input", elem_classes="hidden-input", container=False)
|
static/mode_toggle.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
() => {
|
| 2 |
window.__selectedMode = 'fast';
|
| 3 |
-
var MODE_GPU_DURATION = { fast:
|
| 4 |
window.__setMode = function(m) {
|
| 5 |
window.__selectedMode = m;
|
| 6 |
var fast = document.getElementById('mode-btn-fast');
|
|
|
|
| 1 |
() => {
|
| 2 |
window.__selectedMode = 'fast';
|
| 3 |
+
var MODE_GPU_DURATION = { fast: 30, high_detail: 60 };
|
| 4 |
window.__setMode = function(m) {
|
| 5 |
window.__selectedMode = m;
|
| 6 |
var fast = document.getElementById('mode-btn-fast');
|
templates/app.html
CHANGED
|
@@ -120,8 +120,8 @@
|
|
| 120 |
<div class="settings-group-body">
|
| 121 |
<div class="slider-row">
|
| 122 |
<label>GPU時間(秒)</label>
|
| 123 |
-
<input type="range" id="custom-gpu-duration" min="10" max="120" step="5" value="
|
| 124 |
-
<span class="slider-val" id="custom-gpu-duration-val">
|
| 125 |
</div>
|
| 126 |
<div class="slider-row">
|
| 127 |
<label>シード</label>
|
|
|
|
| 120 |
<div class="settings-group-body">
|
| 121 |
<div class="slider-row">
|
| 122 |
<label>GPU時間(秒)</label>
|
| 123 |
+
<input type="range" id="custom-gpu-duration" min="10" max="120" step="5" value="30">
|
| 124 |
+
<span class="slider-val" id="custom-gpu-duration-val">30</span>
|
| 125 |
</div>
|
| 126 |
<div class="slider-row">
|
| 127 |
<label>シード</label>
|