Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Thor Tigress Cub

TensorRT Edge-LLM

The Thor served its models with llama.cpp only. NVIDIA’s engine for the Thor is TensorRT Edge-LLM. This chapter is the plan to test it, the design for two engines behind one agent, and the first results.

Status, 2026-10-06: Qwen3.6-35B-A3B in NVFP4 runs on Edge-LLM v0.11.0 as a second model in the Thor Tigress Cub’s picker, next to Nemotron 3 Nano on llama.cpp. The results are in “First results” below. The Nano on Edge-LLM hasn’t been built yet. Facts about Edge-LLM come from NVIDIA’s documentation and release notes; each source is named.

This chapter covers

  • why Edge-LLM and not TensorRT-LLM
  • what Edge-LLM supports on the Thor, and what is still experimental
  • the system design for two engines behind one agent
  • the build-and-test pipeline, step by step
  • what to measure, and when Edge-LLM would replace llama.cpp
  • the open questions and risks

Why Edge-LLM

EngineOn the ThorModel formatServing
llama.cpp (today)built here from commit 8216c84 for sm_110GGUF (Nemotron 3 Nano Q8_0, 33.6 GB)llama-server, OpenAI-compatible, router mode
TensorRT-LLMnot supported on Jetson; NVIDIA’s forum points Thor users to Edge-LLMTensorRT enginestrtllm-serve
TensorRT Edge-LLMofficially supported: JetPack 7.0/7.1 (CUDA 13.0) and 7.2 (CUDA 13.2)TensorRT engines built on the deviceexperimental OpenAI-compatible server

The Thor has TensorRT 10.16.2 and CUDA 13.2 installed (checked with pip and dpkg). Edge-LLM isn’t installed.

The reason to try it is speed. Generating a token reads every active weight once, so speed follows the bytes read per token (chapter “Model serving”, “Estimate its speed”). NVIDIA publishes the Nano in NVFP4, a 4-bit format the Thor’s Blackwell GPU runs natively. It is 19.3 GB against 33.6 GB for our Q8_0: about 0.61 bytes per parameter, so about 2 GB read per token for 3.2B active. The same formula estimates about 90 tok/s against the 53.5 measured today. That is an estimate from one calibration point, not a measurement.

The one published Thor result: in the MLPerf Inference v6.1 Edge Agentic benchmark, Edge-LLM ran Qwen3.6-27B in NVFP4 at 52.33 output tokens/s, with a median 247 ms to the first token, and finished 6.4 times faster than the llama.cpp reference run (24 min 36 s against 2 h 37 min, 1,007 turns, inputs up to about 23.5K tokens). That is a different model and workload from ours.

What Edge-LLM supports

From the supported-models page and the release notes:

ItemStatus
Nemotron 3 Nano 30B-A3Bsupported in NVFP4 (nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4, 19.3 GB) since v0.7.0
Nemotron 3.5 Lightning 30B-A3Bsupported in NVFP4 (21.6 GB), with MTP and DFlash speculative decoding, since v0.10.0
Nemotron 3 Super 120B-A12Bsupported in NVFP4
Mixture-of-experts and Mamba hybridssupported for the listed models only
OpenAI-compatible serverexperimental since v0.7.0; in-flight batching, single rank, since v0.11.0
Python wheels for aarch64since v0.11.0 (2026-09-29), Python 3.10 to 3.12
Latest releasev0.11.0, 2026-09-29

System design

thor-tigress-agent on 8080 routes each request by model id to either the llama.cpp router on 8079, serving Nemotron 3 Nano from a GGUF file, or the TensorRT Edge-LLM server on 8081, serving Qwen3.6-35B-A3B from engines built on the Thor. thor-tigress-serve manages both.
Figure 16.1 Two engines behind one agent, running since 2026-10-06.
PartBeforeNow (2026-10-06)
thor-tigress-agentone model server (--model 127.0.0.1:8079)--engine MODEL=HOST:PORT per other engine; each request goes to the engine serving the model it names; /v1/models merges the lists, leaving out an engine that doesn’t answer
llama.cpp router:8079, GGUF files in ~/models/gguf/unchanged
Edge-LLM servernone:8081, user service thor-edge-llm (thor-tigress-serve edge), capped at 48 GB; checkpoint in ~/models/edge-llm/<model>/, engines in ~/models/edge-llm/cache/
thor-tigress-servellama.cpp onlyEDGE_MODEL names the checkpoint; list shows it with its engine; load and unload start and stop its service
memory checkscover llama.cpp’s modelsload checks free memory for either engine

Design rules:

  • Clients don’t change. The web chat, Claude Code and OpenCode keep sending a model name to :8080. Which engine serves it is the agent’s business.
  • One model, one engine at a time. The Nano in Q8_0 on llama.cpp (57.8 GB with 4 × 1M context) and the Nano in NVFP4 on Edge-LLM side by side may not fit. The test runs Edge-LLM with the llama.cpp Nano unloaded, at a quiet hour.
  • Engines are built, not downloaded. A TensorRT engine is compiled for the exact GPU that runs it, so every engine is built on the Thor.

The pipeline

Planned pipeline: NVIDIA's NVFP4 checkpoint from Hugging Face, exported to ONNX with tensorrt-edgellm-export, built into a TensorRT engine on the Thor with llm_build, served by the experimental OpenAI-compatible server on port 8081, and measured against llama.cpp with the same prompts.
Figure 16.2 From checkpoint to measured engine.

The commands follow the Jetson AI Lab tutorial and the Edge-LLM docs. None were run here yet.

1. Tools. NVIDIA’s PyTorch container for export, and the C++ runtime built on the Thor:

docker pull nvcr.io/nvidia/pytorch:26.05-py3
git clone https://github.com/NVIDIA/TensorRT-Edge-LLM.git
cd TensorRT-Edge-LLM && git submodule update --init --recursive
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DTRT_PACKAGE_DIR=/usr \
  -DCMAKE_TOOLCHAIN_FILE=cmake/aarch64_linux_toolchain.cmake \
  -DEMBEDDED_TARGET=jetson-thor -DCUDA_CTK_VERSION=13.0 -DENABLE_CUTE_DSL=ALL
make -j"$(nproc)"

The tutorial passes -DCUDA_CTK_VERSION=13.0; the Thor has CUDA 13.2. Whether that matters is the first thing to check.

2. Checkpoint and export. NVIDIA publishes the Nano already in NVFP4, so the quantize step is skipped. The export takes a checkpoint folder:

hf download nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4 --local-dir ~/models/edge-llm/nemotron-3-nano/checkpoint
tensorrt-edgellm-export ~/models/edge-llm/nemotron-3-nano/checkpoint ~/models/edge-llm/nemotron-3-nano/onnx

3. Build the engine on the Thor:

./build/examples/llm/llm_build --onnxDir ~/models/edge-llm/nemotron-3-nano/onnx \
  --engineDir ~/models/edge-llm/nemotron-3-nano/engine

4. Serve. The experimental server, on a port of its own:

python -m experimental.server --model <engine or checkpoint> --port 8081

5. Measure. First with the C++ benchmark tool (./build/examples/llm/llm_bench --engineDir … --mode generation), then through the server with the same requests sent to llama.cpp.

What to measure

Each with the date, the Edge-LLM version, the precision, the context size and the number of slots, as for every number in this book.

MeasureHowllama.cpp today
generation speed, one replythe Rust prompt from chapter “Model serving”, 600 tokens, thinking off53.5 tok/s
generation speed, four replies at oncefour requests together; tok/s each and in totalto measure
time to first tokenprompts of 1K and 23.5K tokensto measure
memoryMemAvailable before and after starting the server57.8 GB (4 × 1M)
longest context that loadsraise until it fails1,048,576 per slot × 4
answer qualityspark scores on the same 20 prompts; compile rate of the Rust answersto measure
export and build timewall clock for steps 2 and 3none (GGUF is downloaded as is)
diskONNX plus engine size33.6 GB
stabilitythe server under the chat’s normal use for 24 hoursto measure the same way

Edge-LLM becomes the default engine for a model only if:

  • it generates at least 1.5 times faster on one reply and on four,
  • spark scores and compile rates are no worse,
  • it fits with at least 8 GB free at the context the chat needs,
  • and its server handles thinking and tool calls (below) for 24 hours without a restart.

First results

Measured on 2026-10-06 on the Thor, with Edge-LLM v0.11.0 installed from its aarch64 wheel into ~/.local/share/edge-llm/venv (no container: Docker needs sudo there, and the wheel carries the runtime built for jetson-thor-jp72-cu13-sm110).

Build. tensorrt-edgellm-serve built everything itself from nvidia/Qwen3.6-35B-A3B-NVFP4 (23.4 GB) on its first start:

StepTime
language-model engine (40 layers)270 s, of which TensorRT 261 s
vision engine (the checkpoint is multimodal)113 s
first start, total, to the first answer442 s
later starts, engines reused from the cache30 s

The engines take 1.7 GB on disk; the weights stay in the checkpoint. The vision engine built without trouble, unlike issue #233.

Memory. Free memory went from 59 GB to 29 GB while the server started next to the Nano, with a 32K-token context and one reply at a time (--max-kv-cache-capacity 32768 --max-input-len 16384 --max-batch-size 1). It settled at about 35 GB free with both running.

Features the chat needs. With --reasoning-parser auto --tool-call-parser auto, through the agent:

FeatureResult
streamed reasoning (reasoning_content) with Think onyes; first token 0.12 s on the server
enable_thinking: falseanswers without reasoning
tool calls (the Web switch)yes: it called web_search and the agent’s search loop ran

The same 20 Rust tasks (in jetson-thor/model-serving/compare.py: median, config parsing, brackets, a ring buffer and so on), one turn each, thinking off, at most 2,048 tokens, first Rust block compiled with rustc --edition 2024 --test:

Qwen3.6-35B-A3B NVFP4, Edge-LLMNemotron 3 Nano Q8_0, llama.cpp
speed, median78.0 tok/s53.3 tok/s
compiles18 of 2015 of 20
tests pass14 of 2014 of 20
answers cut at 2,048 tokens06
spark: all five rules30%5%
spark: no comments in function bodies40%18%
spark: no unwrap90%76%
spark: false claims0%0%
words of prose per answer0 (code only)238

Against the bar in “What to measure”: faster, more answers compile, better on the five rules, no false claims; tests passing are equal. So it went into the chat as an option, not as the default. The speed estimate of about 90 tok/s was 15% high.

Not measured yet: four replies at once (the server was built for one), time to first token on long prompts, the longest context it holds, and 24 hours of use.

A clean-code model in the chat

The second use of Edge-LLM: a model picked for writing clean code, offered in the Thor Tigress Cub’s model picker next to the Nano.

Candidates. Models on Edge-LLM’s supported list with an NVFP4 checkpoint published by NVIDIA (sizes from the Hugging Face file listings):

ModelKindCheckpointSizeSpeed estimate
Qwen3.8-27Bdense, 27.3Bnvidia/Qwen3.8-27B-NVFP421.9 GBabout 8 tok/s by the formula; Edge-LLM ran its predecessor Qwen3.6-27B at 52.33 tok/s output throughput in MLPerf, a batched workload
Qwen3.6-35B-A3Bmixture of experts, 34.7B total, 3B activenvidia/Qwen3.6-35B-A3B-NVFP423.4 GBabout 90 tok/s by the formula

Qwen3-Coder-Next, the coding model in chapter “Model serving”, isn’t on Edge-LLM’s list, so it stays a llama.cpp candidate.

How the winner is picked. Clean code is measured, not judged by eye:

MeasureToolPass mark
the five Rust rulesspark, on the answers to the same 20 Rust taskshigher than the Nano’s score on the same tasks
compilescargo build on each answer, as teacher doeshigher than the Nano’s rate
tests passthe tests in each taskhigher than the Nano’s rate
no false claimsspark’s false-claim checklower than the Nano’s rate
speedtok/s through the agent, one replyat least 30 tok/s, to keep the chat usable

The baseline is the Nano’s numbers on the same tasks, measured the same day. A coding model alone isn’t enough: in the earlier baseline (chapter “The checker: spark”), Qwen2.5-Coder-7B on TensorRT-LLM followed all five rules in 4% of its answers.

In the chat. The winner gets an engine of its own on the Edge-LLM server and appears in the picker as one more model. The agent sends requests for it to :8081 and everything else to :8079 (figure 16.1). Memory: the Nano takes 57.8 GB, so about 50 GB is left with 8 GB kept free. A 22 to 23 GB checkpoint plus its context fits, at a context to be measured.

Steps, each needing a GPU time window on the Thor:

  1. Build both candidates’ engines (pipeline above).
  2. Run the 20 Rust tasks through each, and through the Nano.
  3. Score them with spark, cargo build and the tests.
  4. Serve the winner on :8081, add the agent’s routing, and add it to the picker.

Open questions and risks

QuestionWhy it mattersHow to find out
Does the experimental server stream reasoning_content and honour chat_template_kwargs.enable_thinking?the chat’s Think switch and the thinking panel depend on itsend the chat’s own request and read the stream
Does it support tool calls?the Web switch runs a web_search tool loop in the agenta request with tools
How long a context can the engine hold, and at what memory cost?the Nano is served with 1M tokens per slotstep 5, “longest context”
Does the server rebuild everything it serves?an open issue (NVIDIA/TensorRT-Edge-LLM #233, v0.11.0 on a Thor) reports the server building unneeded parts for about 30 minutes, then failingbuild first with llm_build, then point the server at the engine
CUDA 13.0 in the build flags, 13.2 on the Thora mismatch could fail the buildstep 1
Shared GPUexport and build are long GPU jobs on the Thor everyone’s chat runs onrun in a time window the owner sets, with the Nano unloaded

Sources