ct-tranchau commited on
Commit
39cc007
Β·
verified Β·
1 Parent(s): 4668908

Add step-by-step ZeroGPU diagnostics

Browse files
Files changed (1) hide show
  1. app.py +74 -0
app.py CHANGED
@@ -124,6 +124,75 @@ def _embed(masks, img_rgb, df_base):
124
  raise
125
 
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  # ── helpers ──────────────────────────────────────────────────────────────────
128
 
129
  def read_um_per_px(tif_path):
@@ -379,6 +448,10 @@ with gr.Blocks(title="RootScope", **_blocks_kwargs) as demo:
379
  "until predictions stop changing.",
380
  )
381
  run_btn = gr.Button("Run RootScope", variant="primary")
 
 
 
 
382
 
383
  with gr.Column(scale=1):
384
  overlay = gr.Image(label="Predicted cell types", type="filepath",
@@ -433,6 +506,7 @@ with gr.Blocks(title="RootScope", **_blocks_kwargs) as demo:
433
  )
434
  model_pick.change(switch_model, [results_state, model_pick],
435
  [overlay, summary, stats_md, csv_btn])
 
436
 
437
  if __name__ == "__main__":
438
  launch_kwargs = {"theme": _THEME} if _THEME_ON_LAUNCH else {}
 
124
  raise
125
 
126
 
127
+ # ── ZeroGPU diagnostics ──────────────────────────────────────────────────────
128
+ # "GPU task aborted" means the worker process died, so nothing it printed
129
+ # survives. Each step below is its own @spaces.GPU call: whichever one fails to
130
+ # come back is the culprit.
131
+
132
+ @spaces.GPU(duration=60)
133
+ def _diag_alloc():
134
+ import torch
135
+ x = torch.zeros(2048, 2048, device="cuda")
136
+ return f"{torch.cuda.get_device_name(0)}, alloc ok, sum={float(x.sum())}"
137
+
138
+
139
+ @spaces.GPU(duration=60)
140
+ def _diag_devices():
141
+ import torch
142
+ out = []
143
+ try:
144
+ p = next(CELLPOSE_MODEL.net.parameters())
145
+ out.append(f"cellpose net on {p.device} ({p.dtype})")
146
+ except Exception as e:
147
+ out.append(f"cellpose net ERR {type(e).__name__}: {e}")
148
+ try:
149
+ p = next(DINOV2_MODEL.parameters())
150
+ out.append(f"dinov2 on {p.device}")
151
+ except Exception as e:
152
+ out.append(f"dinov2 ERR {type(e).__name__}: {e}")
153
+ out.append(f"torch {torch.__version__}")
154
+ return "; ".join(out)
155
+
156
+
157
+ @spaces.GPU(duration=120)
158
+ def _diag_cellpose():
159
+ import numpy as np
160
+ img = (np.random.rand(256, 256, 3) * 255).astype(np.uint8)
161
+ m = rs.stage_segment(img, gpu=True, cellpose_model=CELLPOSE_MODEL)
162
+ return f"segmented 256x256 noise -> {int(m.max())} labels, dtype {m.dtype}"
163
+
164
+
165
+ @spaces.GPU(duration=120)
166
+ def _diag_dino():
167
+ import numpy as np
168
+ from rootscope.cnn_embeddings import extract_cnn_embeddings
169
+ masks = np.zeros((128, 128), dtype=np.int32)
170
+ masks[20:60, 20:60] = 1
171
+ masks[70:110, 70:110] = 2
172
+ img = (np.random.rand(128, 128, 3) * 255).astype(np.uint8)
173
+ df = extract_cnn_embeddings(masks, img, use_gpu=True, model=DINOV2_MODEL)
174
+ return f"embedded {len(df)} cells, {df.shape[1] - 1} dims"
175
+
176
+
177
+ def run_diagnostics():
178
+ steps = [
179
+ ("1. CUDA allocation", _diag_alloc),
180
+ ("2. model devices", _diag_devices),
181
+ ("3. Cellpose-SAM on GPU", _diag_cellpose),
182
+ ("4. DINOv2 on GPU", _diag_dino),
183
+ ]
184
+ lines = []
185
+ for name, fn in steps:
186
+ try:
187
+ lines.append(f"PASS {name}: {fn()}")
188
+ except Exception as e:
189
+ lines.append(f"FAIL {name}: {type(e).__name__}: {e}")
190
+ lines.append("")
191
+ lines.append("^ this step is where it breaks.")
192
+ break
193
+ return "\n".join(lines)
194
+
195
+
196
  # ── helpers ──────────────────────────────────────────────────────────────────
197
 
198
  def read_um_per_px(tif_path):
 
448
  "until predictions stop changing.",
449
  )
450
  run_btn = gr.Button("Run RootScope", variant="primary")
451
+ with gr.Accordion("Diagnostics", open=False):
452
+ diag_btn = gr.Button("Test the GPU step by step")
453
+ diag_out = gr.Textbox(label="Result", lines=7,
454
+ show_copy_button=True)
455
 
456
  with gr.Column(scale=1):
457
  overlay = gr.Image(label="Predicted cell types", type="filepath",
 
506
  )
507
  model_pick.change(switch_model, [results_state, model_pick],
508
  [overlay, summary, stats_md, csv_btn])
509
+ diag_btn.click(run_diagnostics, None, diag_out)
510
 
511
  if __name__ == "__main__":
512
  launch_kwargs = {"theme": _THEME} if _THEME_ON_LAUNCH else {}