Skip to content

fix(engine): start a single rank without a rendezvous port - #615

Draft
YevheniiKotyrlo wants to merge 1 commit into
FlashML-org:mainfrom
YevheniiKotyrlo:fix-single-rank-rendezvous
Draft

YevheniiKotyrlo wants to merge 1 commit into
FlashML-org:mainfrom
YevheniiKotyrlo:fix-single-rank-rendezvous

Conversation

@YevheniiKotyrlo

@YevheniiKotyrlo YevheniiKotyrlo commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Part of #301

Problem

With the default --tensor-parallel-size 1, the engine still forms its one-rank gloo group through a TCP rendezvous: on --port + 1 for a server (ServerArgs.distributed_addr), and on the fixed 127.0.0.1:2333 for an offline engine (EngineConfig.distributed_addr). Anything listening there fails the load with DistNetworkError: ... EADDRINUSE, as #301 reports. As benwilson found there, that store also listens on every interface, and on Windows every start logs [c10d] The client socket has failed to connect to ...:<port + 1>. A single rank meets no other process, so it needs none of this.

Solution

_init_communication takes where the ranks meet from _rendezvous. A single rank forms its group over a FileStore at a fresh tempfile.mkstemp path, which it deletes as soon as init_process_group returns. A one-rank gloo group does not read its store again: collectives and destroy_process_group run with the file gone, and nothing recreates it. So no port is bound, and a run killed after that point leaves no file.

More than one rank keeps init_method=config.distributed_addr as before, and the --tensor-parallel-size help now says those ranks meet on --port + 1.

I used a FileStore because it is the one store that needs no socket on both platforms. torch builds no HashStore on Windows (torch/distributed/__init__.py imports it only off win32). A TCPStore on an OS-chosen port would still listen, and on Windows it needs use_libuv=False.

The two init_process_group calls differed only in the backend, so they become one.

Tests

tests/engine/test_communication.py:

  • A single-rank server starts while its --port + 1 is held, and an offline engine starts while 2333 is held. On main both fail with DistNetworkError (EADDRINUSE on Linux, system error 10048 on Windows).
  • A formed single-rank group runs an all_reduce with no store file left. The test fails when the file is kept.

Verification

RTX 3090 Ti (driver 617.14), Ryzen 9 9950X3D, Qwen/Qwen3-0.6B. The command was python -m freetoken --model-path Qwen3-0.6B --host 127.0.0.1 --port 21000 --num-pages 4000, with 127.0.0.1:21001 held by another socket.

I could not run more than one rank, since this machine has one GPU. That path keeps the rendezvous it had on main.

Related

#461 also touches _init_communication: it makes the port configurable (default --port + 1) and binds the store to loopback for every TP size. This change removes the rendezvous for a single rank instead and leaves more than one rank as it is, so #461's approach still applies there. On Windows, its explicit TCPStore(...) needs use_libuv=False, since torch has no libuv there: DistStoreError: use_libuv was requested but PyTorch was built without libuv support.

KarrAcaRn pushed a commit to KarrAcaRn/FreeToken-ByAI that referenced this pull request Oct 6, 2026
FlashML-org#604 rejected (accepts JSON response formats without enforcing them); FlashML-org#605 deferred
(pre-sm70 only); drafts FlashML-org#614, FlashML-org#615, FlashML-org#616 deferred with what next already covers.

Assisted-by: Claude Opus 5.5

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant