Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
File size: 5,681 Bytes
1ba7218 0ac9178 1ba7218 a6beab2 0ac9178 a6beab2 0ac9178 a6beab2 0ac9178 a6beab2 0ac9178 a6beab2 0ac9178 a6beab2 0ac9178 a6beab2 0ac9178 1ba7218 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | """Shared evaluation runtime: device selection, ZeroGPU bypass, CPU thread hints."""
from __future__ import annotations
import importlib.util
import os
import sys
import types
_cpu_thread_settings_applied = False
_torchcodec_patch_applied = False
def _force_transformers_torchcodec_unavailable() -> None:
"""Tell transformers to use librosa/soundfile for audio, not torchcodec."""
try:
import transformers.utils.import_utils as import_utils
import_utils._torchcodec_available = False
def _is_torchcodec_available() -> bool:
return False
import_utils.is_torchcodec_available = _is_torchcodec_available
except Exception:
pass
def disable_broken_torchcodec() -> None:
"""
Transformers prefers torchcodec for ``load_audio`` when the package is installed,
but Hub Job images often lack FFmpeg shared libraries (libavutil.so.*).
If torchcodec cannot load, mark it unavailable so transformers falls back to
librosa / soundfile.
"""
global _torchcodec_patch_applied
if _torchcodec_patch_applied:
return
_torchcodec_patch_applied = True
force_off = os.environ.get("FFASR_DISABLE_TORCHCODEC", "").strip().lower() in (
"1",
"true",
"yes",
"on",
)
if force_off or importlib.util.find_spec("torchcodec") is None:
if force_off and importlib.util.find_spec("torchcodec") is not None:
print(
"[ffasr] FFASR_DISABLE_TORCHCODEC=1: using librosa/soundfile for audio "
"(torchcodec disabled on Hub Jobs).",
flush=True,
)
_force_transformers_torchcodec_unavailable()
return
try:
from torchcodec.decoders import AudioDecoder # noqa: F401
except (OSError, RuntimeError, ImportError, AttributeError):
print(
"[ffasr] torchcodec native libraries unavailable; "
"transformers will use librosa/soundfile for audio.",
flush=True,
)
_force_transformers_torchcodec_unavailable()
stub = types.ModuleType("torchcodec")
stub.__dict__["decoders"] = types.ModuleType("torchcodec.decoders")
sys.modules["torchcodec"] = stub
sys.modules["torchcodec.decoders"] = stub.__dict__["decoders"]
except Exception:
_force_transformers_torchcodec_unavailable()
def patch_transformers_load_audio_for_paths() -> None:
"""
Route ``transformers.audio_utils.load_audio`` for file paths through soundfile
(no torchcodec / FFmpeg). Safe to call before loading user custom scripts.
"""
try:
import numpy as np
import transformers.audio_utils as audio_utils
from backends._audio_utils import load_wav_mono
_orig = audio_utils.load_audio
def _load_audio(audio, sampling_rate=16000, timeout=None):
if isinstance(audio, str):
return load_wav_mono(audio, sampling_rate=int(sampling_rate))
if isinstance(audio, np.ndarray):
return audio
return _orig(audio, sampling_rate=sampling_rate, timeout=timeout)
audio_utils.load_audio = _load_audio
except Exception:
pass
def zerogpu_disabled() -> bool:
"""When True, never wrap evaluation in ``spaces.GPU`` even if ``spaces`` is installed."""
return os.environ.get("FFASR_DISABLE_ZEROGPU", "").strip().lower() in (
"1",
"true",
"yes",
"on",
)
def spaces_available() -> bool:
return importlib.util.find_spec("spaces") is not None
def use_spaces_gpu_decorator() -> bool:
"""Use ZeroGPU decorator only when ``spaces`` is present and not explicitly disabled."""
return spaces_available() and not zerogpu_disabled()
def resolve_eval_devices() -> tuple[str, int]:
"""
Return ``(device_str, device_int)`` for backends / HF pipeline.
``FFASR_DEVICE`` (default ``auto``): ``cpu`` | ``cuda`` | ``auto``.
``auto`` uses CUDA when available, else CPU.
"""
choice = (os.environ.get("FFASR_DEVICE", "auto") or "auto").strip().lower()
if choice not in ("auto", "cpu", "cuda"):
choice = "auto"
import torch
has_cuda = torch.cuda.is_available()
if choice == "cpu":
return "cpu", -1
if choice == "cuda":
if not has_cuda:
raise RuntimeError("FFASR_DEVICE=cuda but torch.cuda.is_available() is False.")
return "cuda", 0
# auto
if has_cuda:
return "cuda", 0
return "cpu", -1
def apply_cpu_thread_settings_once() -> None:
"""
Apply optional torch thread limits from env (once per process).
- ``FFASR_TORCH_NUM_THREADS`` — passed to ``torch.set_num_threads`` if a positive int.
- ``FFASR_TORCH_NUM_INTEROP_THREADS`` — ``torch.set_num_interop_threads`` if set.
For BLAS/OpenMP, operators typically set ``OMP_NUM_THREADS`` / ``MKL_NUM_THREADS``
in the Space environment (see docs); those are read by the native libs at load time.
"""
global _cpu_thread_settings_applied
if _cpu_thread_settings_applied:
return
_cpu_thread_settings_applied = True
import torch
raw = os.environ.get("FFASR_TORCH_NUM_THREADS", "").strip()
if raw.isdigit():
n = int(raw)
if n > 0:
try:
torch.set_num_threads(n)
except Exception:
pass
raw_i = os.environ.get("FFASR_TORCH_NUM_INTEROP_THREADS", "").strip()
if raw_i.isdigit():
ni = int(raw_i)
if ni > 0:
try:
torch.set_num_interop_threads(ni)
except Exception:
pass
|