M300A a écrit :
De tête déjà, t'as passé iommu=pt ?
Édit: pas sûr que ça soit nécessaire si t'es directement sur le host mais ça coûte rien d'essayer
|
Ca a reussi avec le guide suivant:
# Enable PCIe P2P on pc3090 (dual 3090-class, vLLM TP=2)
## Context
Both GPUs run without peer access — `nvidia-smi topo -p2p rwnap` reports `GNS`, the stock
driver's software block on GeForce cards. Every tensor-parallel all-reduce in the vLLM TP=2
path is therefore staged through host memory instead of crossing PCIe directly.
The estate's own cross-rig data (`/opt/ai/club-3090/docs/PCIE_P2P.md` §6) puts the win for
exactly this configuration — dual 3090, TP=2, vLLM — at **prefill +12–14%, TTFT −13–15%,
decode +7–12%**, with the spec-decode path (this slug runs the DFlash2 drafter) at +19–22%
in #95. On a 90K prefill currently taking ~70 s that is roughly 8 s per long prompt. §6 is
equally clear this buys nothing on llama.cpp/GGUF — the case rests entirely on the vLLM TP path.
**This was attempted on 2026-08-13 and abandoned within an hour.** Timestamps reconstruct it:
baseline bench 09:47, modules built 10:06, `bench-p2p.txt` created **empty** at 10:27, revert
confirmed 10:44. An empty bench file means the harness got nothing — the server never came up.
Had the stock module silently kept loading, the bench would have produced a full,
baseline-identical file instead. So the likely failure was the §8 *hollow grant*: the patched
module loaded, granted P2P, `detect_nvlink.sh` auto-enabled the P2P path, and NCCL hung at
`pynccl` init — **with the IOMMU translating**, which §8 lists as the first cause to check.
The IOMMU is still translating: `amd_iommu=on` is rejected by this kernel
(`AMD-Vi: Unknown option - 'on'`), leaving `Default domain type: Translated`. That one-line fix
is the most likely reason this attempt succeeds where August did not.
**The version situation forces a decision, and it is urgent on its own terms.** The installed
610.43.02 has been superseded: its .deb is **gone from the pool** (verified — `apt-get download`
404s), while `610.57.04-0ubuntu0.26.04.3` is live in both `resolute-updates` and
`resolute-security` and fetchable today. `50unattended-upgrades` allows
`${distro_codename}-security`, nothing is held, and the local apt index is 11 days stale — so
the driver **will** upgrade itself once the index refreshes. A kernel bump is queued too
(`linux-image-generic` 7.0.0-31.31 vs 7.0.0-30.30 installed). Building a custom module against
a version that no longer exists, on a box poised to upgrade underneath it, is the wrong
foundation. So this plan takes both upgrades deliberately, first.
**Intended outcome:** P2P engaged and *proven* to carry correct data, vLLM serving on it with a
measured same-sitting A/B, a driver that survives kernel upgrades by itself, and a rollback that
does not depend on the network.
## Target state
| | from | to |
|---|---|---|
| kernel | 7.0.0-30-generic | 7.0.0-31-generic |
| driver | 610.43.02 (deb gone from pool) | 610.57.04-0ubuntu0.26.04.3 |
| kernel module | stock `nvidia-dkms-610-open` | `nvidia/610.57.04-p2p` via DKMS, from fork branch `610.57.04-p2p-v3` |
| IOMMU | translating | `iommu=pt` |
| `NVLINK_MODE` | unset (→ `auto`) | `pcie_p2p` |
**3 reboots.** Each phase changes one variable; serving stays pinned to the pre-patch path
until Phase 6, so the driver swap is proven before anything serving depends on it.
## Execution status (updated 2026-09-14 22:40)
| phase | state |
|---|---|
| 1 IOMMU passthrough | ✅ `iommu=pt`, `Default domain type: Passthrough`, no `Unknown option` |
| 2 kernel + driver upgrade | ✅ `7.0.0-31-generic` / `610.57.04`, stock DKMS rebuilt for -29/-30/-31, all four holds applied |
| 3 rollback re-prime | ✅ 610.57.04 debs + `-31` module tarball + 610.57.04 source cached; 610.43.02 artifacts retained |
| 3 baseline | ⚠️ **partial** — see below |
| 4 build `610.57.04-p2p-v3` | ✅ passed, see below |
| 5–8 | not started |
**Baselines captured (stock 610.57.04, P2P off):**
- `p2p-validate.sh` → **exit 0, HEALTHY**, both arms correct
- bandwidth → **peer 5.76 GB/s vs host-staged 6.65 GB/s (0.87×)**, "no peer advantage" — 6.65 GB/s
is the number P2P must beat
- `p2p-check.sh` → correctness PASS, 5.8 GB/s
**Still outstanding in Phase 3** — both ran before the server finished booting and must be redone
against the live endpoint (`localhost:8104`, *not* 8010 — 8010 was the old qwen3.6 container):
- `verify-full.sh` → 8 checks failed on an unreachable server
- `bench.sh` → output file is 242 bytes of "service not reachable"; it would poison the Phase 8
A/B if left in place
**Gate 4 result — passed clean:**
- all five modules `version 610.57.04` (= running driver), `vermagic 7.0.0-31-generic` (= running
kernel); licenses `Dual MIT/GPL`, `nvidia-peermem` `Dual BSD/GPL` (matches stock)
- build log 15749 lines, **0 errors**, no modpost failures, no undefined symbols
- patch confirmed in the worktree: 31 files / 1185 insertions vs upstream `e4a5faa2`, core commit
`94b69ebc`, `ENABLE_RESIZABLE_BAR` default = 1. Much larger than the 610.43.02 patch (8 files /
83 insertions) — it touches `p2p_caps.c`, `kern_bus_*` across maxwell/pascal/turing,
`nv_gpu_ops.c`, `mem_desc.c`, `io_vaspace.c`
- `patch-libcuda-p2p.py` is a **separate userspace step, not needed here** — mixed-generation only,
and this pair is both GA102
- the branch also carries an auto-enabled experimental hugepage `cudaHostRegister` fast path;
**dormant on this rig** (HugePages_Total 0, no hugetlbfs bind). It would go live if
`scripts/hugepages.sh` were ever used — remember this if odd behaviour appears later
## Preconditions — verified, no action needed
| item | state |
|---|---|
| Resizable BAR / Above 4G | **on** — BAR1 32768 MiB per card, ≥ VRAM (the v3 README's hard prerequisite) |
| Topology | GPU0 `01:00.0` on root port `00:01.1`, GPU1 `03:00.0` on `00:01.3`, both Gen4 x8, `PHB` |
| GPU pair | both GA102 — **same generation**, so per the v3 README no `libcuda` patch is needed |
| NVLink | not possible — the 3090 Ti has no NVLink fingers. BAR1 path only |
| Secure Boot | disabled — no module signing |
| initramfs | contains **no** nvidia modules — no `update-initramfs` step |
| Recovery | headless, no display manager, sshd active — a driver that fails to load cannot lock you out |
## Locked decisions
1. **Upgrade kernel + driver first**, deliberately, then patch `610.57.04-p2p-v3`.
2. **Install via DKMS** as `nvidia/610.57.04-p2p` — auto-rebuilds on kernel upgrades and lands
in `updates/dkms`, where depmod's `search updates ubuntu built-in` order makes it win.
3. **Ship the default custom all-reduce config** (`NVLINK_MODE=pcie_p2p`), gated hard on
`verify-full.sh`.
4. **Full same-sitting A/B**, baselined on the *final* stock stack.
## Prep required before starting (the cached artifacts are version-pinned)
These were written for 610.43.02 and must be re-pointed at 610.57.04 — a mechanical edit:
- `~/p2p-run/dkms.conf` — `PACKAGE_VERSION`
- `~/p2p-run/install-dkms.sh` — `STOCK_VER`, `P2P_VER`, `DST`
- `~/p2p-run/rollback.sh` — `STOCK_VER`, `P2P_VER`
- `~/p2p-run/rollback-cache/` — re-primed in Phase 3 against the new stack. Keep the existing
610.43.02 tarballs as a deeper fallback; they are the only copy of that version left.
## Files this plan modifies
- `/etc/default/grub` — `amd_iommu=on` → `iommu=pt` (line 10, leaves `iomem=relaxed` intact)
- `/opt/ai/club-3090/.env` — add `NVLINK_MODE`, `force_off` then `pcie_p2p`
- `/usr/src/nvidia-610.57.04-p2p/` — new, staged by `install-dkms.sh`
- DKMS registry — stock `nvidia/610.57.04` removed, `nvidia/610.57.04-p2p` added
- apt holds on the nvidia packages, applied **after** the upgrade
No source files are edited; the patch lives in the fork branch.
## Existing tooling to reuse — do not reinvent
| tool | use |
|---|---|
| `/opt/ai/club-3090/scripts/p2p-validate.sh` | real NCCL all-reduce, checks **values**; exit 0/2/3/4/5 |
| `/opt/ai/club-3090/scripts/report.sh` | "Interconnect verdict" + "Transfer check" for the running container |
| `/opt/ai/club-3090/scripts/verify-full.sh` | ~2 min functional; step 8 degeneracy/cascade, step 9 MTP acceptance |
| `/opt/ai/club-3090/scripts/verify-stress.sh` | 10–20 min long-ctx needle ladder |
| `/opt/ai/club-3090/scripts/bench.sh` | the A/B harness behind the existing bench files |
| `/opt/ai/club-3090/scripts/launch.sh --variant vllm/qwen38-27b-dual-superfast` | boots the running slug (`dflash2-fp8.yml`) |
| `/opt/ai/club-3090/scripts/detect_nvlink.sh` | already handles patched-driver PCIe P2P in `auto`; `pcie_p2p` forces it |
| `~/p2p-check.sh` | byte-verified peer copy + GB/s, via the vLLM image's torch |
---
## Phase 1 — IOMMU passthrough (reboot #1)
Done **first**, on the current known-good 610.43.02 stack, so a passthrough problem is found
against a system whose behaviour you already know. Passthrough removes IOMMU DMA isolation for
all devices — fine on this trusted single-user box, not if VFIO guests ever get passthrough.
```bash
sudo sed -i 's/amd_iommu=on/iommu=pt/' /etc/default/grub
grep GRUB_CMDLINE_LINUX_DEFAULT /etc/default/grub # eyeball before committing
sudo update-grub && sudo reboot
```
**GATE 1** — `/proc/cmdline` has `iommu=pt` · kernel logs `Default domain type: Passthrough` ·
no `Unknown option` line · both GPUs, NVMe and both NICs present · `topo -p2p` **still `GNS`**
(expected) · vLLM serves.
**Fail →** revert the sed, `update-grub`, reboot, and stop: without passthrough the patched
module reproduces August.
## Phase 2 — Deliberate kernel + driver upgrade (reboot #2)
Takes the upgrade that is coming anyway, at a moment you choose. 16 packages move together
(the whole userspace: `libnvidia-compute-610`, `-gl`, `-encode`, `-decode`, `nvidia-utils-610`,
firmware, …) plus the kernel to 7.0.0-31.
```bash
sudo apt update
apt list --upgradable | grep -E "nvidia|linux-image|linux-headers" # read before committing
sudo apt install --only-upgrade $(dpkg -l | awk '/610\.43\.02/ {print $2}' | tr '\n' ' ')
sudo apt install linux-generic # pulls -31 image + headers
sudo reboot
```
**GATE 2** — `nvidia-smi` reports **610.57.04** · `uname -r` is `7.0.0-31-generic` ·
`dkms status` shows stock `nvidia/610.57.04` built for the new kernel · `iommu=pt` survived ·
vLLM serves and `verify-full.sh` passes on the stock stack.
Then freeze it:
```bash
sudo apt-mark hold nvidia-dkms-610-open nvidia-driver-610-open \
nvidia-kernel-source-610-open nvidia-kernel-common-610
```
**Fail →** the previous kernel is still in the GRUB menu; boot it. The 610.43.02 rollback
tarballs in `~/p2p-run/rollback-cache/` are the only copy of that driver left.
## Phase 3 — Re-prime rollback, then baseline on the final stock stack
Rollback assets must describe the stack you are actually leaving. Unlike 610.43.02, this
version's .deb **is** downloadable — so cache the real packages, not just tarballs.
```bash
cd ~/p2p-run/rollback-cache
apt-get download nvidia-dkms-610-open nvidia-kernel-source-610-open nvidia-kernel-common-610
tar -czf stock-modules-$(uname -r).tar.gz \
-C /var/lib/dkms/nvidia/610.57.04/$(uname -r)/x86_64 module
tar -czf stock-nvidia-610.57.04-src.tar.gz -C /usr/src nvidia-610.57.04
```
Then the seatbelt and the baseline. `detect_nvlink.sh` `auto` flips on one signal —
`topo -p2p r` reporting `OK` — and inspects neither IOMMU, ACS, BAR1, nor whether the grant
carries bytes. Pinning `force_off` decouples "the driver changed" from "serving changed",
which is exactly what went wrong in August.
```bash
echo "NVLINK_MODE=force_off" >> /opt/ai/club-3090/.env
[ -z "${NVLINK_MODE+x}" ] || echo "WARNING: NVLINK_MODE exported in shell — it WINS over .env (#425)"
cd ~/p2p-run
bash ~/p2p-run/rollback.sh status | tee state.before.txt
nvidia-smi topo -p2p rwnap > topo-p2p.before.txt
nvidia-smi --query-gpu=index,name,power.limit --format=csv > gpu-tune.before.txt
docker stop vllm-qwen38-27b-dual-superfast
bash ~/p2p-check.sh 2>&1 | tee bw.before.txt
bash /opt/ai/club-3090/scripts/p2p-validate.sh 2>&1 | tee validate.before.txt; echo "exit=$?"
docker start vllm-qwen38-27b-dual-superfast # wait for ready
bash /opt/ai/club-3090/scripts/verify-full.sh 2>&1 | tee verify.before.txt
bash /opt/ai/club-3090/scripts/bench.sh 2>&1 | tee ~/bench-nop2p-610.57.04-$(date +%F).txt
```
**GATE 3** — debs downloaded and new tarballs written · `.env` has `force_off` and
`NVLINK_MODE` is not exported in the shell · `GNS` confirmed · bandwidth recorded (expect
~4–6 GB/s) · `p2p-validate.sh` exit **0** on stock · `verify-full` passes **including step 9
MTP ≥ 2.0** (the pre-patch reading that makes the post-patch one meaningful) · fresh bench
captured on 610.57.04.
## Phase 4 — Build the patched modules (nothing installed)
The clone has ~1498 root-owned objects from August and is on the old branch; clean before
switching or the checkout fights you.
```bash
cd ~/open-gpu-kernel-modules
sudo make clean && sudo chown -R leo3090:leo3090 .
git fetch origin && git checkout 610.57.04-p2p-v3 && git status -sb
grep -n "ENABLE_RESIZABLE_BAR, 1" kernel-open/nvidia/nv-reg.h # confirm the patch is present
make modules -j16 2>&1 | tee ~/p2p-run/build.log
```
**GATE 4** — all five modules present with `version: 610.57.04`, `vermagic: 7.0.0-31-generic`,
`license: Dual MIT/GPL`, no modpost errors. A version mismatch here is the §8 "match the patch
branch to your exact driver version" row — the single most common cause of a hollow grant.
A dry run of what DKMS does in Phase 5; failure here is free.
## Phase 5 — Install via DKMS (reboot #3)
```bash
docker stop vllm-qwen38-27b-dual-superfast
sudo systemctl stop nvidia-persistenced # it holds the driver open
sudo bash ~/p2p-run/install-dkms.sh # after the version bump noted in Prep
```
The script stages a clean copy to `/usr/src/nvidia-610.57.04-p2p`, runs `dkms add` and
`dkms build`, **verifies the built artifacts, and only then** removes stock and installs — so a
build failure leaves the running system fully intact.
**GATE 5 (pre-reboot, the script prints it)** — every `modinfo -n` under `updates/dkms/` ·
`version 610.57.04`, `vermagic 7.0.0-31-generic` · `dkms status` shows `nvidia/610.57.04-p2p`
installed and **no** stock `nvidia/610.57.04`.
**Fail →** Route B in the same sitting:
`sudo dkms remove -m nvidia -v 610.57.04 --all && cd ~/open-gpu-kernel-modules && sudo make modules_install && sudo depmod -a`,
accepting that kernel upgrades then need Phases 4–5 rerun by hand.
**PASS →** `sudo reboot`
## Phase 6 — Prove the grant carries bytes (serving still pinned off)
Walk the §7a correctness ladder before anything serving depends on it.
```bash
nvidia-smi topo -p2p rwnap | tee ~/p2p-run/topo-p2p.after.txt
journalctl -k -b | grep -iE "NVRM|Xid"
bash ~/p2p-check.sh 2>&1 | tee ~/p2p-run/bw.after.txt
bash /opt/ai/club-3090/scripts/p2p-validate.sh 2>&1 | tee ~/p2p-run/validate.after.txt; echo "exit=$?"
```
**GATE 6** — `OK` not `GNS` · no Xid · BAR1 still 32768 MiB · peer copy **correctness PASS**
with bandwidth clearly above Phase 3 (expect ~8–13 GB/s) · **`p2p-validate.sh` exit 0**.
| exit | action |
|---|---|
| 2 hang | hollow grant. Confirm `iommu=pt` took; check ACS on `00:01.1`/`00:01.3`; only then consider §5's `NVreg_RegistryDwords` — **Blackwell evidence, 3090 is confirmed working without it, and it costs ~3% when P2P is off** |
| 3 wrong data | hard stop, `rollback.sh l1`, do not proceed |
| 4/5 | harness problem — compare against `validate.before.txt` |
## Phase 7 — Serving on P2P, gated on output
```bash
docker rm -f vllm-qwen38-27b-dual-superfast # drops the layer holding the stale cache
find /opt/ai/club-3090 -name "gpu_p2p_access_cache_for_*.json" -delete
sed -i 's/^NVLINK_MODE=.*/NVLINK_MODE=pcie_p2p/' /opt/ai/club-3090/.env
cd /opt/ai/club-3090
VLLM_SKIP_P2P_CHECK=0 bash scripts/launch.sh --variant vllm/qwen38-27b-dual-superfast
bash scripts/report.sh 2>&1 | tee ~/p2p-run/report.after.txt
bash scripts/verify-full.sh 2>&1 | tee ~/p2p-run/verify.after.txt
bash scripts/verify-stress.sh 2>&1 | tee ~/p2p-run/stress.after.txt # 10-20 min
```
The vLLM P2P cache is keyed **only** on the device-id list — nothing that moves when the driver
changes — so a `true` written before the swap would outlive it.
**GATE 7** — weights actually load (a hang at `pynccl` with `vLLM is using nccl==…` as the last
line is the §8 signature → `rollback.sh l0`, return to Gate 6) · `report.sh` verdict
`✓ engaged` · Transfer check `✓ N/N directed pairs OK` · `verify-full` passes **every** step,
especially step 8 degeneracy and **step 9 MTP ≥ 2.0** · `verify-stress` passes.
**If step 8 or 9 fails you are in #922** — transport fine, custom kernel not. Do not roll back
the driver. Force `AR="--disable-custom-all-reduce"` at
`/opt/ai/club-3090/models/qwen3.8-27b/vllm/compose/dual/autoround-int4/dflash2-fp8.yml:176`,
relaunch, re-verify. That keeps the prefill win, which §6 calls the reliable half.
## Phase 8 — Measure and decide
```bash
bash /opt/ai/club-3090/scripts/bench.sh 2>&1 | tee ~/bench-p2p-610.57.04-$(date +%F).txt
```
Compare against the **Phase 3** file — same driver, same kernel, same sitting. Do not compare
against `bench-baseline-nop2p.txt`; §6 records a cross-session baseline drifting 17.7%.
**GATE 8** — no metric regressed beyond noise · prefill @10K and @90K improved (if not, P2P is
not carrying the all-reduce — re-read the verdict before believing the bench) · power caps
identical across arms (`nvidia-pl.service` re-applied the 250 W / 220 W limits recorded in
`gpu-tune.before.txt`; a service that failed to re-apply invalidates the comparison).
Read prefill first. Decode gains come from the custom kernel, not the link.
---
## Rollback
```bash
bash ~/p2p-run/rollback.sh status # no sudo; prints state and recommends a tier
```
| tier | when | cost |
|---|---|---|
| **L0** | hang at `pynccl`, or #922 garbage — driver is fine | ~30 s, **no reboot** |
| **L1** | stock driver back, kernel unchanged | ~2 min + reboot, no compile, no network |
| **L2** | stock driver back, kernel has moved | ~15 min + reboot |
| **L3** | trouble that began with `iommu=pt` | reboot |
| **L4** | will not boot — GRUB `e`, drop `iommu=pt`, Ctrl-X | manual |
L0 covers both likely failures. L1's guard compares snapshot vermagic against the running
kernel and refuses, pointing at L2, if they differ.
Going back further than 610.57.04 is possible but one-way-ish: its .deb is fetchable, 610.43.02's
is **not**. The only remaining copy of 610.43.02 is the pair of tarballs already in
`~/p2p-run/rollback-cache/` — do not delete them.
## Verification (end to end)
1. `bash ~/p2p-run/rollback.sh status` → module under `updates/dkms`, `dkms status` shows only
`nvidia/610.57.04-p2p`, `iommu: pt`, `NVLINK_MODE=pcie_p2p`
2. `nvidia-smi topo -p2p rwnap` → `OK` both directions
3. `bash ~/p2p-check.sh` → correctness PASS, bandwidth ≫ `bw.before.txt`
4. `bash /opt/ai/club-3090/scripts/p2p-validate.sh` → exit 0
5. `bash /opt/ai/club-3090/scripts/report.sh` → `✓ engaged` + `✓ N/N directed pairs OK`
6. `bash /opt/ai/club-3090/scripts/verify-full.sh` → all steps, step 9 MTP ≥ 2.0
7. `bash /opt/ai/club-3090/scripts/verify-stress.sh` → needle ladder passes
8. `bash /opt/ai/club-3090/scripts/bench.sh` → prefill up vs the Phase 3 file, decode not down
9. **The DKMS payoff:** at the next kernel bump, confirm `dkms status` rebuilt
`nvidia/610.57.04-p2p` automatically and `topo -p2p` still reports `OK` after reboot
## Known risks
- **`install-dkms.sh` is unrun**, and now also needs its version constants bumped. The `MAKE[0]`
line is reasoned from the fork's two Makefiles plus Ubuntu's known-good conf, not observed —
no passwordless sudo here. It fails at build time with stock intact if wrong.
- **610.57.04 is untested on this box**, as is the `-v3` branch. Its README is the most developed
of the three variants (RTX 30/40/50, mixed-generation, shared console mapping) and the base
`610.57.04-p2p` branch dates from 2026-08-13, so the line has had a month of iteration — but
nobody here has run it.
- **#922 on AMD is unknown** — reproduced on two Intel rigs, not on Threadripper. Gate 7 is the
mitigation; `verify-full` step 9 is a direct detector on this slug.
- **`verify-full` cannot catch fluent-but-wrong output** — hence `verify-stress` in Gate 7.
- **ACS is unread** (needs root). If bandwidth disappoints with everything else green, that is
the first suspect; Ubuntu's generic kernel has no `pcie_acs_override`, so it is a BIOS setting.
- **Holds are a commitment.** Unholding and upgrading past 610.57.04 requires a matching fork
branch to exist first, or you get the hollow-grant hang.