vllm-project / vllm-project/afd-plugin
[Feature]: Add CAMAsync multi-stream execution on a shared NPU stream pipeline
@specture724 is already working on this.
Since Aug 5, 2026.
- Dominant language
- Python
- Stars
- 228
- Forks
- 48
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 53
Description
Feature, motivation, and pitch
Add multi-stream execution for CAMAsyncAFDConnector, with a design-first requirement to determine how much infrastructure can be shared with the CAMP2P FFN-side multi-stream work proposed in #68.
CAMAsync currently has pipeline-level asynchronous behavior, but its Attention and connector-driven FFN paths do not expose a reviewed, reusable stream/event scheduler. On the FFN side, async_dispatch_recv, expert computation, and async_combine_send are orchestrated serially by the runner loop and followed by a device-wide synchronization. On the Attention side, dispatch/combine can be delayed across layers or microbatch stages, but stream placement, dependencies, buffer lifetime, and synchronization are not represented by a common runtime abstraction.
The goal is to overlap CAM communication with model computation safely, while avoiding a second connector-specific multi-stream implementation. The preferred outcome is one plugin-owned NPU stream-pipeline framework used by both CAMP2P (#68) and CAMAsync, with only operator invocation and transfer-state handling remaining connector-specific.
Related issue: #68.
Design-first requirement
Implementation must not begin with connector-local stream creation. Phase 0 must produce and review a short design that answers:
- What is common between CAMP2P and CAMAsync?
- stream creation and ownership;
- receive/compute/send phase scheduling;
- event recording and waiting;
- tensor and transfer-state lifetime tracking;
- bounded in-flight work;
- exception cleanup, shutdown, and single-stream fallback;
- profiling and correctness instrumentation.
- What must remain connector-specific?
- CAMP2P
a2e/e2aarguments, HCCL group selection, andCAMP2PTransferState; - CAMAsync
async_dispatch_recv/async_combine_sendandasync_dispatch_send/async_combine_recvarguments, pending FIFO state, routing metadata, dynamic-quant buffers, and external CAM operator constraints.
- CAMP2P
- Do the external
umdk_cam_op_libasync operators honor the activetorch.npustream, and are their communicator/handle and buffers safe for concurrent in-flight operations? - Which dependencies require NPU events, which require operator-provided completion, and where—if anywhere—is host synchronization unavoidable?
- Which combinations are supported initially: Attention side, FFN side, async MoE ubatching on/off, dynamic quantization, DP/PCP/TP/SP, and eager-only execution?
The design must include execution timelines/DAGs for both #68 CAMP2P and CAMAsync, plus a decision table showing shared versus connector-specific components. If CAM operators cannot safely execute on caller-selected streams, document the limitation and retain the common scheduling/lifecycle shell with a narrow CAM-specific synchronization adapter rather than duplicating the whole framework.
Proposed shared architecture
Introduce a plugin-owned NPU stream-pipeline layer, with final names chosen during design review. The intended ownership is:
AFDNPUStreamPipelineExecutor
owns:
compute / receive-communication / send-communication streams
reusable NPU event pool
bounded in-flight work slots
dependency scheduling
tensor/state lifetime
cleanup and single-stream fallback
Connector stream adapter
CAMP2P adapter:
recv = a2e
send = e2a
transfer state = CAMP2PTransferState
CAMAsync adapter:
recv = async_dispatch_recv
send = async_combine_send
transfer state = AFDAsyncTransferState
optional Attention-side dispatch/combine phases
The shared executor should consume explicit work items and phase callbacks or a typed adapter contract. It must not inspect connector internals with pervasive getattr/hasattr, and it must not add mutable global stream state.
The first implementation should prioritize the FFN pipeline because it maps directly to #68:
receive work N+1 on recv stream
overlaps
compute work N on compute stream
overlaps
send work N-1 on send stream
Each edge must be represented by an explicit event:
- receive complete before compute reads routed/shared activations and quantization scales;
- compute complete before send reads routed/shared outputs;
- send complete before a slot's buffers or transfer state are reused;
- layer/stage identity and CAM pending FIFO ordering remain correct.
After FFN-side correctness is established, the same framework may be extended to the CAMAsync Attention side for async_dispatch_send/async_combine_recv overlap. Attention-side support should be a separate reviewed phase because its cross-layer and two-microbatch dependency graph differs from the FFN work-item loop.
Configuration and capability gating
Define one typed multistream configuration contract shared by supported NPU connectors. Do not restore the recently removed ambiguous legacy switches (is_multistream, is_attn_multistream, is_ffn_multistream, or untyped multistream_info) without an explicit compatibility decision.
The final configuration should:
- default to the existing single-stream behavior;
- allow role/phase enablement only where implemented;
- validate connector and operator capabilities during initialization;
- bound the number of in-flight work items and streams;
- fail early for unsupported graph, topology, quantization, or async-MoE combinations;
- use the same common schema for CAMP2P and CAMAsync, with small connector-specific extensions only when required.
vLLM compatibility and extension points
Preferred extension points:
- plugin-owned
AFDNPUFFNModelRunnerconnector-driven and control-plane-driven execution; - plugin-owned NPU FFN worker loop;
- plugin-owned CAMP2P and CAMAsync connector adapters;
- plugin-owned CAMAsync Attention/model scheduling after the FFN phase is validated.
Compat shim needed: only for pinned vLLM v0.19.1 / vLLM-Ascend v0.19.1rc1 stream or forward-context contracts that cannot be accessed through stable interfaces.
Monkey patch needed: none expected. Do not modify vLLM or vLLM-Ascend source trees.
Phased implementation plan
Phase 0: design and operator-contract validation
- Document CAMP2P and CAMAsync phase DAGs, ownership, event edges, buffer reuse, error propagation, and shutdown.
- Run focused probes against
afd_ascendandumdk_cam_op_libto verify current-stream behavior and concurrent communicator/buffer safety. - Decide the shared adapter/config API and the supported initial feature matrix.
- Review the design jointly with #68 before implementation.
Phase 1: common runtime and single-stream parity
- Add the shared executor, typed work slots, event pool, adapter interface, and lifecycle management.
- Route both CAMP2P and CAMAsync through it in single-stream compatibility mode.
- Prove identical call ordering and outputs before enabling overlap.
Phase 2: FFN-side multi-stream
- Enable receive/compute/send overlap for CAMP2P (#68) and CAMAsync using the same executor.
- Replace per-step device-wide synchronization with the narrow event waits required by dependencies and shutdown.
- Keep a runtime switch for immediate fallback to serialized execution.
Phase 3: CAMAsync Attention-side evaluation
- Model the dispatch/compute/combine dependency graph across layers and async-MoE stages.
- Reuse the same stream/event/work-slot primitives.
- Enable only the combinations validated by tests and operator probes.
Phase 4: tuning and cleanup
- Tune in-flight depth and event reuse from measurements.
- Remove temporary connector-local scheduling code.
- Document the final support matrix and operational controls.
Validation plan
- CPU-safe tests for configuration parsing, capability gating, phase DAG construction, slot reuse, exception cleanup, shutdown, and serialized fallback.
- Mock-stream tests asserting exact event record/wait ordering and proving buffers are not reused before send completion.
- Connector tests preserving CAMP2P transfer state and CAMAsync routing/dynamic-quant metadata across in-flight work.
- NPU correctness tests comparing single-stream and multi-stream outputs for CAMP2P and CAMAsync.
- CAMAsync E2E coverage for prefill, including supported async-MoE ubatching and topology combinations from the Phase 0 matrix.
- Stress tests with skewed token routing, zero routed tokens on an FFN rank, multiple layers, repeated stages, and shutdown during blocked receive.
- Profiling traces showing actual overlap among receive communication, FFN computation, and send communication; operator names and stream IDs must make overlap auditable.
- Performance comparison in communication-bound and FFN-compute-bound workloads, reporting throughput and per-layer latency without setting a pass threshold until the operator-contract probe is complete.
- Regression coverage for default single-stream CAMP2P and CAMAsync behavior.
Acceptance criteria
- A reviewed design explicitly maps the common framework to both this issue and #68 before multi-stream implementation begins.
- CAMP2P and CAMAsync use the same concrete stream executor, event pool, work-slot lifecycle, configuration model, and fallback path; the shared layer is exercised by both, not merely prepared for future reuse.
- Connector-specific code is limited to typed operator adapters and transfer-state semantics.
- CAMAsync FFN receive/compute/send overlap is visible in an NPU profiling trace and produces output equivalent to the serialized path.
- No device-wide synchronization remains in the steady-state multi-stream loop unless Phase 0 proves it is required by an external operator; any such synchronization is isolated and documented.
- Tensor buffers, routing metadata, quantization scales, transfer states, and communicator resources remain valid until their dependent event completes.
- Unsupported feature combinations fail during initialization, and the default remains safe single-stream execution.
- No vLLM or vLLM-Ascend source modification is required.
Before submitting
- I searched existing issues and RFCs.
- I identified this as plugin-owned NPU scheduling and connector-adapter work, with a versioned compat helper only if required by the pinned runtime.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.