Lab 05-04 · RPC cluster¶
Objective¶
Run a model using the memory (and, if present, the GPU) of another machine through the ggml RPC backend:
start ggml-rpc-server on the remote host, connect to it with --rpc, check how the weights are distributed and measure the
price you pay in speed. The same exercise works on a single machine with two terminals (or two containers):
that is the setup used in the examples below.
Prerequisites¶
- Two machines on the same trusted local network (A = main, B = remote), or a single machine with two terminals.
- On both, the release tarball binaries (e.g.
llama-b11046-bin-ubuntu-x64.tar.gz, module 01) or a build with-DGGML_RPC=ON. The installer'sllamabinary does not have the RPC backend: its--helpdoes not show--rpc. - The model downloaded on machine A (B receives the tensors over the network, it does not read the file).
Materials¶
| What | Source | Size |
|---|---|---|
| Test model | ggml-org/Qwen3.5-0.8B-GGUF → Qwen3.5-0.8B-Q8_0.gguf (Apache 2.0) |
795 MB |
| Model "that does not fit" (variant) | ggml-org/gemma-3-12b-it-GGUF:Q4_K_M |
6.96 GB |
| Binaries | release tarball in ~/llama-lab/rel/llama-b11046/ (contains ggml-rpc-server, llama-cli, llama-server, llama-bench and libggml-rpc.so) |
16 MB |
Expected output:
load_backend: loaded RPC backend from …/libggml-rpc.so
load_backend: loaded CPU backend from …/libggml-cpu-haswell.so
Usage: ggml-rpc-server [options]
-t, --threads N number of threads for the CPU device (default: 3)
-d, --device <dev1,dev2,...> comma-separated list of devices
-H, --host HOST host to bind to (default: 127.0.0.1)
-p, --port PORT port to bind to (default: 50052)
-c, --cache enable local file cache
Steps¶
-
On machine B (or in terminal 1): start the server. Locally use
127.0.0.1; on two machines use B's LAN address (-H 192.168.1.20) and only on a trusted network:Expected output:
Starting RPC server v7.0.0 endpoint : 127.0.0.1:50052 local cache : n/a Devices: CPU: AMD EPYC Processor (with IBPB) (11960 MiB, 11960 MiB free) transport : TCPOn a machine with a GPU you see
CUDA0: NVIDIA … (32109 MiB, 31588 MiB free)instead; with-d CUDA0orCUDA_VISIBLE_DEVICESyou choose which devices to expose. -
On machine A (terminal 2): is the remote device visible?
The device is called
RPC0(thenRPC1… for other servers, in list order). On the server you seeAccepted client connection/Client connection closed. -
Generate across the network.
M=$(ls ~/.cache/huggingface/hub/models--ggml-org--Qwen3.5-0.8B-GGUF/snapshots/*/Qwen3.5-0.8B-Q8_0.gguf) $R/llama-cli --rpc 127.0.0.1:50052 -m "$M" -st -p "ciao" -n 20 -t 3 -rea offOutput on a 6 vCPU machine without GPU:
Loading is slower than usual: the weights are sent to the RPC server (785 MB over loopback in a few seconds; on a 1 Gbit/s LAN about 8 seconds, for a 7 GB model over a minute).
-
Where did the weights go? Repeat with
-v(full log) and look for the buffers:$R/llama-cli --rpc 127.0.0.1:50052 -m "$M" -st -p "ciao" -n 5 -rea off -v 2>&1 | grep -E "RPC0|CPU_Mapped|offloaded|buffer size"By default llama.cpp distributes weights and KV cache between local and remote devices in proportion to free memory;
-nglalso counts the RPC device as a "GPU". With-tsyou set the proportions:-ts 1,0(everything on the first device),-ts 1,1(half and half). Try-ngl all -ts 0,1to send everything to the remote server and compare theGeneration:line with step 3. -
The HTTP server with a remote backend. Everything that applies to
llama-cliapplies tollama-server:Stop it with Ctrl+C and read
llama_memory_breakdown_print: there is a line forRPC0. -
Local cache (variant). On B restart with
-c: on the second run the large tensors are read from~/.cache/llama.cpp/rpcinstead of being received over the network. Time the loading before and after. -
Shut everything down. Ctrl+C on the RPC server, or:
An RPC server left running is a risk (see below).
Check the result¶
-
--list-devicesshowsRPC0with the server's memory. - The model answered through RPC and you noted pp/tg.
- You compared the speed with the same command without
--rpc: the difference is the cost of the network (small locally, large on a LAN). - You shut down the RPC server and checked with
pgrep -af rpc-serverthat it is gone.
No authentication: trusted network only
ggml-rpc-server has no password, token or TLS; the official README calls it a proof of concept, fragile and
insecure and says to never run it on an open network. Anyone who reaches the port can use your GPU and your RAM
at will. Rules: -H 127.0.0.1 or an isolated LAN address, a firewall that accepts only machine A, or an
SSH tunnel (ssh -L 50052:localhost:50052 utente@B) or a VPN; shut the server down when you do not need it.
Questions and variants¶
- Why is generation over RPC slower even when the server has a fast GPU? Think about what crosses the network at every token (activations between layers) and with what latency.
- With two machines:
-ts 3,1(A keeps 75 %) against-ts 1,3. Which order is better if A has the faster GPU? - Two RPC servers:
--rpc B:50052,C:50052. In what order do they appear in--list-devices? GGML_RPC_DEBUG=1 ggml-rpc-server …shows every command received: count how many messages it takes to generate 5 tokens.- Two containers on the same machine: create a network (
docker network create rpc), start two Ubuntu containers with the tarball mounted in/opt/llamaand use the container names as hosts (--rpc rpc-b:50052). Same security rules: the network is internal to Docker, do not publish the port with-p. - With a GPU on B and a model that does not fit in A's VRAM (gemma-3-12b), compare: everything on A with partial
-nglagainst A+B via RPC. The winner depends on the network: with 1 Gbit/s almost always the local hybrid, with 10 Gbit/s or Thunderbolt/RDMA the cluster.
Deliverable¶
The server startup log (the Devices: lines), the --list-devices output, the [ Prompt … | Generation … ] line
with and without --rpc, and five lines of conclusions: when you would use RPC and which security measures you would adopt.