Skip to content

Commit f6606fd

Browse files
authored
supports multi-node inference (#263)
1 parent 650e76a commit f6606fd

2 files changed

Lines changed: 43 additions & 11 deletions

File tree

diffsynth_engine/engine.py

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ class DiffSynthEngine:
2020
def from_pretrained(cls, model_path_or_config: str | PipelineConfig, **kwargs):
2121
pipeline_config = _resolve_pipeline_config(model_path_or_config)
2222
num_workers = pipeline_config.parallelism
23+
master_addr = kwargs.get("master_addr", "localhost")
2324
master_port = kwargs.get("master_port", 29500)
25+
nnodes = kwargs.get("nnodes", 1)
26+
node_rank = kwargs.get("node_rank", 0)
2427

2528
if num_workers > 1:
26-
return DistributedEngine(pipeline_config, num_workers, master_port)
29+
return DistributedEngine(pipeline_config, num_workers, master_addr, master_port, nnodes, node_rank)
2730
return LocalEngine(pipeline_config)
2831

2932
def generate(self, **kwargs):
@@ -210,41 +213,66 @@ def stop_profile(self):
210213

211214

212215
class DistributedEngine(DiffSynthEngine):
213-
def __init__(self, pipeline_config: PipelineConfig, num_workers: int, master_port: int):
214-
logger.info(f"Initializing {num_workers} workers...")
216+
def __init__(
217+
self,
218+
pipeline_config: PipelineConfig,
219+
num_workers: int,
220+
master_addr: str = "localhost",
221+
master_port: int = 29500,
222+
nnodes: int = 1,
223+
node_rank: int = 0,
224+
):
225+
if nnodes <= 0:
226+
raise ValueError(f"nnodes must be positive, got {nnodes}")
227+
if not 0 <= node_rank < nnodes:
228+
raise ValueError(f"node_rank must be in [0, {nnodes}), got {node_rank}")
229+
if num_workers % nnodes != 0:
230+
raise ValueError(f"num_workers ({num_workers}) must be a multiple of nnodes ({nnodes})")
231+
232+
nproc_per_node = num_workers // nnodes
233+
rank_offset = node_rank * nproc_per_node
234+
self.node_rank = node_rank
235+
236+
logger.info(
237+
f"Initializing {nproc_per_node} workers on node {node_rank} "
238+
f"(world_size={num_workers}, master={master_addr}:{master_port})..."
239+
)
215240

216241
set_device(0)
217242

218243
self.workers = []
219244
self.conns = []
220245

221246
ctx = mp.get_context("spawn")
222-
for rank in range(num_workers):
247+
for local_rank in range(nproc_per_node):
248+
global_rank = rank_offset + local_rank
223249
conn_main, conn_worker = ctx.Pipe(duplex=True)
224250

225251
process = ctx.Process(
226252
target=run_worker_loop,
227253
args=(
228-
rank, # local_rank
229-
rank, # rank
254+
local_rank, # local_rank
255+
global_rank, # rank
230256
num_workers, # world_size
257+
master_addr, # master_addr
231258
master_port, # master_port
232259
conn_worker, # conn
233260
pipeline_config, # pipeline_config
234261
),
235-
name=f"diffsynth-worker-{rank}",
262+
name=f"diffsynth-worker-{global_rank}",
236263
daemon=True,
237264
)
238265
process.start()
239266

240267
self.workers.append(process)
241268
self.conns.append(conn_main)
242269

243-
for rank, conn in enumerate(self.conns):
270+
for i, conn in enumerate(self.conns):
244271
result = conn.recv()
245272
if result["status"] != "ready":
246-
raise RuntimeError(f"Worker {rank} failed to start: {result.get('error', 'Unknown error')}")
247-
logger.info("All workers are ready")
273+
global_rank = rank_offset + i
274+
raise RuntimeError(f"Worker {global_rank} failed to start: {result.get('error', 'Unknown error')}")
275+
logger.info(f"All workers on node {node_rank} are ready")
248276

249277
def _dispatch(self, method: str, output_rank: int | None = 0, **kwargs):
250278
self.conns[0].send(

diffsynth_engine/worker.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,18 @@ def __init__(
2222
local_rank: int,
2323
rank: int,
2424
world_size: int,
25+
master_addr: str,
2526
master_port: int,
2627
pipeline_config: PipelineConfig,
2728
):
2829
self.local_rank = local_rank
2930
self.rank = rank
3031
self.world_size = world_size
32+
self.master_addr = master_addr
3133
self.master_port = master_port
3234
self.pipeline_config = pipeline_config
3335

34-
os.environ["MASTER_ADDR"] = "localhost"
36+
os.environ["MASTER_ADDR"] = master_addr
3537
os.environ["MASTER_PORT"] = str(master_port)
3638
os.environ["LOCAL_RANK"] = str(local_rank)
3739
os.environ["RANK"] = str(rank)
@@ -81,6 +83,7 @@ def run_worker_loop(
8183
local_rank: int,
8284
rank: int,
8385
world_size: int,
86+
master_addr: str,
8487
master_port: int,
8588
conn: mp.connection.Connection,
8689
pipeline_config: PipelineConfig,
@@ -90,6 +93,7 @@ def run_worker_loop(
9093
local_rank=local_rank,
9194
rank=rank,
9295
world_size=world_size,
96+
master_addr=master_addr,
9397
master_port=master_port,
9498
pipeline_config=pipeline_config,
9599
)

0 commit comments

Comments
 (0)