Skip to content

Commit 4489049

Browse files
committed
Added /terminate to free VRAM
1 parent 43de78a commit 4489049

8 files changed

Lines changed: 40 additions & 23 deletions

File tree

base/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ RUN pip install --no-deps --no-cache-dir uv && uv --no-cache pip install --syste
99

1010
EXPOSE 8080
1111

12-
CMD ["./start.sh"]
12+
CMD ["python", "-u", "webservice.py"]

base/start.sh

Lines changed: 0 additions & 7 deletions
This file was deleted.

base/tagger_worker.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,17 @@
3131

3232
CALLBACK_SERVER: str = os.getenv("CALLBACK_SERVER") or ""
3333
NUM_WORKERS = int(os.getenv("NUM_WORKERS") or 1)
34+
# Needs to be defined as a reference object, e.g. dict.
35+
_global = {"pool": None}
3436

3537

3638
def run_pending_tasks() -> None:
3739
"""
3840
Send a new task to the pool if there is no busy task.
3941
If there is no pool running, start a new pool.
4042
"""
41-
global pool
42-
4343
# One task at a time.
44-
tasks_in_queue = pool._taskqueue.qsize()
44+
tasks_in_queue = _global["pool"]._taskqueue.qsize()
4545
if tasks_in_queue > 0:
4646
return
4747

@@ -54,11 +54,11 @@ def run_pending_tasks() -> None:
5454
if sl.get_status()["busy"] is False:
5555
sl.busy("Parsing file") # Sets busy true
5656
# Extra None check for typing
57-
if (not is_pool_running(pool)) or pool is None:
57+
if (not is_pool_running()) or _global["pool"] is None:
5858
# Spawn pool if not running
59-
pool = mp.Pool(processes=NUM_WORKERS, initializer=process.init)
59+
_global["pool"] = mp.Pool(processes=NUM_WORKERS)
6060
# Perform task at running pool
61-
pool.apply_async(process_file, args=(sl.filename,))
61+
_global["pool"].apply_async(process_file, args=(sl.filename,))
6262

6363

6464
def process_file(filename: str):
@@ -183,28 +183,31 @@ def send_error_to_callback_server(filename: str, out_path: str, message: str) ->
183183
keep_or_delete_file(r, out_path)
184184

185185

186-
def is_pool_running(pool: Optional[Pool]) -> bool:
186+
def is_pool_running() -> bool:
187187
"""
188188
Check if the pool is running by trying to execute a dummy function.
189189
"""
190-
if pool is None:
190+
if _global["pool"] is None:
191191
return False
192192
try:
193-
pool.apply_async(lambda: None)
193+
_global["pool"].apply_async(lambda: None)
194194
except ValueError as e:
195195
if str(e) == "Pool not running":
196196
return False
197197
return True
198198

199199

200-
# Pool needs to be defined after the functions it will execute.
201-
# https://stackoverflow.com/questions/41385708/multiprocessing-example-giving-attributeerror#comment101561695_42383397
202-
pool = None
200+
def terminate_pool() -> None:
201+
"""
202+
Terminate the pool if it is running.
203+
"""
204+
_global["pool"].terminate()
205+
203206

204-
if __name__ == "__main__":
207+
def run_background():
205208
# Can't use fork with the gpu.
206209
mp.set_start_method("spawn", force=True)
207-
pool = mp.Pool(processes=NUM_WORKERS, initializer=process.init)
210+
_global["pool"] = mp.Pool(processes=NUM_WORKERS)
208211

209212
# It is ugly, but it is also used here:
210213
# https://pypi.org/project/schedule/

base/webservice.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import os
1414
import subprocess
1515
import uuid
16+
import threading
1617

1718
# Third-party
1819
import bottle
@@ -23,6 +24,7 @@
2324
from shared import OUTPUT_FOLDER, UPLOAD_FOLDER, ERROR_FOLDER
2425
from statuslogger import StatusLogger
2526
from process import OUTPUT_EXTENSION, PROCESSING_SPEED
27+
from tagger_worker import run_background, terminate_pool
2628

2729
app = application = bottle.default_app()
2830

@@ -163,4 +165,15 @@ def delete_file(id: str):
163165
return HTTPResponse("File " + id + " deleted", 200)
164166

165167

166-
app.run(host="0.0.0.0", port=8080)
168+
@post("/terminate")
169+
def terminate():
170+
"""
171+
Terminate the worker pool immediately, freeing RAM (& VRAM).
172+
"""
173+
terminate_pool()
174+
return HTTPResponse("Terminated the worker pool", 200)
175+
176+
177+
if __name__ == "__main__":
178+
threading.Thread(target=run_background, daemon=True).start()
179+
app.run(host="0.0.0.0", port=8080)

flair/process.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ def process(in_file: str, out_file: str) -> None:
3434
"""
3535
Process the file at path "in_file" and write the result to path "out_file".
3636
"""
37+
if tagger is None or splitter is None:
38+
init()
3739
with open(out_file, "w+", encoding="utf-8") as f_out:
3840
with open(in_file, "r", encoding="utf-8") as f_in:
3941
doc = f_in.read()

pie/base/process.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ def process(in_file: str, out_file: str) -> None:
5050
Pie outputs to the same directory as the input file.
5151
We process the file in a temporary directory so we don't polute /input.
5252
"""
53+
if tagger is None:
54+
init()
5355
with tempfile.TemporaryDirectory() as temp_dir:
5456
# input
5557
temp_in_file = os.path.join(temp_dir, "file.txt")

spacy/process.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ def process(in_file: str, out_file: str) -> None:
5555
"""
5656
Process the file at path "in_file" and write the result to path "out_file".
5757
"""
58+
if nlp is None:
59+
init()
5860
with open(out_file, "w+", encoding="utf-8") as f_out:
5961
with open(in_file, "r", encoding="utf-8") as f_in:
6062
is_xml = is_file_xml(in_file)

stanza/process.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def process(in_file: str, out_file: str) -> None:
6161
"""
6262
Process the file at path "in_file" and write the result to path "out_file".
6363
"""
64+
if xml_nlp is None or txt_nlp is None:
65+
init()
6466
with open(out_file, "w+", encoding="utf-8") as f_out:
6567
with open(in_file, "r", encoding="utf-8") as f_in:
6668
is_xml = is_file_xml(in_file)

0 commit comments

Comments
 (0)