I built a local LLM box with two AMD Radeon AI PRO R9700 GPUs and could not find much practical benchmark information online, so I ran a small set of llama.cpp ROCm tests and wrote up the results. This is not a perfect lab benchmark; it is a field note for people trying to decide what these cards are useful for in local inference.
The main finding: dual R9700s are very useful for long-context prompt processing, but they do not magically improve single-stream token generation. For interactive chat, one GPU can be just as fast. For long prompts, RAG, document ingestion, or throughput-oriented serving, the second GPU starts to matter.
I tested local GGUF inference on a desktop with 2× AMD Radeon AI PRO R9700 GPUs using ROCm + llama.cpp on Ubuntu. The short version:
- ROCm works on this setup, but the software stack matters.
- For dense models, Qwen3.6 27B Q5_K_M was faster than Gemma 4 31B it Q5_K_M.
- Dual GPUs helped a lot with prompt processing / prefill, especially at longer contexts.
- Dual GPUs did not improve single-stream token generation; generation speed was often the same or slightly slower than one GPU.
- Sparse-active / MoE-like models such as Gemma 4 26B A4B and Qwen3.6 35B A3B UD-Q5_K_M showed much higher throughput, but they should not be compared directly against dense models as if the architectures were the same.
- Practical takeaway: use one GPU when decode latency is the bottleneck and the model fits; use two GPUs when long-context prefill or throughput matters.
I bought/assembled a dual-R9700 local LLM system and found very little practical benchmark information online for these cards. Most local inference discussion is still centered around NVIDIA cards, older AMD cards, or cloud GPUs.
So this is not meant to be a definitive leaderboard. It is a practical report from one real system:
- What works?
- What kind of throughput should I expect?
- Does a second R9700 help?
- Which settings seem sensible for llama.cpp serving?
| Component | Details |
|---|---|
| CPU | AMD Ryzen 9 7900X, 12 cores / 24 threads |
| Motherboard | ASRock X870E Taichi Lite |
| RAM | 64 GB system memory |
| GPUs | 2× AMD Radeon AI PRO R9700, gfx1201, ~32 GB VRAM each |
| iGPU | AMD Radeon Graphics, gfx1036; intentionally avoided for compute |
| OS | Ubuntu 26.04 LTS |
| Kernel | Linux 7.0.0-15-generic |
| ROCm | ROCm 7.2.2 userspace with Ubuntu in-kernel amdgpu |
| llama.cpp commit | d77599234ea6e498775aeadbce665eece5bd98cd |
Important runtime detail: I used HIP_VISIBLE_DEVICES=0 or HIP_VISIBLE_DEVICES=0,1 to avoid accidentally involving the integrated GPU.
Dense models:
Qwen3.6-27B-Q5_K_M.ggufgemma-4-31B-it-Q5_K_M.gguf
Sparse-active / MoE-like models:
Qwen3.6-35B-A3B-UD-Q5_K_M.ggufgemma-4-26B-A4B-it-UD-Q5_K_M.gguf
I keep dense and sparse-active models separate below because active-parameter count changes the meaning of throughput numbers.
Main benchmark command pattern:
./build-rocm/bin/llama-bench \
-m <model.gguf> \
-ngl 99 \
-sm <none|layer> \
-p 512,1024,2048,4096,8192,16384,32768 \
-n 128 \
-b 2048 \
-ub 512 \
-ctk q8_0 \
-ctv q8_0 \
-fa 1 \
-r 3 \
-o mdSingle GPU:
HIP_VISIBLE_DEVICES=0
-sm noneDual GPU:
HIP_VISIBLE_DEVICES=0,1
-sm layerParameter notes:
-ngl 99: offload all possible layers to GPU.-fa 1: flash attention enabled.-ctk q8_0 -ctv q8_0: q8_0 KV cache. I chose this for long-context VRAM practicality and comparable runs.-b 2048: logical batch size.-ub 512: initial microbatch size. I later compared512vs1024.-r 3: three repetitions.pp*: prompt processing / prefill throughput.tg128: generation throughput for 128 generated tokens.
| Test | Single R9700 tok/s | Dual R9700 tok/s |
|---|---|---|
| pp512 | 956.41 | 860.92 |
| pp1024 | 913.89 | 1227.66 |
| pp2048 | 877.56 | 1432.51 |
| pp4096 | 846.78 | 1534.47 |
| pp8192 | 798.67 | 1529.63 |
| pp16384 | 722.98 | 1425.44 |
| pp32768 | 611.02 | 1215.87 |
| tg128 | 24.85 | 24.31 |
Qwen3.6 27B is a good example of the main pattern: dual GPUs roughly doubled long-context prefill performance, but did not help generation.
| Test | Single R9700 tok/s | Dual R9700 tok/s |
|---|---|---|
| pp512 | 751.77 | 695.98 |
| pp1024 | 703.40 | 931.71 |
| pp2048 | 651.97 | 1049.70 |
| pp4096 | 616.22 | 1105.74 |
| pp8192 | 573.55 | 1088.55 |
| pp16384 | 511.90 | 1000.07 |
| pp32768 | 425.48 | 840.01 |
| tg128 | 21.74 | 21.18 |
Gemma 4 31B showed the same broad behavior, but was slower than Qwen3.6 27B in this dense-model comparison.
For dense GGUF serving on this system, Qwen3.6 27B Q5_K_M looks like the better speed candidate than Gemma 4 31B Q5_K_M.
The second GPU is useful for prompt ingestion, especially long-context workloads. It is not useful for improving single-stream decode speed in these tests.
Source: unsloth/Qwen3.6-35B-A3B-GGUF, file Qwen3.6-35B-A3B-UD-Q5_K_M.gguf (~25 GB).
| Test | Single R9700 tok/s | Dual R9700 tok/s |
|---|---|---|
| pp512 | 2653.96 | 2522.14 |
| pp1024 | 2562.32 | 3224.92 |
| pp2048 | 2477.70 | 3708.46 |
| pp4096 | 2369.20 | 3913.99 |
| pp8192 | 2210.13 | 3880.54 |
| pp16384 | 1977.61 | 3590.30 |
| pp32768 | 1636.86 | 3038.47 |
| tg128 | 77.25 | 71.88 |
| Test | Single R9700 tok/s | Dual R9700 tok/s |
|---|---|---|
| pp512 | 3079.41 | 2360.63 |
| pp1024 | 3003.94 | 3215.09 |
| pp2048 | 2795.09 | 4341.08 |
| pp4096 | 2667.01 | 4595.05 |
| pp8192 | 2463.88 | 4562.45 |
| pp16384 | 2173.67 | 4250.05 |
| pp32768 | 1781.85 | 3513.11 |
| tg128 | 74.26 | 66.56 |
These numbers are much higher than the dense models, but that is expected for sparse-active architectures. The fair conclusion is not “Gemma 26B beats dense 27B/31B in every way”; it is that sparse-active models deserve their own category and are very interesting for local serving.
I also tested whether a larger microbatch helped.
| GPU mode | ubatch | pp8192 | pp32768 | tg128 |
|---|---|---|---|---|
| Single R9700 | 512 | 805.68 | 611.26 | 24.86 |
| Single R9700 | 1024 | 831.85 | 632.91 | 24.86 |
| Dual R9700 | 512 | 1531.27 | 1215.35 | 24.15 |
| Dual R9700 | 1024 | 1462.58 | 1207.05 | 23.97 |
For Qwen3.6 27B, -ub 1024 helped slightly on one GPU but not on two GPUs. For dual GPU, -ub 512 looked better or equal.
| GPU mode | ubatch | pp8192 | pp32768 | tg128 |
|---|---|---|---|---|
| Single R9700 | 512 | 2467.67 | 1776.59 | 74.26 |
| Single R9700 | 1024 | 2861.23 | 1986.70 | 74.25 |
| Dual R9700 | 512 | 4567.68 | 3507.79 | 66.68 |
| Dual R9700 | 1024 | 4913.87 | 3807.60 | 66.56 |
For Gemma 4 26B A4B, -ub 1024 clearly improved prompt processing and did not materially change generation.
The clearest win for two R9700s was long-context prompt processing.
For Qwen3.6 27B:
pp32768single GPU: 611.02 tok/spp32768dual GPU: 1215.87 tok/s
For Gemma 4 31B:
pp32768single GPU: 425.48 tok/spp32768dual GPU: 840.01 tok/s
For Qwen3.6 35B A3B UD-Q5_K_M:
pp32768single GPU: 1636.86 tok/spp32768dual GPU: 3038.47 tok/s
For Gemma 4 26B A4B:
pp32768single GPU: 1781.85 tok/spp32768dual GPU: 3513.11 tok/s
That is the happy story.
The less exciting story is generation:
- Qwen3.6 27B: 24.85 tok/s single vs 24.31 tok/s dual
- Gemma 4 31B: 21.74 tok/s single vs 21.18 tok/s dual
- Qwen3.6 35B A3B: 77.25 tok/s single vs 71.88 tok/s dual
- Gemma 4 26B A4B: 74.26 tok/s single vs 66.56 tok/s dual
For one interactive user, single-GPU decode can be just as good or better. For workloads with long prompts, large documents, RAG, or multi-user serving, dual GPUs become much more interesting.
For my current OpenAI-compatible llama.cpp server test, I am using Qwen3.6 27B with roughly 200k context:
HIP_VISIBLE_DEVICES=0,1 ./build-rocm/bin/llama-server \
-m ~/models/Qwen3.6-27B-Q5_K_M.gguf \
-a qwen3.6-27b-q5km-rocm-200k \
-ngl 99 \
-c 200000 \
-fa 1 \
--reasoning off \
-ctk q8_0 \
-ctv q8_0 \
-b 2048 \
-ub 512 \
-np 1 \
-sm layer \
--host <host> \
--port 8080 \
--no-webuillama.cpp rounded the context to 200192. Flash attention is enabled. The server keeps the model loaded in VRAM until stopped; it does not automatically unload and reload the model in my current setup.
I also disabled reasoning by default for interactive use because the hidden reasoning overhead made answers noticeably slower. It can still be useful for harder questions, but for a daily-driver local model I prefer fast direct answers by default.
- These are
llama-benchresults, not a full application benchmark. - I still need to run more
llama-serverAPI latency tests: time-to-first-token, full response latency, and real prompt workloads. q8_0KV is practical for long context, butf16KV should be compared for quality and speed before making final serving claims.- Model quality is not measured here. This post is mostly about throughput and practical setup.
- ROCm support is improving quickly, so results may change with driver, ROCm, and llama.cpp updates.
- Sparse-active and dense model numbers should not be mixed into one simplistic ranking.
If you have a similar dual-R9700 setup:
- Use
HIP_VISIBLE_DEVICESexplicitly so the iGPU does not get involved. - Use one GPU for latency-sensitive single-user generation when the model fits.
- Use two GPUs when long-context prefill is the bottleneck.
- Keep dense and sparse-active model comparisons separate.
- Try Qwen3.6 27B Q5_K_M as a dense baseline.
- Try Gemma 4 26B A4B or Qwen3.6 35B A3B UD-Q5_K_M if sparse-active models fit your use case.
- Do not assume a second GPU improves decode speed. Test it.
- llama-server API latency with short, medium, and long prompts.
- Time-to-first-token under OpenAI-compatible API calls.
f16KV vsq8_0KV at 8k and 32k.- Single-user vs multi-user server behavior.
- More model quality notes, not just speed.