Repository navigation
AMD HIP: the primary ordinal, and the helper caches beside the resident RAM mode - #1184
tuandat3019 wants to merge 1 commit into
Conversation
…nt RAM mode Three changes for two-card AMD PCs whose faster card does not come first in the runtime's enumeration (Windows HIP orders the cards itself; HIP_VISIBLE_DEVICES only filters): - gfx1032 (RX 6600) joins the unvalidated build list - it shares the gfx1030 / gfx1031 / gfx1034 dp4a path. - STRATA_PRIMARY_DEVICE=N picks the visible ordinal the engine's own session runs on; it is set before any context or allocation exists. The helper caches take the other visible devices, the HIP arch check and the peer tier's device queries follow it, and the primary's session is created on the chosen device. A layer split still assumes device 0 and is refused with this set. Unset or 0 is upstream's behavior unchanged. - The helper-GPU caches are allowed beside the resident RAM mode: the experts a helper holds are left out of the RAM copy as a split stage's are, and the two adaptive tiers already keep each other's experts out. RemoteExperts::finish spins on its stream like PeerExperts::finish - on HIP the CUDA branch's cudaInitDevice(ScheduleSpin) does not exist. Measured on an RX 6800 (16 GB, gfx1030) + RX 6600 (8 GB, gfx1032), Windows 11, 32 GB of RAM, Swift 1.5 IQ3_XXS at 160K context, the resident RAM mode with the helper's cache left out of the copy: decode 37.5 -> 44.2 tok/s on 8K-token requests with a 3800-slot helper; the CPU pool's share of the routed experts falls from ~2.9 to ~0.4 entries per layer-window.
|
Thanks tuandat3019. Ported (0.1.45) on top of the current main with conflicts resolved and you as co-author: STRATA_PRIMARY_DEVICE, the helper caches beside the resident RAM mode, gfx1032 in the build list. With the switches unset the default is bit-identical (R9700 and two NVIDIA boxes, 10 prompts plus exact 4K/20K) and as fast. We cannot reproduce your 37.5 -> 44.2 tok/s without two RDNA2 cards, so the helper-plus-resident path is not measured on our side; it stays opt-in. |
|
Thanks for the pull request. Your change is already in If part of your work did not make it in and you want it considered, open a new pull request on top of |
Three small changes for a two-card AMD PC whose faster card does not come first in the runtime's
enumeration. On Windows the HIP runtime orders the devices itself -
HIP_VISIBLE_DEVICESonlyfilters, it cannot reorder - so with both cards visible an engine run could only put the model on the
first one. On the measured PC the RX 6600 (gfx1032) is numbered 0 and the RX 6800 (gfx1030) 1;
before this, the only way to run the model on the 6800 was to hide the 6600 from the engine.
What changes
cmake/hip_backend.cmake: gfx1032 (RX 6600) joins the unvalidated arch list; it shares thegfx1030 / gfx1031 / gfx1034 dp4a path.
docs/AMD_HIP.mdgains a line with what was run.STRATA_PRIMARY_DEVICE=N: picks the visible ordinal the engine's own session runs on. It is setbefore any context or allocation exists (every other device switch in the engine saves/restores
the current device, so that one call is where the primary is picked). The helper caches
(
--expert-cache-device1..3) take the visible devices other than the primary, the HIP arch checkcovers the primary, the primary's session is created on the chosen device, and the peer tier's
cudaDeviceCanAccessPeer/cudaDeviceEnablePeerAccessqueries use the same ordinal. A layersplit still assumes device 0 and is refused with this set. Unset or 0 is the current behavior.
--resident-experts, the low-RAMmode) - the combination was refused before. The experts a helper holds are left out of the RAM
copy as a layer split's later stages are, and the two adaptive tiers already keep each other's
experts out (
helper_holdsin the primary's candidates,RemoteExpertOpt::adapt's residenttable).
RemoteExperts::finishalso spins on its stream likePeerExperts::finish: on HIP theCUDA branch's
cudaInitDevice(ScheduleSpin)does not exist, so the device kept the defaultpolicy and the blocking sync's wake-up sat on the pool's critical path for every layer.
docs/SECOND_GPU.mddocuments the combination and the sizing lesson below.Measured (RX 6800 + RX 6600, Windows 11)
reads ~13 GB/s host->device); i5-11400F (6 cores / 12 threads); 32 GB of RAM; NVMe.
engine 0.1.40 + this change, built with
tools\hip\build_windows.batandSTRATA_HIP_ARCHS=gfx1030;gfx1032.with 32,768 resident cells; MTP
--spec 4 --spec-min-p 0.6.--resident-expertson all arms, one warmup then 8measured runs at a fixed seed (temperature 0.6); after the warmup the engine reuses ~99.9% of the
prompt, so these are warm-decode numbers. Decode tok/s are the engine's own per-request figures;
one machine, one model.
(about 10 per layer) cost about 0.3-0.6 ms per layer on the CPU pool's critical path, well under
the CPU rows and page faults they replace.
also relieves RAM pressure on a 32 GB PC.
The sizing lesson (also in docs/SECOND_GPU.md)
--expert-cache-device1 autoreadscudaMemGetInfo, which on Windows reports the process's WDDMbudget: it cannot see the desktop, the vision encoder (a separate process), a streaming host or
other apps on that card. An auto-sized helper on such a card over-commits; WDDM backs the excess
with system RAM ("shared GPU memory"), and that memory comes out of the machine's RAM - on this 32 GB
PC it pushed the resident complement towards the pagefile and made the helper read its own cache over
PCIe. An explicit count (3800 here, of ~4100 that fit an empty card) kept the cache in real VRAM.
One more measurement note: when a helper swaps experts during a long session, a re-admitted expert
that the helper held at startup but the RAM copy left out is read from the model files again. With
the default
--adapt-swaps 96that measured 0.5-1.0 GB of file reads per 8K-token request here(averaging ~10-30 MB/s of SSD traffic through decode);
--adapt-swaps 8cut it ~5x (70-400 MB perrequest) with the same decode throughput (44.0 vs 44.2 tok/s), and
--adapt-swaps 0removed itentirely at a cost of ~7 tok/s.
Not covered
STRATA_PRIMARY_DEVICE(refused).CUDA_VISIBLE_DEVICESwithCUDA_DEVICE_ORDER=PCI_BUS_IDalready reorders, this is notneeded there.