Skip to content

RPC: Pipeline parallelism - #202

Merged
gianni-cor merged 7 commits into
rpc-tensor-upstreamfrom
pipeline_parallel
Aug 25, 2026
Merged

gianni-cor merged 7 commits into
rpc-tensor-upstreamfrom
pipeline_parallel

Conversation

@amangupta-tether

@amangupta-tether amangupta-tether commented Aug 6, 2026

Copy link
Copy Markdown

Overview

https://app.asana.com/0/0/1217186633202282/f

Tested on 2x DGX Sparks with -ub 512 -p 2048 on llama-bench. 47% better throughput with PP compared to no layer parallelism

model size params backend ngl split pipeline fa dev ts dio test t/s
deepseek4 MXFP4 MoE 145.63 GiB 284.33 B CUDA,RPC 999 layer 0 1 RPC0/RPC1 1.00/1.00 1 pp2048 398.47 +/- 13.87
deepseek4 MXFP4 MoE 145.63 GiB 284.33 B CUDA,RPC 999 layer 1 1 RPC0/RPC1 1.00/1.00 1 pp2048 587.11 +/- 5.76
deepseek4 MXFP4 MoE 145.63 GiB 284.33 B CUDA,RPC 999 tensor 0 1 RPC0/RPC1 1.00/1.00 1 pp2048 500.00 +/- 12.15
deepseek4 MXFP4 MoE 145.63 GiB 284.33 B CUDA,RPC 999 layer 0 1 RPC0/RPC1 1.00/1.00 1 tg128 14.98 +/- 0.09
deepseek4 MXFP4 MoE 145.63 GiB 284.33 B CUDA,RPC 999 layer 1 1 RPC0/RPC1 1.00/1.00 1 tg128 14.48 +/- 0.14
deepseek4 MXFP4 MoE 145.63 GiB 284.33 B CUDA,RPC 999 tensor 0 1 RPC0/RPC1 1.00/1.00 1 tg128 18.17 +/- 0.60

Additional information

Requirements

@github-actions github-actions Bot added documentation Improvements or additions to documentation examples ggml testing devops labels Aug 6, 2026
@amangupta-tether
amangupta-tether marked this pull request as ready for review August 17, 2026 06:29
@amangupta-tether
amangupta-tether requested review from a team as code owners August 17, 2026 06:29
Comment thread tests/CMakeLists.txt
Comment thread ggml/src/ggml-rpc/ggml-rpc.cpp Outdated
swap ? backend_dst : backend_src,
swap ? backend_src : backend_dst,
};
auto * comm = (ggml_backend_rpc_comm_context *) ggml_backend_rpc_comm_init(ranks, 2);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add multi-node support for GGML_RPC_DIRECT_COPY.

Layer pipelines with more than two stages need the middle server to communicate with both neighbours: A↔B and B↔C. The current server state holds only one peer per device, so after A↔B is initialized, B cannot create the B↔C connection. That prevents direct server-to-server activation copies in a multi-stage pipeline.

Please store direct-copy peers per remote endpoint/session, with clear lifetime management, and add a three-endpoint test that verifies A→B and B→C direct copies in the same run.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have dropped GGML_RPC_DIRECT_COPY feature entirely as it was providing no measurable benefit, we can revisit at a later stage if required.

@amangupta-tether
amangupta-tether force-pushed the pipeline_parallel branch 2 times, most recently from 83df9ac to 33b0775 Compare August 19, 2026 06:13
Comment thread ggml/src/ggml-rpc/ggml-rpc.cpp Outdated
Comment thread .github/workflows/build-rpc.yml
@DmitryMalishev

This comment was marked as resolved.

Comment thread .github/workflows/build-rpc.yml Outdated
Comment thread ggml/src/ggml-rpc/ggml-rpc.cpp Outdated
Comment thread ggml/src/ggml-rpc/ggml-rpc.cpp
Comment thread ggml/src/ggml-rpc/ggml-rpc.cpp
Comment thread ggml/src/ggml-rpc/ggml-rpc.cpp
@amangupta-tether
amangupta-tether force-pushed the pipeline_parallel branch 2 times, most recently from 889bdbe to e2f5ffd Compare August 25, 2026 08:59
amangupta-tether and others added 6 commits August 25, 2026 17:44
Resolve sub-buffers in meta and RPC backends so split allocations retain their owning buffer.

Assisted-by: GPT-5.6 Sol
Exercise asynchronous transfers, events, cross-server copies, memset, graph execution, and pairwise all-reduce against live RPC endpoints.

Assisted-by: GPT-5.6 Sol
Comment on lines +649 to +656
~rpc_command_queue() {
{
std::lock_guard<std::mutex> lock(mutex);
shutdown = true;
}
cv.notify_one();
if (worker.joinable()) {
worker.join();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amangupta-tether could you take a look at the Windows CI failure here?

windows (x64-openblas) is failing on ctest #27 test-thread-safety with 0xC0000374 (STATUS_HEAP_CORRUPTION):

27: All threads finished without errors.
26/38 Test #27: test-thread-safety ....Exit code 0xc0000374 ***Exception: 50.12 sec
The following tests FAILED:
	 27 - test-thread-safety (Exit code 0xc0000374)

job log

Note the ordering: the test prints "All threads finished without errors" and only then aborts, so the heap corruption is being detected during teardown rather than in the test body. The two sibling matrix jobs (x64-vulkan, x64-cpu-static) show The operation was canceled — that's just fail-fast collateral from this one, not separate failures.

Where I'd start looking: this destructor joins worker, and the queue instances are kept in a function-local static std::unordered_map<std::string, std::weak_ptr<rpc_command_queue>> in get_command_queue() below. On Windows, a thread joined from static-destruction / DLL-unload order is a very common source of exactly this signature. Worth ruling out first — I haven't confirmed it from a stack trace, so it's a starting point rather than a diagnosis.

Two data points on scope:

For what it's worth, the other red checks on this PR are not code: cpu-x64-high-perf ran all suites green (53/53 and 56/56) and then died with exit code 127 / '/opt/actions-runner-3/externals/node24/bin/node' ... No such file or directory, which is self-hosted runner breakage.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gianni-cor please see

The failure is real, but the proposed RPC diagnosis is not supported.

• The same queue/destructor code passed x64-openblas twice immediately beforehand.
• Since that passing head, only CUDA kernels and RPC server tensor deserialization changed. Neither runs in test-thread-safety.
• The test never adds an RPC server, so no rpc_command_queue worker is created.
• The static map stores weak_ptrs, so its destruction cannot trigger queue destruction or worker.join().

The post-test crash indicates teardown-time corruption, but not RPC teardown specifically. Treat this as a likely Windows/OpenBLAS flake and rerun the failed job; no PR 202 code change is justified from this evidence
alone.

@gianni-cor
gianni-cor merged commit 29db2fb into temp-10297 Aug 25, 2026
33 of 49 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

devops documentation Improvements or additions to documentation examples ggml testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants