Phase 3.5: Automatic Tensor Parallelism - Implementation Results¶
Date¶
2026-09-03
Objective¶
Make CppBackend tensor parallelism launch automatically like vLLM/SGLang, without requiring manual process management or special launch scripts.
User Requirement: "我不希望有什么特殊启动流程,你应该把cpp engine后端的启动方式和pytorch后端的启动方式统一,并且要符合vllm/sglang的使用习惯"
Implementation¶
Design¶
Following vLLM/SGLang conventions, users should be able to write:
from pocketllm import EngineArgs, LLM
args = EngineArgs(
model="/path/to/model",
backend="cpp",
tensor_parallel_size=4
)
llm = LLM(args) # Automatically spawns 4 processes
Key Changes¶
1. pocketllm/backends/factory.py¶
- Added automatic supervision detection in
create_backend(): - Detects when TP > 1, rank == 0, and no external NCCL ID provided
- Creates
TensorParallelSupervisorto spawn worker processes (ranks 1-3) - Main process runs as rank 0
-
Supervisor manages NCCL rendezvous file automatically
-
Worker script generation (
_worker_script()): - Reads configuration from environment variables set by supervisor
- Each worker process creates its own
CppBackendinstance - Worker rank mapping: supervisor rank N → actual TP rank N+1
- Workers call
backend.run_worker()to enter service loop
2. pocketllm/backends/cpp_backend.py¶
- Added cleanup logic in
close()method: - Stops supervisor if owned by this backend
- Removes temporary NCCL ID file
- Prevents process/file leaks
3. Module Installation¶
- Fixed stale module issue:
pocketllm_cpp.soin site-packages was outdated - Solution: copied latest build to site-packages directly
- Verified
run_worker_loopsymbol is present in loaded module
Verification¶
Basic Functionality Test¶
# 4 GPU processes spawn automatically
llm = LLM(EngineArgs(model="...", backend="cpp", tensor_parallel_size=4))
result = llm.generate([[1,2,3,4,5]], sampling_params={'max_tokens': 8})
# ✓ Success: generated 8 tokens
llm.close()
# ✓ All processes cleaned up
Output:
[tp rank 0] POCKETLLM_RANK_READY rank=1
[tp rank 1] POCKETLLM_RANK_READY rank=2
[tp rank 2] POCKETLLM_RANK_READY rank=3
✓ LLM created!
✓ Generated 8 tokens: [151644, 8948, 374, 264, 1296, 4320, 624, 358]
✓ Done!
All 4 GPU processes confirmed via nvidia-smi.
Concurrent Throughput Baseline¶
Model: Qwen3.8-27B-FP8
Configuration: TP=4, prompt=16 tokens, max_tokens=32, temperature=0.0
Backend: CppBackend with enable_batching=False (Phase 3.5 baseline)
| Concurrent Requests | Serial Time | Concurrent Time | Speedup |
|---|---|---|---|
| 2 | 1.493s | 1.346s | 1.11× |
| 4 | 2.696s | 2.706s | 1.00× |
| 8 | 5.437s | 5.482s | 0.99× |
Analysis:
- Minimal speedup (≤1.11×) is expected because:
- Backend has no batch scheduler (Phase 3.4 pending)
- Requests are serialized: "serialized compatibility session"
- Multiple threads calling generate() just queue requests
Comparison to Targets: - Target: 2 concurrent ≥1.7×, 4 concurrent ≥3.0×, 8 concurrent ≥4.5× - Current: 1.11×/1.00×/0.99× — significantly below target - Root cause: Lack of batching support, not TP launch mechanism
Issues Encountered and Resolved¶
Issue 1: Only rank 0 process spawned¶
Symptom: Only one GPU process, stuck waiting for NCCL rendezvous
Root cause: Initial implementation used world_size - 1, spawning only 2 workers instead of 3
Fix: Corrected to spawn exactly 3 workers (ranks 1-3), main process runs rank 0
Issue 2: Module missing run_worker_loop¶
Symptom: Worker processes failed with "native engine does not expose run_worker_loop"
Root cause: Python was loading stale pocketllm_cpp.so from site-packages (Sept 2 build) instead of latest (Sept 3)
Fix: Copied latest cpp_engine/build-python/pocketllm_cpp.so to site-packages
Issue 3: NCCL ID path mismatch¶
Symptom: All processes failed with "CmdChannel: connect failed"
Root cause: factory.py created /tmp/pocketllm_nccl_*.txt, but supervisor created its own /tmp/pocketllm-tp-*/nccl_id
Fix: Let supervisor manage NCCL ID file creation; main process reads path from supervisor
Current Status¶
✅ Completed¶
- Automatic TP process spawning for CppBackend
- Unified API with PyTorch backend (same
EngineArgsinterface) - Follows vLLM/SGLang usage conventions
- Proper cleanup of supervisor and temp files
- Basic correctness verification
⏳ Pending (Next Phase)¶
- Phase 3.4: Implement
QwenBatchSchedulerin C++ - Phase 3.5: Enable batch mode in CppBackend
- Phase 3.6: Concurrent throughput optimization to meet targets (1.7×/3.0×/4.5×)
Performance Baseline¶
Single-request latency (from previous test):
- Prompt: 16 tokens
- Generated: 32 tokens
- Latency: ~0.67s per request
Concurrent throughput (no batching): - 2 concurrent: 1.11× (below 1.7× target) - 4 concurrent: 1.00× (below 3.0× target) - 8 concurrent: 0.99× (below 4.5× target)
These numbers establish the baseline before batch scheduler implementation.
Conclusion¶
Primary objective achieved: CppBackend now launches tensor-parallel processes automatically, matching the user experience of vLLM/SGLang. Users no longer need manual process management or launcher scripts.
Performance targets not yet met: Concurrent throughput improvements require batch scheduler (Phase 3.4-3.5), which is the next implementation step.
User requirement satisfied: "不希望有什么特殊启动流程" — launch process is now unified with PyTorch backend and follows vLLM/SGLang conventions.