diff --git a/docs/install/linux.md b/docs/install/linux.md index 5f448f52..9c8e4024 100644 --- a/docs/install/linux.md +++ b/docs/install/linux.md @@ -190,26 +190,35 @@ Three ways to opt in, in order of preference: with an AMD GPU but no ROCm runtime it stays offered-but-unselected — install ROCm first (or continue on CPU). Choosing ROCm makes the bootstrap reinstall `torch`/`torchaudio` from the ROCm wheel index -(`https://download.pytorch.org/whl/rocm6.2` by default) right after the -dependency sync. +(`https://download.pytorch.org/whl/rocm6.4` by default) right after the +dependency sync — matched to the app's pinned `torch==2.8.0` (the rocm6.2 +index only ever published up to torch 2.5.1, so it silently failed the +reinstall and left the CPU-only CUDA build in place). **2. Environment variable (existing installs / headless).** Set `OMNIVOICE_TORCH_VARIANT=rocm` before launching — the next bootstrap performs the same ROCm reinstall. `OMNIVOICE_TORCH_INDEX=` overrides the wheel -index when you need a different ROCm version -([pytorch.org](https://pytorch.org/get-started/locally/) lists available -wheels). If the reinstall fails (network, unsupported card), OmniVoice keeps -the default torch build and warns instead of breaking the install. +index when you need a different ROCm version — e.g. AMD publishes newer +driver-matched builds (7.2.x) at `repo.radeon.com` as a `--find-links` page +rather than a PyPI-style index: +```bash +uv pip install --reinstall torch==2.8.0 torchaudio==2.8.0 \ + --find-links https://repo.radeon.com/rocm/manylinux/rocm-rel-7.2.4/ +``` +run that manually if you want a specific ROCm point release; the +`OMNIVOICE_TORCH_INDEX` env var only accepts a PEP 503 index URL, not a +find-links page. If the reinstall fails (network, unsupported card), OmniVoice +keeps the default torch build and warns instead of breaking the install. **3. Manual wheel swap (fallback).** Replace torch with the ROCm wheel **after** the first-run install populates the venv: ```bash # From the project directory (source install), into OmniVoice's uv venv. -# Current stable is ROCm 6.2 — match your installed ROCm/driver version -# (https://pytorch.org/get-started/locally/ lists available wheels). +# Matches the app's torch==2.8.0 pin — a different ROCm point release +# (e.g. rocm6.2, rocm7.x) may not carry that exact torch build. uv pip install --reinstall torch torchaudio \ - --index-url https://download.pytorch.org/whl/rocm6.2 + --index-url https://download.pytorch.org/whl/rocm6.4 ``` Once a ROCm build of PyTorch is in the venv, detection is automatic — diff --git a/frontend/src-tauri/src/bootstrap.rs b/frontend/src-tauri/src/bootstrap.rs index b59cd6ba..e484854a 100644 --- a/frontend/src-tauri/src/bootstrap.rs +++ b/frontend/src-tauri/src/bootstrap.rs @@ -704,9 +704,14 @@ fn sync_failure_is_torch_download(tail: &str) -> bool { || (low.contains("torch") && (low.contains("failed to download") || low.contains("failed to fetch"))) } -/// Default PyTorch ROCm wheel index for the opt-in AMD path (#124). ROCm 6.2 is -/// the current stable wheel set; overridable via OMNIVOICE_TORCH_INDEX. -const ROCM_TORCH_INDEX: &str = "https://download.pytorch.org/whl/rocm6.2"; +/// Default PyTorch ROCm wheel index for the opt-in AMD path (#124). +/// ROCm 6.4, not 6.2: the app's pinned `torch==2.8.0` (pyproject.toml) has no +/// build on the rocm6.2 index (it tops out at 2.5.1), so that index silently +/// failed the reinstall and left the default CUDA build in place — which runs +/// on CPU on an AMD GPU (#972). rocm6.4 carries a matching 2.8.0 build. +/// Overridable via OMNIVOICE_TORCH_INDEX (e.g. a `--find-links` URL for +/// distro-matched ROCm builds torch's own index doesn't carry). +const ROCM_TORCH_INDEX: &str = "https://download.pytorch.org/whl/rocm6.4"; /// `uv pip install` args that replace the default CUDA torch build with the AMD /// ROCm wheel (#124). Opt-in (gated on OMNIVOICE_TORCH_VARIANT=rocm by the @@ -1817,7 +1822,10 @@ mod tests { assert!(args.iter().any(|a| a == "torch")); assert!(args.iter().any(|a| a == "torchaudio")); let i = args.iter().position(|a| a == "--index-url").expect("has --index-url"); - assert!(args[i + 1].contains("rocm6.2"), "default index is the rocm6.2 wheel set"); + // rocm6.4, not rocm6.2: rocm6.2's index tops out at torch 2.5.1 and + // can't satisfy the app's torch==2.8.0 pin (#972) — a regression to + // rocm6.2 here would silently resurrect the CPU-fallback bug. + assert!(args[i + 1].contains("rocm6.4"), "default index is the rocm6.4 wheel set (matches torch==2.8.0)"); } #[test]