lsmpp commited on
Commit
dbc3379
·
verified ·
1 Parent(s): 87ade98

Keep CPU inference safe across ZeroGPU forks and size GPU requests per task

Browse files
Files changed (3) hide show
  1. app.py +6 -2
  2. pixtext_ocr.py +2 -1
  3. space.py +17 -3
app.py CHANGED
@@ -212,7 +212,9 @@ def detect(session, jid, request: DetectRequest):
212
  import torch
213
  from pixtext_ocr import detect_words
214
 
215
- torch.set_num_threads(4)
 
 
216
  root = ocr_root(jid)
217
  update_job(jid, message="Detecting words and reading text", progress=0.3)
218
  with Image.open(session["directory"] / "source.png") as image:
@@ -229,7 +231,9 @@ def refine(session, jid, request: RefineRequest, progress_report=None):
229
 
230
  if not torch.cuda.is_available():
231
  raise RuntimeError("Refinement needs a CUDA GPU. Detection and box editing are ready to use.")
232
- torch.set_num_threads(4)
 
 
233
  if os.environ.get("PIXTEXT_GPU_MEMORY_FRACTION"):
234
  torch.cuda.set_per_process_memory_fraction(float(os.environ["PIXTEXT_GPU_MEMORY_FRACTION"]))
235
  if PIPELINE_VARIANT != request.variant:
 
212
  import torch
213
  from pixtext_ocr import detect_words
214
 
215
+ threads = int(os.environ.get("PIXTEXT_CPU_THREADS", "4"))
216
+ if torch.get_num_threads() != threads:
217
+ torch.set_num_threads(threads)
218
  root = ocr_root(jid)
219
  update_job(jid, message="Detecting words and reading text", progress=0.3)
220
  with Image.open(session["directory"] / "source.png") as image:
 
231
 
232
  if not torch.cuda.is_available():
233
  raise RuntimeError("Refinement needs a CUDA GPU. Detection and box editing are ready to use.")
234
+ threads = int(os.environ.get("PIXTEXT_CPU_THREADS", "4"))
235
+ if torch.get_num_threads() != threads:
236
+ torch.set_num_threads(threads)
237
  if os.environ.get("PIXTEXT_GPU_MEMORY_FRACTION"):
238
  torch.cuda.set_per_process_memory_fraction(float(os.environ["PIXTEXT_GPU_MEMORY_FRACTION"]))
239
  if PIPELINE_VARIANT != request.variant:
pixtext_ocr.py CHANGED
@@ -8,6 +8,7 @@ from __future__ import annotations
8
  import hashlib
9
  import json
10
  import math
 
11
  from functools import lru_cache
12
  from pathlib import Path
13
 
@@ -82,7 +83,7 @@ class WordOCR:
82
  )
83
  self.detector.eval()
84
  options = ort.SessionOptions()
85
- options.intra_op_num_threads = 4
86
  options.inter_op_num_threads = 1
87
  self.recognizer = ort.InferenceSession(
88
  str(rec_path), sess_options=options, providers=["CPUExecutionProvider"]
 
8
  import hashlib
9
  import json
10
  import math
11
+ import os
12
  from functools import lru_cache
13
  from pathlib import Path
14
 
 
83
  )
84
  self.detector.eval()
85
  options = ort.SessionOptions()
86
+ options.intra_op_num_threads = int(os.environ.get("PIXTEXT_CPU_THREADS", "4"))
87
  options.inter_op_num_threads = 1
88
  self.recognizer = ort.InferenceSession(
89
  str(rec_path), sess_options=options, providers=["CPUExecutionProvider"]
space.py CHANGED
@@ -3,6 +3,9 @@
3
  import os
4
 
5
  os.environ["PIXTEXT_GRADIO"] = "1"
 
 
 
6
  os.environ.setdefault("HF_HUB_DISABLE_TELEMETRY", "1")
7
 
8
  # Import before torch so ZeroGPU can enable its CUDA staging mode.
@@ -26,7 +29,7 @@ def load_models():
26
  from pixtext import PixTextPipeline
27
  from huggingface_hub import snapshot_download
28
 
29
- torch.set_num_threads(4)
30
  if not torch.cuda.is_available() and not spaces.config.Config.zero_gpu:
31
  return {}
32
  pipelines = {}
@@ -47,8 +50,16 @@ def load_models():
47
  PIPELINES = load_models()
48
 
49
 
50
- @spaces.GPU(duration=120)
 
 
 
 
 
 
 
51
  def gpu_refine(directory: str, size: list[int], jid: str, payload: str):
 
52
  started = time.perf_counter()
53
  request = studio.RefineRequest.model_validate_json(payload)
54
  studio.PIPELINE = PIPELINES.get(request.variant)
@@ -56,10 +67,13 @@ def gpu_refine(directory: str, size: list[int], jid: str, payload: str):
56
  progress = gr.Progress()
57
 
58
  def report(**values):
59
- progress(values.get("progress", 0), desc=values.get("message", "Refining"))
 
 
60
 
61
  result = studio.refine({"directory": Path(directory), "size": size}, jid, request, report)
62
  result["elapsed"] = round(time.perf_counter() - started, 2)
 
63
  return result
64
 
65
 
 
3
  import os
4
 
5
  os.environ["PIXTEXT_GRADIO"] = "1"
6
+ os.environ.setdefault("PIXTEXT_CPU_THREADS", "1")
7
+ os.environ.setdefault("OMP_NUM_THREADS", "1")
8
+ os.environ.setdefault("OPENBLAS_NUM_THREADS", "1")
9
  os.environ.setdefault("HF_HUB_DISABLE_TELEMETRY", "1")
10
 
11
  # Import before torch so ZeroGPU can enable its CUDA staging mode.
 
29
  from pixtext import PixTextPipeline
30
  from huggingface_hub import snapshot_download
31
 
32
+ torch.set_num_threads(int(os.environ["PIXTEXT_CPU_THREADS"]))
33
  if not torch.cuda.is_available() and not spaces.config.Config.zero_gpu:
34
  return {}
35
  pipelines = {}
 
50
  PIPELINES = load_models()
51
 
52
 
53
+ def estimate_duration(directory: str, size: list[int], jid: str, payload: str):
54
+ import math
55
+ request = json.loads(payload)
56
+ count = sum(row.get("enabled", True) for row in request["regions"])
57
+ return max(20, min(90, 10 + math.ceil(request["steps"] * max(1, count / 8))))
58
+
59
+
60
+ @spaces.GPU(duration=estimate_duration)
61
  def gpu_refine(directory: str, size: list[int], jid: str, payload: str):
62
+ print("PixText GPU worker: starting", flush=True)
63
  started = time.perf_counter()
64
  request = studio.RefineRequest.model_validate_json(payload)
65
  studio.PIPELINE = PIPELINES.get(request.variant)
 
67
  progress = gr.Progress()
68
 
69
  def report(**values):
70
+ message = values.get("message", "Refining")
71
+ print("PixText GPU:", message, flush=True)
72
+ progress(values.get("progress", 0), desc=message)
73
 
74
  result = studio.refine({"directory": Path(directory), "size": size}, jid, request, report)
75
  result["elapsed"] = round(time.perf_counter() - started, 2)
76
+ print("PixText GPU worker: complete", result["elapsed"], flush=True)
77
  return result
78
 
79