vllm-project/vllm-omni
View on GitHub[RFC]: Unify Rotary Position Embedding Implementations Across Models
Open
#2,436 opened on Apr 2, 2026
help wanted
Repository metrics
- Stars
- (4,990 stars)
- PR merge metrics
- (PR metrics pending)
Description
RFC: Unify Rotary Position Embedding Implementations Across Models
Background
PR #2393 optimized Wan2.2's apply_rotary_emb_wan function by replacing the inefficient torch.empty_like + strided slice assignment pattern with torch.stack + flatten. This achieved a 25% speedup (44s → 33s on NPU, 55s → 44s on A100).
During code review, we discovered that multiple models in vllm-omni have their own rotary embedding implementations with varying efficiency levels.
Current State
| Model | Implementation | Pattern | Status |
|---|---|---|---|
| wan_transformer | apply_rotary_emb_wan |
torch.stack + flatten |
✅ Optimized (PR #2393) |
| helios_transformer | apply_rotary_emb |
empty_like + strided slice |
❌ Needs optimization |
| stable_audio | apply_rotary_embed |
torch.cat |
✅ Optimized |
| qwen_image | apply_rotary_emb_qwen |
torch.stack + flatten |
✅ Optimized |
| omnigen2 | apply_rotary_emb |
torch.stack + flatten |
✅ Optimized |
Meanwhile, vLLM core already provides optimized implementations:
vllm.model_executor.layers.rotary_embedding.common.ApplyRotaryEmb- Uses efficient patterns for both Neox-style (torch.cat) and interleaved/GPT-J style (torch.stack + flatten)vllm.vllm_flash_attn.layers.rotary- Compiled CUDA kernel, optimized at kernel level
Problem
- Code duplication: Each model implements its own RoPE function
- Inconsistent performance: Some implementations use inefficient patterns (strided slice assignment causes
InplaceCopy/ViewCopyoverhead on NPU) - Maintenance burden: Optimizations need to be applied to each model individually
- Missing hardware optimizations: Custom ops and compiled kernels from vLLM core are not being leveraged
Proposal
We propose to unify rotary embedding implementations across all models in vllm-omni:
Phase 1: Immediate Fixes
- Apply the
torch.stack + flattenpattern tohelios_transformer.py(same fix as PR #2393) - This is a low-risk change that maintains the same mathematical semantics
Phase 2: Centralized Implementation
- Create a unified
apply_rotary_embutility in a shared location (e.g.,vllm_omni/layers/rotary_embedding.py) - Support all required variations:
- Neox-style (even/odd split)
- Interleaved/GPT-J style
- Optional: different RoPE scaling methods (linear, dynamic, yarn, etc.)
Phase 3: Leverage vLLM Core
- Investigate using
ApplyRotaryEmbfrom vLLM core directly - For NPU: Consider implementing a custom NPU op for RoPE if profiling shows further optimization opportunities
- This aligns with vLLM's design philosophy of hardware-agnostic model code with platform-specific kernels
Benefits
- Performance: Ensure all models benefit from optimized implementations
- Maintainability: Single source of truth for RoPE logic
- Consistency: Same behavior and performance characteristics across models
- Future-proof: Easier to add new hardware optimizations (NPU custom ops, etc.)
Call for Discussion
- Should we prioritize reusing vLLM core's
ApplyRotaryEmbor maintain our own implementation? - Are there any model-specific RoPE variations that cannot be unified?
- What's the preferred location for the shared implementation?
cc @fhfuih @wtomin @hsliuustc0106