Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
build
build_*/
.worktrees/
.vscode
__pycache__
_site
Expand Down
93 changes: 47 additions & 46 deletions docs/rai-setup-linux.md → docs/core-setup-linux.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Building the `--rai` backend on Linux from scratch
# Building the `--core` backend on Linux from scratch

How to get from a bare checkout to `flm run phi4-mini-it-rai` on a machine with
an AMD NPU. The `--rai` backend reaches kernels through **ryzenai-corelib**
How to get from a bare checkout to `flm run phi4-mini-it-core` on a machine with
an AMD NPU. The `--core` backend reaches kernels through **ryzenai-corelib**
instead of FastFlowLM's own kernel flow, and corelib lives outside this
repository, so most of the work is standing up that prefix.

Written against the working install on this machine. Paths use `$P` for the
dependency prefix (here `/home/alfxu/ddprefix`); substitute your own.

> **Status:** at corelib 0.11.0 the rai backend has been run on hardware on
> Windows only. The Linux build configures and links against this layout, but
> it has not been run end to end on Linux at this revision. The
> [Known issues](#known-issues) are from an earlier Linux bring-up.
> **Status:** the core backend has been run on hardware on Windows only. The
> steps below are updated for corelib 0.33.1, but they have not been run end
> to end on Linux at this revision. The [Known issues](#known-issues) are from
> an earlier Linux bring-up.

---

Expand All @@ -29,48 +29,44 @@ step 4 and installing XRT itself.

---

## 1. Dependency prefix: DynamicDispatch, then corelib
## 1. Dependency prefix: corelib

This is the hard part and it is already written up in **`$P/BUILD-NOTES.md`** —
read that first. It records the two things that actually matter (the required
DD branch, and `BUILD_SHARED_LIBS=ON` for DD), the sudo-free dependency prefix,
the non-PIC link traps, and the exact `cmake` command lines for both projects.

Do not re-derive it. The short version:
corelib no longer links DynamicDispatch, so there is no DD prefix to
build first. **`$P/BUILD-NOTES.md`** still records the sudo-free dependency
prefix and the non-PIC link traps; its DynamicDispatch steps no longer apply.

```bash
P=/home/alfxu/ddprefix # your dependency prefix

# DynamicDispatch -> $P/install-dds (see BUILD-NOTES.md for the full line)
cmake -S DynamicDispatch -B build-dds ... -DCMAKE_INSTALL_PREFIX=$P/install-dds
cmake --build build-dds -j"$(nproc)" --target install

# ryzenai-corelib -> $P/install-corelib
cmake -S ryzenai-corelib -B build-corelib -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$P/install-corelib \
-DRYZENAI_CORELIB_STAGE_RUNTIME_DLLS=OFF \
-DCMAKE_PREFIX_PATH="$P/install-dds;$P/shim;$P/root/usr;$P/root/usr/lib/x86_64-linux-gnu;/opt/xilinx/xrt"
cmake --build build-corelib -j"$(nproc)"
-DCMAKE_PREFIX_PATH="$P/shim;$P/root/usr;$P/root/usr/lib/x86_64-linux-gnu;/opt/xilinx/xrt"
cmake --build build-corelib -j"$(nproc)" --target install
```

**Version must match exactly.** `src/include/rai/corelib_api.hpp` has a
`#error` for anything other than corelib **0.11.0**:
The default build installs `libryzenai_corelib.so` and one
`libryzenai_corelib_model_<name>.so` per model, each carrying that model's
kernels. corelib loads a model library only from the directory it was itself
loaded from, so those libraries must sit beside it; nothing else is needed at
run time, no kernel store and no environment variable.

**Version must match exactly.** `src/include/core/corelib_api.hpp` has a
`#error` for anything other than corelib **0.33.1**:

```bash
grep -E 'CORELIB_VERSION_(MAJOR|MINOR|PATCH)' \
$P/install-corelib/include/ryzenai/corelib.h
```

Must print `0`, `11`, `0`. (`BUILD-NOTES.md` still says 0.4.0 in its opening
line — that text is stale; the installed headers are 0.11.0.) The headers must
also be from after the weight API became one `*_weights_create` per operator;
an older 0.11.0 checkout fails the FastFlowLM build on those symbols.
Must print `0`, `33`, `1`. (`BUILD-NOTES.md` still says 0.4.0 in its opening
line — that text is stale.)

### Verify corelib before going further

```bash
source /opt/xilinx/xrt/setup.sh
export LD_LIBRARY_PATH=$P/install-dds/lib:$P/install-corelib/lib:/opt/xilinx/xrt/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$P/install-corelib/lib:/opt/xilinx/xrt/lib:$LD_LIBRARY_PATH
$P/build-corelib/tests/ryzenai_corelib_tests
```

Expand All @@ -82,30 +78,31 @@ device setup and the build are sound; it does not exercise repeated dispatch.

---

## 2. Build FastFlowLM with `--rai`
## 2. Build FastFlowLM with `--core`

The installer does configure, build and relocate in one step:

```bash
cd /home/alfxu/FastFlowLM/src
RYZENAI_CORELIB_ROOT=$P/install-corelib ./home_install.sh --rai
RYZENAI_CORELIB_ROOT=$P/install-corelib ./home_install.sh --core
```

`RYZENAI_CORELIB_ROOT` is needed **once** — CMake caches it. If you ever delete
`src/build/`, you must pass it again, because the cache goes with it.

What the flags do:

- `--rai` selects the `linux-rai-on` preset (`-DFLM_ENABLE_RAI=ON`) and installs
to `/scratch/$USER/flm_exe_rai` rather than `~/flm_exe`. A rai prefix stages
corelib and DynamicDispatch, which are far too large for a home directory, and
a rai build and a stock one would otherwise overwrite each other.
- `--core` selects the `linux-core-on` preset (`-DFLM_ENABLE_CORE=ON`) and installs
to `/scratch/$USER/flm_exe_core` rather than `~/flm_exe`. A core prefix stages
corelib and every `libryzenai_corelib_model_*.so` beside it, whose model
kernels are far too large for a home directory, and a core build and a stock
one would otherwise overwrite each other.
- `FLM_PREFIX=/path` overrides the install location.
- `--no-build` installs an existing `build/` tree without rebuilding.

### How the corelib lookup resolves

The `FLM_ENABLE_RAI` block of `src/CMakeLists.txt`, in order:
The `FLM_ENABLE_CORE` block of `src/CMakeLists.txt`, in order:

| | Headers (`ryzenai/corelib.h`) | Library (`libryzenai_corelib`) |
|---|---|---|
Expand All @@ -121,17 +118,18 @@ from the corelib *build tree*, not a stripped or patched copy:

```bash
objdump -p src/lib/libryzenai_corelib.so | grep RUNPATH
# -> /home/alfxu/ddprefix/install-dds/lib:/opt/xilinx/xrt/lib:
# -> should name /opt/xilinx/xrt/lib
```

Without that RUNPATH it will not find DynamicDispatch at run time.
Without that RUNPATH it will not find XRT at run time. Copy every
`libryzenai_corelib_model_*.so` into `src/lib/` beside it too.

### Rebuilding after a source change

```bash
cd /home/alfxu/FastFlowLM/src
cmake --build build -j"$(nproc)"
cp build/flm /scratch/$USER/flm_exe_rai/flm
cp build/flm /scratch/$USER/flm_exe_core/flm
```

Faster than re-running the installer, and it skips the XRT-shadowing problem in
Expand All @@ -146,11 +144,11 @@ it shadows the real XRT and breaks the NPU with confusing errors. Delete it
after **every** installer run:

```bash
rm -f /scratch/$USER/flm_exe_rai/lib/libxrt_coreutil.so.2
rm -f /scratch/$USER/flm_exe_core/lib/libxrt_coreutil.so.2
```

This is a known bug in the installer's `ldd` staging walk
(`home_install.sh:251-261`), not yet fixed. A rai prefix deliberately bundles no
(`home_install.sh:247-256`), not yet fixed. A core prefix deliberately bundles no
XRT — `flm_env.sh` pins `XILINX_XRT` to the real root instead — so the staged
copy is wrong by construction.

Expand Down Expand Up @@ -184,18 +182,18 @@ log out and back in, and `tmux kill-server` if you use tmux.

```bash
source /opt/xilinx/xrt/setup.sh
source /scratch/$USER/flm_exe_rai/flm_env.sh
/scratch/$USER/flm_exe_rai/flm pull phi4-mini-it-rai:4b
/scratch/$USER/flm_exe_rai/flm run phi4-mini-it-rai:4b -c 4096
source /scratch/$USER/flm_exe_core/flm_env.sh
/scratch/$USER/flm_exe_core/flm pull phi4-mini-it-core:4b
/scratch/$USER/flm_exe_core/flm run phi4-mini-it-core:4b -c 4096
```

`flm_env.sh` sets `FLM_CONFIG_PATH`, `FLM_XCLBIN_PATH`, `FLM_MODEL_PATH`
(`/scratch/alfxu`) and pins `XILINX_XRT`. It does **not** set `ulimit` — step 4
is on you.

Models live under `$FLM_MODEL_PATH/models/<name>`. The shipped
`model_list.json` already carries the `-rai` tags (`phi4-mini-it-rai:4b`,
`qwen3-rai:*`, `gemma4-it-rai:*`, `qwen3.5-rai:*`), so `flm pull` fetches them
`model_list.json` already carries the `-core` tags (`phi4-mini-it-core:4b`,
`qwen3-core:*`, `gemma4-it-core:*`, `qwen3.5-core:*`), so `flm pull` fetches them
like any other model.

---
Expand Down Expand Up @@ -235,10 +233,13 @@ shape is a dead end.

| Variable | Effect |
|---|---|
| `RYZENAI_CORELIB_TRACE_XRT` | trace XRT calls |
| `RYZENAI_CORELIB_TRACE=xrt` | trace XRT calls (`kernels,xrt` for both logs, `all` for every category) |
| `RYZENAI_CORELIB_SAFE_MODE` | force staging buffers, no host-pointer import |
| `RYZENAI_CORELIB_NO_RUN_POOL` | disable run-object reuse |
| `RYZENAI_CORELIB_NO_CRASH_HANDLER` | leave crashes to the debugger |
| `RYZENAI_CORELIB_REPORT_FALLBACKS=1` | when a stream is released, report host (CPU fallback) time per artifact, and every dispatch that ran on a later PDI than its first choice; no output means nothing fell back |
| `RYZENAI_CORELIB_MAX_RUNS_IN_FLIGHT` | how many runs of one kernel a stream lets run ahead (64 unset, `0` for no cap) |
| `RYZENAI_CORELIB_KERNELS_ROOT` | a kernel store to load from, for corelib development only; every model library already carries its kernels, so a normal run sets nothing |

### Other rough edges

Expand Down
8 changes: 4 additions & 4 deletions docs/docs/benchmarks/phi4_results.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,19 @@ AMD Ryzen™ AI 7 350 (Kraken Point) with 32 GB DRAM; performance is comparable

---

## 🧪 Phi-4-mini-instruct Q8_0 GGUF on the rai backend (`phi4-mini-it-rai:4b`, `aie_next`)
## 🧪 Phi-4-mini-instruct Q8_0 GGUF on the core backend (`phi4-mini-it-core:4b`, `dev04`)

These are **descriptive measurements from individual runs**, not a benchmark sweep and not a pass threshold. Each figure below comes from one run, not from an average over many. They are not comparable to the tables above, which sweep 1k–32k on NPU2.

### Provenance

| | |
|---|---|
| Machine | aie_next development machine |
| Machine | dev04 development machine |
| OS | Microsoft Windows 11 Enterprise 10.0.26100 |
| FastFlowLM commit | `16943bc4` |
| corelib commit / version | `a8c6e8d` / `0.11.0`, built from source, loaded from beside `flm.exe` |
| Run | 2026-10-01, `flm serve phi4-mini-it-rai:4b --ctx-len 4096`, `/api/generate` with `max_tokens: 8` |
| Run | 2026-10-01, `flm serve phi4-mini-it-core:4b --ctx-len 4096`, `/api/generate` with `max_tokens: 8` |

### Measurements

Expand All @@ -72,7 +72,7 @@ One server, four prompts in increasing length, each a fresh conversation. The

Model load was 1.0–1.2 s (`Model loaded in`, as reported by FLM). Every reply
was a coherent continuation of the prompt, and the server log reports
`Backend: rai (from model catalog)`.
`Backend: core (from model catalog)`.

Not measured at this version: cold and warm TTFT in isolation, and the
cancellation and capacity-boundary checks.
8 changes: 4 additions & 4 deletions docs/docs/instructions/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,15 @@ flm serve llama3.2:1b --ctx-len 8192
| id | kernels | ships on |
|---|---|---|
| `flm` | FastFlowLM's own NPU kernels | Strix / Krackan Point |
| `rai` | AMD's ryzenai-corelib | the next NPU generation |
| `core` | AMD's ryzenai-corelib | the next NPU generation |

You normally never set this. The model tag already names the flow — a family ending in `-rai` wants corelib's kernels, everything else FastFlowLM's — and `flm list` only ever offers you tags this build and this machine can actually run. `flm run` separately prints the silicon as `NPU platform: aie_next`. A model family has at most one engine per backend, so there is nothing to choose between.
You normally never set this. The model tag already names the flow — a family ending in `-core` wants corelib's kernels, everything else FastFlowLM's — and `flm list` only ever offers you tags this build and this machine can actually run. `flm run` separately prints the silicon as `NPU platform: dev04`. A model family has at most one engine per backend, so there is nothing to choose between.

The flag exists for overriding what the tag says, and for the targets that will join this list later:

```shell
flm run phi4-mini-it:4b --backend flm
flm serve phi4-mini-it-rai:4b --backend rai
flm serve phi4-mini-it-core:4b --backend core
```

**Precedence**, highest first:
Expand All @@ -256,7 +256,7 @@ flm serve phi4-mini-it-rai:4b --backend rai
|---|---|---|
| 1 | `--backend <id>` | the flag above, or a `"backend"` field on a `/v1/chat/completions` or `/v1/completions` request |
| 2 | `FLM_BACKEND=<id>` | environment variable, for a whole shell session |
| 3 | the model's catalog entry | `rai` for a tag whose family ends in `-rai`, `flm` otherwise |
| 3 | the model's catalog entry | `core` for a tag whose family ends in `-core`, `flm` otherwise |

A per-request `"backend"` overrides `--backend` for that request, and reloads the model if it differs from the one already loaded — exactly as asking for a different model does.

Expand Down
Loading
Loading