Fix ROCm backend (target MIGraphX EP) and add CUDA support
All checks were successful
Mirror to GitHub / mirror (push) Successful in 1s
release / build (push) Successful in 1m50s

ROCm silently fell back to CPU: the code targeted ONNX Runtime's classic
ROCMExecutionProvider, but distro ROCm-enabled ONNX Runtime builds (e.g.
Arch's onnxruntime-rocm) are commonly compiled with --use_migraphx instead,
and registration failures were invisible since breadmill never installed a
tracing subscriber. Switches the rocm feature to target MIGraphX, adds a
default tracing subscriber so EP registration success/failure is always
visible, and fixes a real crash where MIGraphX's output sequence padding
could index the attention mask out of bounds during mean-pooling.

Also adds a CUDA backend (--cuda / backend = "cuda") mirroring the same
ort execution-provider pattern, for NVIDIA hardware.

Version bump: 0.1.0 -> 0.2.0.
This commit is contained in:
Breadway 2026-07-03 21:58:39 +08:00
parent d3843f3131
commit 2618a33fd5
10 changed files with 227 additions and 96 deletions

171
Cargo.lock generated
View file

@ -25,7 +25,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures 0.2.17",
"cpufeatures",
]
[[package]]
@ -111,15 +111,6 @@ dependencies = [
"generic-array",
]
[[package]]
name = "block-buffer"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
dependencies = [
"hybrid-array",
]
[[package]]
name = "block-padding"
version = "0.3.3"
@ -142,7 +133,7 @@ dependencies = [
[[package]]
name = "breadmill"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"breadsearch-shared",
"hex",
@ -154,8 +145,9 @@ dependencies = [
"rusqlite",
"serde",
"serde_json",
"sha2 0.11.0",
"sha2",
"tokenizers",
"tracing-subscriber",
"ureq 2.12.1",
"usearch",
"zip",
@ -163,7 +155,7 @@ dependencies = [
[[package]]
name = "breadsearch"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"bread-theme",
"breadsearch-shared",
@ -174,7 +166,7 @@ dependencies = [
[[package]]
name = "breadsearch-shared"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"serde",
"serde_json",
@ -315,7 +307,7 @@ version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common 0.1.7",
"crypto-common",
"inout",
]
@ -383,12 +375,6 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "const-oid"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
[[package]]
name = "constant_time_eq"
version = "0.3.1"
@ -420,15 +406,6 @@ dependencies = [
"libc",
]
[[package]]
name = "cpufeatures"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
dependencies = [
"libc",
]
[[package]]
name = "crc"
version = "3.4.0"
@ -497,15 +474,6 @@ dependencies = [
"typenum",
]
[[package]]
name = "crypto-common"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
dependencies = [
"hybrid-array",
]
[[package]]
name = "cxx"
version = "1.0.194"
@ -688,22 +656,11 @@ version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer 0.10.4",
"crypto-common 0.1.7",
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
name = "digest"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
dependencies = [
"block-buffer 0.12.1",
"const-oid",
"crypto-common 0.2.2",
]
[[package]]
name = "dirs"
version = "5.0.1"
@ -779,7 +736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
@ -1350,7 +1307,7 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest 0.10.7",
"digest",
]
[[package]]
@ -1375,15 +1332,6 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "hybrid-array"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da"
dependencies = [
"typenum",
]
[[package]]
name = "icu_collections"
version = "2.2.0"
@ -1624,6 +1572,12 @@ dependencies = [
"libc",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.186"
@ -1708,7 +1662,7 @@ dependencies = [
"nom_locate",
"rand",
"rangemap",
"sha2 0.10.9",
"sha2",
"stringprep",
"thiserror 2.0.18",
"ttf-parser",
@ -1758,6 +1712,15 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30"
[[package]]
name = "matchers"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
dependencies = [
"regex-automata",
]
[[package]]
name = "matrixmultiply"
version = "0.3.10"
@ -1775,7 +1738,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
"cfg-if",
"digest 0.10.7",
"digest",
]
[[package]]
@ -1924,6 +1887,15 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "num-complex"
version = "0.4.6"
@ -2104,7 +2076,7 @@ version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest 0.10.7",
"digest",
"hmac",
]
@ -2416,7 +2388,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
@ -2587,8 +2559,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"digest 0.10.7",
"cpufeatures",
"digest",
]
[[package]]
@ -2598,19 +2570,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"digest 0.10.7",
"cpufeatures",
"digest",
]
[[package]]
name = "sha2"
version = "0.11.0"
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
"digest 0.11.3",
"lazy_static",
]
[[package]]
@ -2758,7 +2728,7 @@ dependencies = [
"getrandom 0.3.4",
"once_cell",
"rustix",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
@ -2810,6 +2780,15 @@ dependencies = [
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
]
[[package]]
name = "time"
version = "0.3.51"
@ -2997,6 +2976,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex-automata",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
@ -3167,6 +3176,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "vcpkg"
version = "0.2.15"

View file

@ -80,3 +80,7 @@ Start from `breadbox/breadbox/src/main.rs`. **Reuse verbatim:** the gtk4-layer-s
- nomic prefixes + mean-pool + normalize must match between index and query or recall collapses.
- `ort` linking: prefer the crate's downloaded/bundled ONNX Runtime to avoid version skew with Arch's `onnxruntime`.
- Office formats (docx/odt) are best-effort in v1; md/txt/org/pdf are the reliable path.
- GPU EPs (ROCm/CUDA) fail to register silently at the ONNX Runtime level and fall back to CPU — always check
startup logs for `Successfully registered` before trusting a GPU build is actually accelerating. See
[README: GPU backend notes](README.md#gpu-backend-notes) for the MIGraphX-vs-ROCMExecutionProvider distinction
and the per-shape JIT-compile-and-cache behavior that matters for interactive query latency.

View file

@ -22,13 +22,27 @@ Optional features:
| Feature | What it adds |
|---------|-------------|
| `npu` | AMD XDNA NPU via VitisAI ONNX Runtime EP (requires Ryzen AI SDK) |
| `rocm` | AMD iGPU via ROCm ONNX Runtime EP |
| `rocm` | AMD iGPU via the MIGraphX ONNX Runtime EP (ROCm-backed) |
| `cuda` | NVIDIA GPU via the CUDA ONNX Runtime EP |
```
# NPU build
cargo build --release -p breadmill --features npu
# ROCm (AMD iGPU/dGPU) build
cargo build --release -p breadmill --features rocm
# CUDA (NVIDIA GPU) build
cargo build --release -p breadmill --features cuda
```
`rocm`/`cuda`/`npu` all use `ort`'s `load-dynamic` mode: at runtime, breadmill
dlopens whatever `libonnxruntime.so` the dynamic linker resolves (or
`ORT_DYLIB_PATH` if set). GPU acceleration only works if that ONNX Runtime
build actually has the matching execution provider compiled in — breadmill
logs a clear `Successfully registered` / `not enabled in this build` line for
this at startup (see [GPU backend notes](#gpu-backend-notes) below).
## Setup
**1. Fetch the embedding model** (~550 MB, downloaded once from Hugging Face):
@ -89,6 +103,7 @@ breadmill status
# Backend flags (requires the matching Cargo feature)
breadmill --npu
breadmill --rocm
breadmill --cuda
```
## Config
@ -109,7 +124,7 @@ snippet_len = 200 # max characters in result snippet
[model]
name = "nomic-embed-text-v1.5"
dim = 768
backend = "cpu" # "cpu", "npu", or "rocm"
backend = "cpu" # "cpu", "npu", "rocm", or "cuda"
```
`roots` and `excludes` support `~/` expansion. The index respects `.gitignore` files found during the walk.
@ -124,6 +139,37 @@ Set `backend = "npu"` in config (or pass `--npu`) when running a build compiled
4. `/etc/vaip_config.json`
5. `/opt/xilinx/vaip_config.json`
### GPU backend notes
Both `rocm` and `cuda` need a system ONNX Runtime that was actually built with
the matching execution provider — the crate's own downloaded binary is CPU-only.
Point `ORT_DYLIB_PATH` at one, or install a distro package that provides
`libonnxruntime.so` with the EP baked in and let the dynamic linker find it.
**ROCm (`--rocm` / `backend = "rocm"`)** targets ONNX Runtime's **MIGraphX**
execution provider, not the classic `ROCMExecutionProvider`. Distro
ROCm-enabled ONNX Runtime packages (e.g. Arch's `onnxruntime-rocm`) are
commonly built with `--use_migraphx` rather than `--use_rocm`, so this is the
EP that's actually available in practice; the classic ROCm EP needs a bespoke
`--use_rocm` build most distros don't package. Startup logs a
`Successfully registered `MIGraphXExecutionProvider`` line when it's really
active — check for it if in doubt, since a failed GPU EP registration falls
back to CPU silently at the ONNX Runtime level (breadmill's own log line is
only a statement of intent, not a confirmation).
MIGraphX JIT-compiles the model per distinct input sequence length and caches
the compiled kernel to disk (each compile takes ~60120s and produces a
~500MB `.mxr` file). Set `ORT_MIGRAPHX_MODEL_CACHE_PATH=/path/to/cache` so
that cost is paid once per shape instead of on every daemon restart. Because
query text length varies, expect an occasional multi-second stall the first
time a new token length is seen — fine for background document indexing,
noticeable for interactive query embedding.
**CUDA (`--cuda` / `backend = "cuda"`)** targets the standard
`CUDAExecutionProvider` and needs a CUDA-enabled ONNX Runtime + a working
CUDA/cuDNN install. Unverified on real NVIDIA hardware in this repo — only
compile-checked, since development happened on an AMD-only machine.
## Runtime paths
| Purpose | Path |

View file

@ -1,13 +1,19 @@
[package]
name = "breadmill"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
license = "MIT"
[features]
default = []
npu = ["ort/vitis", "ort/load-dynamic"]
rocm = ["ort/rocm", "ort/load-dynamic"]
# "rocm" targets the MIGraphX execution provider, not ONNX Runtime's classic
# ROCMExecutionProvider (--use_rocm build). Distro ROCm-enabled ONNX Runtime
# packages (e.g. Arch's onnxruntime-rocm) are commonly built with --use_migraphx
# instead; the classic ROCm EP needs a bespoke --use_rocm build that ships
# libonnxruntime_providers_rocm.so, which most distros don't package.
rocm = ["ort/migraphx", "ort/load-dynamic"]
cuda = ["ort/cuda", "ort/load-dynamic"]
[[bin]]
name = "breadmill"
@ -26,6 +32,10 @@ breadsearch-shared = { path = "../breadsearch-shared" }
ort = { version = "2.0.0-rc.12", default-features = false, features = ["std", "tracing", "download-binaries", "tls-native", "copy-dylibs", "api-23"] }
tokenizers = "0"
# Surfaces ort's own EP-registration tracing (e.g. a GPU EP silently failing to
# register and falling back to CPU) as visible log output instead of nowhere.
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
# Vector index
usearch = "2"

View file

@ -19,8 +19,14 @@ pub enum Backend {
/// AMD XDNA NPU via the VitisAI ONNX Runtime execution provider.
/// `cache_dir` is used to store the compiled NPU model between runs.
Npu { cache_dir: PathBuf },
/// AMD iGPU via the ROCm ONNX Runtime execution provider.
/// AMD iGPU via the MIGraphX ONNX Runtime execution provider (ROCm-backed).
/// Distro ROCm ONNX Runtime builds (e.g. Arch's onnxruntime-rocm) are
/// commonly compiled with `--use_migraphx`, not `--use_rocm`, so this
/// targets `MIGraphXExecutionProvider` rather than the classic
/// `ROCMExecutionProvider`.
Rocm,
/// NVIDIA GPU via the CUDA ONNX Runtime execution provider.
Cuda,
}
pub struct OrtEmbedder {
@ -108,11 +114,14 @@ impl OrtEmbedder {
let actual_seq = shape[1] as usize;
let actual_dim = shape[2] as usize;
// Mean-pool over non-padding positions
// Mean-pool over non-padding positions. Some execution providers (e.g.
// MIGraphX) pad the output sequence dimension for kernel efficiency, so
// actual_seq can exceed mask.len() — only positions covered by our own
// attention mask are meaningful, so cap the loop at whichever is shorter.
let mut result = vec![0.0f32; actual_dim];
let mut count = 0usize;
for t in 0..actual_seq {
for t in 0..actual_seq.min(mask.len()) {
if mask[t] > 0 {
for d in 0..actual_dim {
result[d] += data[t * actual_dim + d];
@ -155,6 +164,7 @@ fn configure_eps(builder: SessionBuilder, backend: &Backend) -> Result<SessionBu
Backend::Cpu => Ok(builder),
Backend::Npu { cache_dir } => npu_session(builder, cache_dir),
Backend::Rocm => rocm_session(builder),
Backend::Cuda => cuda_session(builder),
}
}
@ -195,14 +205,19 @@ fn build_vitis_ep(cache_dir: &Path) -> Result<ort::ep::ExecutionProviderDispatch
.build())
}
// ---- ROCm EP (AMD iGPU) -----------------------------------------------------
// ---- MIGraphX EP (AMD iGPU, ROCm-backed) -------------------------------------
#[cfg(feature = "rocm")]
fn rocm_session(builder: SessionBuilder) -> Result<SessionBuilder, String> {
eprintln!("breadmill: using ROCm execution provider (device 0)");
eprintln!("breadmill: using MIGraphX execution provider (device 0)");
eprintln!(
"breadmill: note — check the log line above/below for \"Successfully registered \
`MIGraphXExecutionProvider`\"; if it's missing, the ONNX Runtime in use wasn't built \
with MIGraphX support and inference silently fell back to CPU"
);
builder
.with_execution_providers([
ort::execution_providers::ROCmExecutionProvider::default().build(),
ort::ep::MIGraphX::default().with_device_id(0).build(),
ort::ep::CPU::default().build(),
])
.map_err(|e| e.to_string())
@ -214,6 +229,30 @@ fn rocm_session(builder: SessionBuilder) -> Result<SessionBuilder, String> {
Ok(builder)
}
// ---- CUDA EP (NVIDIA GPU) ----------------------------------------------------
#[cfg(feature = "cuda")]
fn cuda_session(builder: SessionBuilder) -> Result<SessionBuilder, String> {
eprintln!("breadmill: using CUDA execution provider (device 0)");
eprintln!(
"breadmill: note — check the log line above/below for \"Successfully registered \
`CUDAExecutionProvider`\"; if it's missing, the ONNX Runtime in use wasn't built \
with CUDA support and inference silently fell back to CPU"
);
builder
.with_execution_providers([
ort::ep::CUDA::default().with_device_id(0).build(),
ort::ep::CPU::default().build(),
])
.map_err(|e| e.to_string())
}
#[cfg(not(feature = "cuda"))]
fn cuda_session(builder: SessionBuilder) -> Result<SessionBuilder, String> {
eprintln!("breadmill: CUDA backend requested but not compiled in (rebuild with --features cuda); using CPU");
Ok(builder)
}
/// Locate the VitisAI EP config file required by the AMD Ryzen AI SDK.
///
/// Search order:

View file

@ -24,17 +24,27 @@ const TOKENIZER_URL: &str =
"https://huggingface.co/nomic-ai/nomic-embed-text-v1.5/resolve/main/tokenizer.json";
fn main() {
// Surfaces ort's EP-registration warnings/errors (e.g. a GPU EP silently
// falling back to CPU) by default, without requiring RUST_LOG to be set.
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("warn,ort=info")),
)
.init();
let raw_args: Vec<String> = std::env::args().collect();
// Extract global flags before command dispatch.
let use_npu = raw_args.iter().any(|a| a == "--npu");
let use_rocm = raw_args.iter().any(|a| a == "--rocm");
let use_cuda = raw_args.iter().any(|a| a == "--cuda");
// Build a view of argv without backend flags for command matching.
let args: Vec<&str> = raw_args
.iter()
.skip(1)
.filter(|a| a.as_str() != "--npu" && a.as_str() != "--rocm")
.filter(|a| a.as_str() != "--npu" && a.as_str() != "--rocm" && a.as_str() != "--cuda")
.map(|s| s.as_str())
.collect();
@ -49,7 +59,7 @@ fn main() {
}
}
Some("--reindex") | Some("reindex") => {
if let Err(e) = run_daemon(true, use_npu, use_rocm) {
if let Err(e) = run_daemon(true, use_npu, use_rocm, use_cuda) {
eprintln!("breadmill: {}", e);
std::process::exit(1);
}
@ -66,7 +76,7 @@ fn main() {
cli_status();
}
None | Some("serve") | Some("--serve") => {
if let Err(e) = run_daemon(false, use_npu, use_rocm) {
if let Err(e) = run_daemon(false, use_npu, use_rocm, use_cuda) {
eprintln!("breadmill: {}", e);
std::process::exit(1);
}
@ -74,7 +84,7 @@ fn main() {
Some(cmd) => {
eprintln!("breadmill: unknown command: {}", cmd);
eprintln!(
"usage: breadmill [serve|reindex|fetch-model|query <text>|status] [--npu|--rocm] [--version]"
"usage: breadmill [serve|reindex|fetch-model|query <text>|status] [--npu|--rocm|--cuda] [--version]"
);
std::process::exit(1);
}
@ -83,7 +93,7 @@ fn main() {
// ---- Daemon -----------------------------------------------------------------
fn run_daemon(force_reindex: bool, use_npu: bool, use_rocm: bool) -> Result<(), String> {
fn run_daemon(force_reindex: bool, use_npu: bool, use_rocm: bool, use_cuda: bool) -> Result<(), String> {
let config = breadsearch_shared::Config::load();
let state_dir = breadsearch_shared::state_dir();
let cache_dir = breadsearch_shared::cache_dir();
@ -101,6 +111,9 @@ fn run_daemon(force_reindex: bool, use_npu: bool, use_rocm: bool) -> Result<(),
} else if use_rocm || config.model.backend == "rocm" {
eprintln!("breadmill: ROCm backend selected");
Backend::Rocm
} else if use_cuda || config.model.backend == "cuda" {
eprintln!("breadmill: CUDA backend selected");
Backend::Cuda
} else {
Backend::Cpu
};

View file

@ -1,6 +1,6 @@
[package]
name = "breadsearch-shared"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
license = "MIT"

View file

@ -129,7 +129,7 @@ pub struct ModelConfig {
pub name: String,
#[serde(default = "default_dim")]
pub dim: usize,
/// Compute backend: "cpu" or "npu" (VitisAI/XDNA).
/// Compute backend: "cpu", "npu" (VitisAI/XDNA), "rocm" (MIGraphX/AMD GPU), or "cuda" (NVIDIA GPU).
#[serde(default = "default_backend")]
pub backend: String,
}

View file

@ -1,6 +1,6 @@
[package]
name = "breadsearch"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
license = "MIT"

View file

@ -5,6 +5,10 @@ After=default.target
[Service]
Type=simple
# Uncomment if built with --features rocm: persists MIGraphX's compiled-kernel
# cache across restarts (each new sequence length otherwise costs a ~60-120s
# recompile). See README.md#gpu-backend-notes.
#Environment=ORT_MIGRAPHX_MODEL_CACHE_PATH=%h/.cache/breadsearch/migraphx-cache
ExecStart=%h/.cargo/bin/breadmill
Restart=on-failure
RestartSec=5