cpyang commited on
Commit
dc4f28d
Β·
verified Β·
1 Parent(s): dd87d68

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. app.py +7 -0
  2. backend.py +33 -11
  3. vendor/SchenkerDiff/inference.py +2 -2
app.py CHANGED
@@ -1,6 +1,13 @@
1
  """app.py – ProGress Music Generation Demo"""
2
  from __future__ import annotations
3
 
 
 
 
 
 
 
 
4
  import os
5
  import random
6
  import sys
 
1
  """app.py – ProGress Music Generation Demo"""
2
  from __future__ import annotations
3
 
4
+ # ZeroGPU: import `spaces` before torch so its CUDA-emulation hooks install
5
+ # first. No-op when not on ZeroGPU; absent (and skipped) in local dev.
6
+ try:
7
+ import spaces # noqa: F401
8
+ except Exception:
9
+ pass
10
+
11
  import os
12
  import random
13
  import sys
backend.py CHANGED
@@ -772,19 +772,21 @@ def device_info() -> str:
772
  cuda.is_available()/get_device_name does not initialise a CUDA context,
773
  so this is cheap to call at startup.
774
  """
 
 
 
 
 
 
 
 
775
  try:
776
  import torch
777
  if torch.cuda.is_available():
778
  return f"GPU Β· {torch.cuda.get_device_name(0)}"
779
  except Exception:
780
  pass
781
- # On a ZeroGPU Space the GPU is only visible inside the @spaces.GPU call, so
782
- # the main process reports no CUDA β€” surface the ZeroGPU runtime instead.
783
- try:
784
- import spaces # noqa: F401
785
- return "ZeroGPU (attached on demand)"
786
- except Exception:
787
- return "CPU"
788
 
789
 
790
  # ─── Module-level cache for SchenkerDiff inference ───────────────────────────
@@ -792,6 +794,13 @@ def device_info() -> str:
792
  # so successive batches in generate_until_target reuse them.
793
  _GEN_CACHE: dict = {}
794
 
 
 
 
 
 
 
 
795
 
796
  def _available_processed_idxs() -> list[int]:
797
  """Indices of processed .pt files actually on disk (for varied conditioning)."""
@@ -857,7 +866,10 @@ def _ensure_generation_setup(progress=None) -> dict:
857
  # (b) When no GPU is present, PL passes map_location=None, so default the
858
  # load to CPU.
859
  _orig_torch_load = torch.load
860
- _no_cuda = not torch.cuda.is_available()
 
 
 
861
  _cpu_dev = torch.device("cpu")
862
  def _patched_load(f, *a, **kw):
863
  kw["weights_only"] = False
@@ -879,7 +891,7 @@ def _ensure_generation_setup(progress=None) -> dict:
879
  # Pin the model + all generation tensors to one device chosen *now*.
880
  # Under ZeroGPU, CUDA only becomes available inside the @spaces.GPU call
881
  # (after import time), so we can't rely on the import-time config.DEVICE.
882
- dev = torch.device("cuda" if torch.cuda.is_available() else "cpu")
883
  model = model.to(dev)
884
  edim = int(model.limit_dist.E.shape[0])
885
 
@@ -1166,17 +1178,27 @@ def generate_until_target(
1166
 
1167
  Returns the (mutated or new) phrases_data dict.
1168
  """
 
1169
  try:
1170
  return _run_generation_gpu(target, batch_size, max_attempts_factor, progress, pool)
1171
  except Exception as gpu_err:
1172
- # GPU unavailable / failed β†’ reset any half-loaded state and retry on CPU.
 
 
 
 
 
1173
  _GEN_CACHE.clear()
 
1174
  if progress:
1175
  try:
1176
  progress(0.0, desc=f"GPU unavailable ({type(gpu_err).__name__}); running on CPU…")
1177
  except Exception:
1178
  pass
1179
- return _run_generation(target, batch_size, max_attempts_factor, progress, pool)
 
 
 
1180
 
1181
 
1182
  # Keep the old function name as a thin wrapper for back-compat.
 
772
  cuda.is_available()/get_device_name does not initialise a CUDA context,
773
  so this is cheap to call at startup.
774
  """
775
+ # On a ZeroGPU Space the GPU only exists inside @spaces.GPU calls; touching
776
+ # torch.cuda in the main process triggers a forbidden low-level CUDA init.
777
+ # Detect ZeroGPU via the `spaces` package FIRST and avoid torch.cuda there.
778
+ try:
779
+ import spaces # noqa: F401
780
+ return "ZeroGPU (attached on demand)"
781
+ except Exception:
782
+ pass
783
  try:
784
  import torch
785
  if torch.cuda.is_available():
786
  return f"GPU Β· {torch.cuda.get_device_name(0)}"
787
  except Exception:
788
  pass
789
+ return "CPU"
 
 
 
 
 
 
790
 
791
 
792
  # ─── Module-level cache for SchenkerDiff inference ───────────────────────────
 
794
  # so successive batches in generate_until_target reuse them.
795
  _GEN_CACHE: dict = {}
796
 
797
+ # When True, generation is pinned to CPU regardless of what torch.cuda reports.
798
+ # Needed for the ZeroGPU CPU-fallback path: ZeroGPU's emulated torch.cuda says
799
+ # a GPU is available even in the main process, so acting on it there would
800
+ # trigger a forbidden low-level CUDA init. The fallback sets this before
801
+ # retrying on CPU.
802
+ _FORCE_CPU: bool = False
803
+
804
 
805
  def _available_processed_idxs() -> list[int]:
806
  """Indices of processed .pt files actually on disk (for varied conditioning)."""
 
866
  # (b) When no GPU is present, PL passes map_location=None, so default the
867
  # load to CPU.
868
  _orig_torch_load = torch.load
869
+ # _FORCE_CPU wins over the (possibly emulated) cuda.is_available() so the
870
+ # CPU-fallback path never initialises CUDA in the ZeroGPU main process.
871
+ use_cuda = (not _FORCE_CPU) and torch.cuda.is_available()
872
+ _no_cuda = not use_cuda
873
  _cpu_dev = torch.device("cpu")
874
  def _patched_load(f, *a, **kw):
875
  kw["weights_only"] = False
 
891
  # Pin the model + all generation tensors to one device chosen *now*.
892
  # Under ZeroGPU, CUDA only becomes available inside the @spaces.GPU call
893
  # (after import time), so we can't rely on the import-time config.DEVICE.
894
+ dev = torch.device("cuda") if use_cuda else _cpu_dev
895
  model = model.to(dev)
896
  edim = int(model.limit_dist.E.shape[0])
897
 
 
1178
 
1179
  Returns the (mutated or new) phrases_data dict.
1180
  """
1181
+ global _FORCE_CPU
1182
  try:
1183
  return _run_generation_gpu(target, batch_size, max_attempts_factor, progress, pool)
1184
  except Exception as gpu_err:
1185
+ # GPU unavailable / failed β†’ retry on CPU. Pin to CPU first: under
1186
+ # ZeroGPU the main process must never touch CUDA (emulated is_available()
1187
+ # reports True), so _FORCE_CPU stops setup from initialising the GPU here.
1188
+ import traceback
1189
+ print("GPU generation failed; falling back to CPU:\n" + traceback.format_exc(),
1190
+ file=sys.stderr, flush=True)
1191
  _GEN_CACHE.clear()
1192
+ _FORCE_CPU = True
1193
  if progress:
1194
  try:
1195
  progress(0.0, desc=f"GPU unavailable ({type(gpu_err).__name__}); running on CPU…")
1196
  except Exception:
1197
  pass
1198
+ try:
1199
+ return _run_generation(target, batch_size, max_attempts_factor, progress, pool)
1200
+ finally:
1201
+ _FORCE_CPU = False
1202
 
1203
 
1204
  # Keep the old function name as a thin wrapper for back-compat.
vendor/SchenkerDiff/inference.py CHANGED
@@ -34,8 +34,8 @@ def initialize_model():
34
 
35
  warnings.filterwarnings("ignore", category=PossibleUserWarning)
36
  torch.set_float32_matmul_precision('medium')
37
- if torch.cuda.is_available():
38
- torch.cuda.empty_cache()
39
 
40
  if not dist.is_initialized():
41
  try:
 
34
 
35
  warnings.filterwarnings("ignore", category=PossibleUserWarning)
36
  torch.set_float32_matmul_precision('medium')
37
+ # NB: no torch.cuda.empty_cache() here β€” under ZeroGPU's emulated main process
38
+ # cuda.is_available() is True but any real CUDA call triggers a forbidden init.
39
 
40
  if not dist.is_initialized():
41
  try: