Skip to content

Commit 320fb1d

Browse files
committed
[Refactor] Follow weight update start/finish contract in WPI engine and example
Signed-off-by: Bill Du <yangspirit@google.com>
1 parent 089ec4f commit 320fb1d

3 files changed

Lines changed: 42 additions & 7 deletions

File tree

docs/training/weight_transfer/wpi.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ from vllm.distributed.weight_transfer.wpi_engine import (
8989
)
9090

9191
# Start weight update on inference side
92-
llm.start_weight_update(is_checkpoint_format=True)
92+
llm.start_weight_update()
9393

9494
# Prepare send arguments with the trainer context
9595
trainer_args = WPITrainerSendWeightsArgs(

examples/rl/rlhf_http_wpi.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ def init_weight_transfer_engine(
7575
response.raise_for_status()
7676

7777

78+
def start_weight_update(base_url: str) -> None:
79+
"""Start a weight update via HTTP endpoint."""
80+
url = f"{base_url}/start_weight_update"
81+
response = requests.post(url, json={}, timeout=60)
82+
response.raise_for_status()
83+
84+
85+
def finish_weight_update(base_url: str) -> None:
86+
"""Finish a weight update via HTTP endpoint."""
87+
url = f"{base_url}/finish_weight_update"
88+
response = requests.post(url, json={}, timeout=60)
89+
response.raise_for_status()
90+
91+
7892
def pause_generation(base_url: str) -> None:
7993
"""Pause generation via HTTP endpoint."""
8094
url = f"{base_url}/pause"
@@ -137,11 +151,13 @@ def main():
137151
socket_dir = "/run/wpi/sockets"
138152
driver_port = 50051
139153

140-
# Calculate model size in bytes
141-
total_model_bytes = sum(
142-
p.numel() * p.element_size() for p in train_model.parameters()
143-
)
144-
print(f"Calculated model size: {total_model_bytes} bytes")
154+
# Calculate model size in bytes with alignment padding
155+
total_model_bytes = 0
156+
for p in train_model.parameters():
157+
itemsize = p.element_size()
158+
total_model_bytes = (total_model_bytes + itemsize - 1) // itemsize * itemsize
159+
total_model_bytes += p.numel() * itemsize
160+
print(f"Calculated model size with alignment: {total_model_bytes} bytes")
145161

146162
print("Initializing weight transfer on server...")
147163

@@ -165,6 +181,9 @@ def main():
165181
# Pause generation before weight sync
166182
pause_generation(BASE_URL)
167183

184+
# Start weight update, broadcast via WPI, then finish
185+
start_weight_update(BASE_URL)
186+
168187
# Broadcast all weights from trainer to vLLM workers
169188
print("Propagating weights via WPI...")
170189
param_iter = ((n, p) for n, p in train_model.named_parameters())
@@ -177,6 +196,8 @@ def main():
177196
# This will pack weights, trigger WPI propagate, and call /update_weights on server
178197
WPIWeightTransferEngine.trainer_send_weights(param_iter, args)
179198

199+
finish_weight_update(BASE_URL)
200+
180201
# Resume generation after weight sync
181202
resume_generation(BASE_URL)
182203

vllm/distributed/weight_transfer/wpi_engine.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,19 @@
1616
│ → receive FD │ │ → receive FD │
1717
│ → CUDA import │ │ → CUDA import │
1818
│ │ │ → connect notify sock │
19+
│ │ │ │
20+
│ /start_weight_upd├───(HTTP/Ray)──→│ start_weight_update() │
21+
│ │ │ │
1922
│ trainer_send_wts │ │ │
2023
│ → pack into buf │ NodePropagate │ receive_weights() │
2124
│ → propagate ────┼───(NCCL)──────→│ → wait_for_ready │
2225
│ → HTTP metadata │ │ → unpack from buffer │
23-
│ /update_weights├───(HTTP)─────→│ → load_weights() │
26+
│ /update_weights├───(HTTP/Ray)─→│ → load_weights() │
27+
│ │ │ │
28+
│ /finish_weight_up├───(HTTP/Ray)──→│ finish_weight_update() │
2429
└──────────────────┘ └───────────────────────┘
2530
31+
2632
Key differences from NCCL/IPC engines:
2733
- NCCL communicator is managed by the WPI driver, not by vLLM
2834
- VRAM buffer is persistent and reused across training steps (no per-update alloc)
@@ -498,6 +504,11 @@ def trainer_send_weights(
498504
The WPI driver handles NCCL communicator setup, broadcast execution,
499505
and READY notification to consumers — all transparently.
500506
507+
.. note::
508+
This method calls ``update_weights`` internally. The caller must
509+
call ``start_weight_update`` before and ``finish_weight_update``
510+
after this method.
511+
501512
Args:
502513
iterator: Iterator of (name, tensor) tuples from the model.
503514
trainer_args: Dict or WPITrainerSendWeightsArgs with WPI config.
@@ -552,6 +563,9 @@ def trainer_send_weights(
552563

553564
for name, tensor in iterator:
554565
weight = tensor.detach().contiguous()
566+
itemsize = weight.element_size()
567+
# Align offset to itemsize boundary to prevent unaligned view errors
568+
offset = (offset + itemsize - 1) // itemsize * itemsize
555569
nbytes = weight.nbytes
556570

557571
if offset + nbytes > ctx.buffer_size_bytes:

0 commit comments

Comments
 (0)