-
Notifications
You must be signed in to change notification settings - Fork 79
Optimize deterministic rollout tensor-parallel all-reduce #365
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,7 +12,11 @@ | |
|
|
||
| import torch | ||
|
|
||
| from rl_engine.distributed.collectives import DETERMINISTIC_ALL_REDUCE_OP | ||
| from rl_engine.distributed.collectives import ( | ||
| DETERMINISTIC_ALL_REDUCE_OP, | ||
| collective_for_group, | ||
| deterministic_all_reduce_inplace, | ||
| ) | ||
| from rl_engine.integrations.ablation import ( | ||
| Implementation, | ||
| IntegrationPlan, | ||
|
|
@@ -40,6 +44,8 @@ | |
| _STRICT_RMS_NORM_INIT_MARKER = "__rl_kernel_original_strict_rms_norm_init__" | ||
| _STRICT_ROTARY_INIT_MARKER = "__rl_kernel_original_strict_rotary_init__" | ||
| _STRICT_LM_HEAD_LINEAR_PATCH_MARKER = "__rl_kernel_original_lm_head_linear_apply__" | ||
| _STRICT_O_PROJ_COLLECTIVE_MARKER = "__rl_kernel_o_proj_collective__" | ||
| _STRICT_ROW_PARALLEL_PATCH_MARKER = "__rl_kernel_original_row_parallel_forward__" | ||
| _RLK_ATTENTION_BACKEND: type[Any] | None = None | ||
| _RLK_ATTENTION_IMPL: type[Any] | None = None | ||
| _RLK_ATTENTION_BUILDER: type[Any] | None = None | ||
|
|
@@ -367,21 +373,23 @@ def _patch_qwen3_strict_model( | |
| rotary_cls: type[Any] | None = None, | ||
| linear_method_cls: type[Any] | None = None, | ||
| attention_cls: type[Any] | None = None, | ||
| row_parallel_cls: type[Any] | None = None, | ||
| det_gemm: Any | None = None, | ||
| ) -> None: | ||
| """Align vLLM's RMSNorm and Attention projections with Megatron.""" | ||
|
|
||
| production_classes = rms_norm_cls is None or linear_method_cls is None or attention_cls is None | ||
| if production_classes: | ||
| from vllm.model_executor.layers.layernorm import RMSNorm | ||
| from vllm.model_executor.layers.linear import UnquantizedLinearMethod | ||
| from vllm.model_executor.layers.linear import RowParallelLinear, UnquantizedLinearMethod | ||
| from vllm.model_executor.layers.rotary_embedding import RotaryEmbedding | ||
| from vllm.model_executor.models.qwen3 import Qwen3Attention | ||
|
Comment on lines
+384
to
386
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
# Resolve the repository's effective vLLM dependency declaration.
rg -n -i --glob 'pyproject.toml' --glob 'requirements*.txt' --glob 'setup.py' \
--glob 'setup.cfg' --glob 'poetry.lock' --glob 'uv.lock' '\bvllm\b' .
# Verify the stock vLLM 0.6.0 module and RowParallelLinear contract.
curl -fsSI \
https://raw.githubusercontent.com/vllm-project/vllm/v0.6.0/vllm/model_executor/models/qwen3.py \
|| true
curl -fsSL \
https://raw.githubusercontent.com/vllm-project/vllm/v0.6.0/vllm/model_executor/layers/linear.py \
| sed -n '936,965p'Repository: RL-Align/RL-Kernel Length of output: 2547 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- local integration symbols and context ---'
sed -n '350,410p' rl_engine/integrations/vllm_runtime.py
sed -n '450,510p' rl_engine/integrations/vllm_runtime.py
printf '%s\n' '--- local dependency declarations and plugin context ---'
sed -n '1,45p' pyproject.toml
sed -n '285,315p' setup.py
rg -n -C 3 'qwen3|RowParallelLinear|return_bias|skip_bias_add|o_proj' rl_engine pyproject.toml setup.py
printf '%s\n' '--- vLLM v0.6.0 RowParallelLinear implementation ---'
curl -fsSL https://raw.githubusercontent.com/vllm-project/vllm/v0.6.0/vllm/model_executor/layers/linear.py \
| rg -n -A 95 -B 10 'class RowParallelLinear'Repository: RL-Align/RL-Kernel Length of output: 50374 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- local strict initialization path ---'
sed -n '640,705p' rl_engine/integrations/vllm_runtime.py
sed -n '150,215p' rl_engine/integrations/vllm_runtime.py
printf '%s\n' '--- vLLM v0.6.0 RowParallelLinear class, constructor, and forward ---'
python3 - <<'PY'
from urllib.request import urlopen
url = "https://raw.githubusercontent.com/vllm-project/vllm/v0.6.0/vllm/model_executor/layers/linear.py"
text = urlopen(url).read().decode()
lines = text.splitlines()
start = next(i for i, line in enumerate(lines) if line.startswith("class RowParallelLinear"))
end = next(
(i for i in range(start + 1, len(lines)) if lines[i].startswith("class ")),
len(lines),
)
for i in range(start, end):
if (
"def __init__" in lines[i]
or "def forward" in lines[i]
or "return_bias" in lines[i]
or "skip_bias_add" in lines[i]
or "return output" in lines[i]
or "return output, output_bias" in lines[i]
):
lo = max(start, i - 4)
hi = min(end, i + 28)
print(f"--- lines {lo + 1}-{hi} ---")
for j in range(lo, hi):
print(f"{j + 1}: {lines[j]}")
PYRepository: RL-Align/RL-Kernel Length of output: 8893 🏁 Script executed: #!/bin/bash
set -euo pipefail
curl -fsSL https://raw.githubusercontent.com/vllm-project/vllm/v0.6.0/vllm/model_executor/layers/linear.py |
python3 -c '
import sys
lines = sys.stdin.read().splitlines()
start = next(i for i, line in enumerate(lines) if line.startswith("class RowParallelLinear"))
end = next(
(i for i in range(start + 1, len(lines)) if lines[i].startswith("class ")),
len(lines),
)
for i in range(start, end):
if any(token in lines[i] for token in (
"def __init__", "def forward", "return_bias", "skip_bias_add",
"return output", "return output, output_bias",
)):
lo = max(start, i - 5)
hi = min(end, i + 30)
print(f"--- lines {lo + 1}-{hi} ---")
for j in range(lo, hi):
print(f"{j + 1}: {lines[j]}")
'Repository: RL-Align/RL-Kernel Length of output: 13337 Align vLLM compatibility with the supported dependency range.
📍 Affects 1 file
🤖 Prompt for AI Agents |
||
|
|
||
| rms_norm_cls = RMSNorm | ||
| rotary_cls = RotaryEmbedding | ||
| linear_method_cls = UnquantizedLinearMethod | ||
| attention_cls = Qwen3Attention | ||
| row_parallel_cls = RowParallelLinear | ||
| assert rms_norm_cls is not None | ||
| assert linear_method_cls is not None | ||
| assert attention_cls is not None | ||
|
|
@@ -435,6 +443,62 @@ def strict_rms_norm_forward_cuda( | |
| eps=instance.variance_epsilon, | ||
| ) | ||
|
|
||
| def bind_o_proj_collective(module: Any) -> None: | ||
| if int(getattr(module, "tp_size", 1)) <= 1: | ||
| return | ||
| from vllm.distributed.parallel_state import get_tp_group | ||
|
|
||
| coordinator = get_tp_group() | ||
| group = getattr(coordinator, "device_group", coordinator) | ||
| collective = collective_for_group(group) | ||
| if collective is None: | ||
| raise RuntimeError("strict rollout o_proj requires an initialized TP process group") | ||
| setattr(module, _STRICT_O_PROJ_COLLECTIVE_MARKER, collective) | ||
|
|
||
| if row_parallel_cls is not None and not hasattr( | ||
| row_parallel_cls, _STRICT_ROW_PARALLEL_PATCH_MARKER | ||
| ): | ||
| row_parallel_forward = row_parallel_cls.forward | ||
|
|
||
| def strict_row_parallel_forward(instance: Any, input_: torch.Tensor) -> Any: | ||
| collective = getattr(instance, _STRICT_O_PROJ_COLLECTIVE_MARKER, None) | ||
| if collective is None: | ||
| return row_parallel_forward(instance, input_) | ||
|
|
||
| if instance.input_is_parallel: | ||
| input_parallel = input_ | ||
| else: | ||
| from vllm.distributed import split_tensor_along_last_dim | ||
|
|
||
| input_parallel = split_tensor_along_last_dim( | ||
| input_, num_partitions=instance.tp_size | ||
| )[instance.tp_rank].contiguous() | ||
|
|
||
| assert instance.quant_method is not None | ||
| bias_ = ( | ||
| None | ||
| if (instance.tp_rank > 0 or instance.skip_bias_add) | ||
| else instance.bias | ||
| ) | ||
| output_parallel = instance.quant_method.apply(instance, input_parallel, bias_) | ||
|
|
||
| if instance.reduce_results and instance.tp_size > 1: | ||
| deterministic_all_reduce_inplace( | ||
| output_parallel, | ||
| collective_handle=int(collective._handle), | ||
| ) | ||
| output = output_parallel | ||
| else: | ||
| output = output_parallel | ||
|
|
||
| if not instance.return_bias: | ||
| return output | ||
| output_bias = instance.bias if instance.skip_bias_add else None | ||
| return output, output_bias | ||
|
|
||
| setattr(row_parallel_cls, _STRICT_ROW_PARALLEL_PATCH_MARKER, row_parallel_forward) | ||
| row_parallel_cls.forward = strict_row_parallel_forward | ||
|
|
||
| if not hasattr(rms_norm_cls, _STRICT_RMS_NORM_INIT_MARKER): | ||
| rms_norm_init = rms_norm_cls.__init__ | ||
|
|
||
|
|
@@ -463,6 +527,7 @@ def attention_init_wrapped(instance: Any, *args: Any, **kwargs: Any) -> None: | |
| attention_init(instance, *args, **kwargs) | ||
| setattr(instance.qkv_proj, _STRICT_PROJECTION_MARKER, "qkv") | ||
| setattr(instance.o_proj, _STRICT_PROJECTION_MARKER, "o_proj") | ||
| bind_o_proj_collective(instance.o_proj) | ||
|
|
||
| setattr(attention_cls, _STRICT_MODEL_PATCH_MARKER, attention_init) | ||
| linear_method_cls.apply = deterministic_linear_apply | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
Do not enable this collective during CUDA Graph replay until it is validated.
PR validation reports an illegal-memory-access error for this strict
o_projgraph-capture path. The new code still routes every marked tensor-parallelo_projthrough the fused deterministic collective. Gate this path during CUDA Graph capture and userow_parallel_forward, or fix and validate capture and replay before release.csrc/cuda/distributed/deterministic_collective.cu#L1099-L1103: do not classify the staged fused path as graph-safe until replay succeeds.rl_engine/integrations/vllm_runtime.py#L485-L489: bypass deterministic reduction for an active CUDA Graph capture until the collective is capture-safe.📍 Affects 2 files
csrc/cuda/distributed/deterministic_collective.cu#L1099-L1103(this comment)rl_engine/integrations/vllm_runtime.py#L485-L489🤖 Prompt for AI Agents