Skip to content

Commit 7e0ceeb

Browse files
committed
fix: unbound gpu<->cpu queues to avoid deadlock in mp deterministic mode
1 parent 989b70c commit 7e0ceeb

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

edsnlp/processing/multiprocessing.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -851,16 +851,14 @@ def __init__(self, stream):
851851
# one single shared queue but N bounded queues, one for each producer.
852852
# This is to avoid the situation where a single producer occupies all
853853
# slots, leading to congestions affecting the whole workers pool.
854-
# In practice, using a single shared queue, in particular for the
855-
# worker -> main
856854

857855
# Input queues for each CPU worker
858856
if not self.stream.reader.read_in_worker:
859857
queue = mp.Queue(2 * num_cpu_workers) if share_queues else None
860858
for cpu in self.cpu_worker_names:
861859
name = f"from-main_to-stage-0_of-{cpu}"
862860
if not share_queues:
863-
queue = mp.Queue(2)
861+
queue = mp.SimpleQueue()
864862
self.data_queues[name] = queue
865863
self.input_queue_names.append(name)
866864

@@ -872,11 +870,11 @@ def __init__(self, stream):
872870
for stage in range(0, len(self.stages) - 1):
873871
# Queue to send data from CPU to GPU
874872
name = f"from-{cpu}_to-stage-{stage}_of-{gpu}"
875-
self.data_queues[name] = mp.Queue(2)
873+
self.data_queues[name] = mp.Queue()
876874

877875
# Answer queue from GPU to CPU
878876
name = f"from-{gpu}_to-stage-{stage + 1}_of-{cpu}"
879-
self.data_queues[name] = mp.Queue(2)
877+
self.data_queues[name] = mp.Queue()
880878

881879
# Final output queue for each CPU worker
882880
name = f"from-{cpu}_to-main"

tests/processing/test_backends.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import random
12
import time
23
from itertools import chain
34
from pathlib import Path
@@ -168,6 +169,25 @@ def test_multiprocessing_gpu_stub_backend(frozen_ml_nlp, backend, deterministic)
168169
list(stream)
169170

170171

172+
def test_multiprocessing_gpu_stub_multi_cpu_deterministic_backend(frozen_ml_nlp):
173+
text1 = "Exemple"
174+
text2 = "Ceci est un autre exemple"
175+
text3 = "Ceci est un très long exemple ! Regardez tous ces mots !"
176+
texts = [text1, text2, text3] * 100
177+
random.Random(42).shuffle(texts)
178+
stream = frozen_ml_nlp.pipe(iter(texts))
179+
stream = stream.set_processing(
180+
batch_size="15 words",
181+
num_gpu_workers=1,
182+
num_cpu_workers=2,
183+
deterministic=True,
184+
# show_progress=True,
185+
# just to test in gpu-less environments
186+
gpu_worker_devices=["cpu"],
187+
)
188+
list(stream)
189+
190+
171191
@pytest.mark.parametrize("wait", [True, False])
172192
def test_multiprocessing_gpu_stub_wait(frozen_ml_nlp, wait):
173193
text1 = "Ceci est un exemple"

0 commit comments

Comments
 (0)