mirror of
https://github.com/Niko1221/Strata.git
synced 2026-11-07 06:15:58 -10:00
DFlash2 on Intel Arc: the tuned bf16-selector pack for SYCL + IQ3_XXS at Arc's own confidence 0.6
The SYCL 0.2.11 engine reads only bf16 selector codebooks, so Arc gets its own tuned file (qwen3.8-flash-next-dflash2.strata1.q4_0-bf16sel.pack, 522,458,112 bytes, own SHA-256 pin) through SetDefault.pack. Only IQ3_XXS, the set measured on the A750 (tuned 0.6 x1.054, 3 of 3 rounds); other Arc sets keep the stock pack. SYCL never gets the selq4 file, CUDA / HIP / Metal never the bf16sel one. NOTICE names the second file and no longer overclaims about the text. (cherry picked from commit 6111c583b70e3c88a3d54039e13d76b19f15742d)
This commit is contained in:
1 parent
aba4ddaca7
commit
ce6bbd7d54
6 files changed
+269
-30
No files matched your search
@@ -11,8 +11,10 @@ synthetic records; no user data), then packed into the engine's runtime format (
|
||||
`tools/dflash2_pack.py --q4_0-selector`). The pack is the same size as the unmodified one (339,694,592 bytes). The model code and the
|
||||
architecture are unchanged. The pack's SHA-256 is `4df2e5ab2b47c064afbe662e16e4f06569877125c2d0e2123a4ac755266c664c`.
|
||||
|
||||
On Macs Strata runs it with `--draft-conf 0.7`; on CUDA (every expert resident) and on Strix Halo it runs at the confidence those platforms already use. It changes how many words are guessed right, never the words
|
||||
the model writes: the text is the target model's, checked word for word against the unmodified drafter on the measured sets.
|
||||
On Macs Strata runs it with `--draft-conf 0.7`; on CUDA (every expert resident) and on Strix Halo it runs at the confidence those platforms already use. It changes how many words are guessed right, not the model: every guess is checked by the target model (greedy output was identical to the unmodified drafter's on Metal and CUDA in the tests; on HIP the text can differ by window length, as with any confidence change).
|
||||
|
||||
A second file, `qwen3.8-flash-next-dflash2.strata1.q4_0-bf16sel.pack` (522,458,112 bytes, SHA-256 `34ca17fee701ff088b6069acc35a26661d237953f5d114be0a3f7dae3ec5cda9`), holds the same tuned weights packed with the bf16 selector tables
|
||||
(`tools/dflash2_pack.py --q4_0`) for the engines that read no other layout (Intel Arc, SYCL). Everything above applies to it too; Strata uses it on Arc at that card's usual confidence.
|
||||
|
||||
Training on the outputs of the Qwen3.8-Flash-Next quantizations: the owner of Strata confirmed on 2026-11-06 that the Qwen model terms allow
|
||||
training on its outputs.
|
||||
|
||||
@@ -68,6 +68,10 @@ are pinned in the code too, so the feed can move the file but a feed that lists
|
||||
model keeps the MTP. Make the entry with `feed_tool.py pack-drafter PACK --out RELEASE/drafters --version 1 --backends metal [--url-prefix ""]` (copies the file flat and writes
|
||||
`<name>.entry.json`) and pass the folder to `build-feed --drafters RELEASE/drafters`; upload the pack beside the feed in the same release. Older Controls ignore the member.
|
||||
|
||||
The member holds two entries (one `pack-drafter` call each, both folders' `.entry.json` files in the same `--drafters` folder): `qwen3.8-flash-next-dflash2.strata1.q4_0-selq4.pack` (339,694,592 bytes) with
|
||||
`--backends metal,cuda,hip`, and `qwen3.8-flash-next-dflash2.strata1.q4_0-bf16sel.pack` (522,458,112 bytes, sha256 34ca17fe...) with `--backends sycl` for the Intel Arc engine, which reads only bf16
|
||||
selector codebooks. Control asks the feed for the file name its table entry (`SET_DEFAULTS`) names and for its own backend, so no platform fetches the other's file.
|
||||
|
||||
`url` is relative to the feed's own location (or an absolute `https://` address; a loopback `http://` is allowed so a local test
|
||||
feed works; a local feed folder may only name files inside itself).
|
||||
For a GitHub release the assets are flat: pack with `--url-prefix ""` and upload every file beside the feed.
|
||||
|
||||
@@ -1630,7 +1630,7 @@ class Runner:
|
||||
if want["data_dir"] is None or not (drafting.needs_pack(**want) or drafting.needs_tuned(**want, **sig)):
|
||||
return
|
||||
tuned = drafting.tuned_applies(want["backend"], want["model_name"], want["archs"], **sig)
|
||||
self.emit("model", f"Downloading the DFlash2 drafter ({drafting.TUNED_GB if tuned else drafting.DOWNLOAD_GB:g} GB, once)…", 0)
|
||||
self.emit("model", f"Downloading the DFlash2 drafter ({drafting.tuned_pack(drafting.tuned_variant(want['backend'], want['model_name'])).gb if tuned else drafting.DOWNLOAD_GB:g} GB, once)…", 0)
|
||||
|
||||
def show(step: str, done: int, total: int) -> None:
|
||||
self.check_cancel()
|
||||
@@ -2356,7 +2356,7 @@ class Runner:
|
||||
if drafting.needs_pack(**want): # chosen DFlash2 (or Auto picking it) and the drafter is not here: it is part of the download
|
||||
sig = self.drafting_signals(_cfg or {}, want)
|
||||
parts.append({"kind": "dflash2", "label": "the DFlash2 drafter",
|
||||
"gb": drafting.TUNED_GB if drafting.tuned_applies(want["backend"], want["model_name"], want["archs"], **sig) else drafting.DOWNLOAD_GB})
|
||||
"gb": drafting.tuned_pack(drafting.tuned_variant(want["backend"], want["model_name"])).gb if drafting.tuned_applies(want["backend"], want["model_name"], want["archs"], **sig) else drafting.DOWNLOAD_GB})
|
||||
except Exception: # noqa: BLE001 - the plan still shows the rest
|
||||
pass
|
||||
gap = self.ready_pack_gap() if st.own_files else None
|
||||
|
||||
+54
-12
@@ -229,6 +229,12 @@ TUNED_NAME = "qwen3.8-flash-next-dflash2.strata1.q4_0-selq4.pack"
|
||||
TUNED_BYTES = 339694592
|
||||
TUNED_SHA256 = "4df2e5ab2b47c064afbe662e16e4f06569877125c2d0e2123a4ac755266c664c"
|
||||
TUNED_GB = 0.34
|
||||
# The same tuned weights for an engine that reads only the bf16 selector codebooks (the SYCL 0.2.11 engine refuses the Q4_0-selector pack above): the Q4_0 pack of tools/dflash2_pack.py
|
||||
# --q4_0 (the tool reproduces the stock Arc pack cda40d62... exactly from the stock weights). Its own name, size and SHA-256; the feed lists it for ["sycl"] only.
|
||||
TUNED_BF16_NAME = "qwen3.8-flash-next-dflash2.strata1.q4_0-bf16sel.pack"
|
||||
TUNED_BF16_BYTES = 522458112
|
||||
TUNED_BF16_SHA256 = "34ca17fee701ff088b6069acc35a26661d237953f5d114be0a3f7dae3ec5cda9"
|
||||
TUNED_BF16_GB = 0.52
|
||||
#: Where it is hosted (owner 11-06, recommendation of the coordinator): a GitHub release asset of Niko1221/Strata, listed in the signed feed (strata-feed.json, feed key 5d1bc23a) as a
|
||||
#: `drafters` entry (packaging/feed_tool.py pack-drafter, build-feed --drafters), so the app gets the feed's signature, offline handling and updates the same way as engine packages.
|
||||
#: The entry's url is relative to the feed (flat release assets); the size and SHA-256 above are pinned in the code as well, so the feed can move the file but never swap its bytes.
|
||||
@@ -268,15 +274,35 @@ MAX_SLOTS = 24576 # every (layer, expert) pair of Qwen3.8-Flash-Next
|
||||
BACKEND_CONF = {"sycl": 0.6, "metal": 0.5}
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TunedPack:
|
||||
"""One tuned file: ``key`` is what SetDefault.pack names (``selq4`` = Q4_0 selector codebooks, the CUDA / HIP / Metal engines; ``bf16sel`` = bf16 selector codebooks, the SYCL engine)."""
|
||||
key: str
|
||||
name: str
|
||||
size: int
|
||||
sha256: str
|
||||
gb: float
|
||||
selector_q4: bool
|
||||
|
||||
|
||||
def tuned_pack(variant: str | None = None) -> TunedPack:
|
||||
"""The pin of a tuned file, read from the module's constants at call time."""
|
||||
if variant == "bf16sel":
|
||||
return TunedPack("bf16sel", TUNED_BF16_NAME, TUNED_BF16_BYTES, TUNED_BF16_SHA256, TUNED_BF16_GB, False)
|
||||
return TunedPack("selq4", TUNED_NAME, TUNED_BYTES, TUNED_SHA256, TUNED_GB, True)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SetDefault:
|
||||
"""What Auto does for one model set on one engine family. ``drafter``: ``dflash2`` or ``mtp``. ``tuned``: DFlash2 starts with Strata's tuned pack (TUNED_NAME) where the pack is here and
|
||||
``where`` holds. ``tuned_conf``: the ``--draft-conf`` that goes with the tuned pack, or None = the backend's OWN conf stays (CONF_STEPS / BACKEND_CONF: only the pack changes). ``where``:
|
||||
"" always (Metal); "resident" CUDA with every expert resident = the card the first CONF_STEPS step (conf 0.35) is for, or a shared-memory chip (sm_121, the Spark class); "gfx1151" Strix Halo."""
|
||||
"" always (Metal); "resident" CUDA with every expert resident = the card the first CONF_STEPS step (conf 0.35) is for, or a shared-memory chip (sm_121, the Spark class); "gfx1151" Strix Halo;
|
||||
"arc_a" Intel Arc A-series (the class the A750 stands for). ``pack``: which tuned file (tuned_pack): ``selq4`` or, for the SYCL engine, ``bf16sel``."""
|
||||
drafter: str
|
||||
tuned: bool = False
|
||||
tuned_conf: float | None = None
|
||||
where: str = ""
|
||||
pack: str = "selq4"
|
||||
|
||||
|
||||
#: Per (engine family, set) defaults, measured. THE ONE TABLE to switch a set either way. The set is the model_name without its "qwen3.8-flash-next-" prefix.
|
||||
@@ -287,6 +313,9 @@ class SetDefault:
|
||||
#: Auto drafter, so only the pack changes and the conf stays what CONF_STEPS / the card class give): ONLY the cells that were measured are enabled:
|
||||
#: cuda "resident" (conf 0.35): IQ3_S l620 (RTX PRO 5000) x1.021 (3/3 rounds) and DGX Spark x1.032 / x1.048 (3/3, two runs); UD-IQ4_XS-v31 DGX Spark x1.050 (3/3). CUDA ids identical.
|
||||
#: hip gfx1151 (Strix Halo, conf 0.35): IQ3_S x1.037, UD-Q4_K_XL x1.043, UD-IQ4_XS x1.045 (3/3 each; the text differs by window length on HIP, as with any conf change).
|
||||
#: SYCL / Intel Arc (owner 11-06 ~11:30 "Yes for Arc"; DF-VAL, A750 8 GB on p1006, SYCL 0.2.11, IQ3_XXS, 3 rounds, against the stock pack at Arc's 0.6 = 18.8 tok/s): the bf16-selector tuned pack
|
||||
#: at 0.6 x1.054 (3/3 rounds), at 0.5 x1.063; MTP x0.995; the stock pack against itself x1.011. The SYCL engine refuses the selq4 pack, so Arc has its OWN file (``pack`` "bf16sel", TUNED_BF16_*)
|
||||
#: and keeps BACKEND_CONF["sycl"] = 0.6. ONLY IQ3_XXS, the measured set; every other Arc set stays on the stock pack until it is measured.
|
||||
#: NOT enabled: a 12 GB / streaming card (the CONF_STEPS 0.8 step: P2003 is still being measured), gfx1201 / R9700 (the DFlash2 prompt stall is open), SYCL / Arc (untested), several cards (not measured),
|
||||
#: and the sets nobody measured on that platform (CUDA UD-Q4_K_XL, CUDA UD-IQ4_XS, Strix UD-IQ4_XS-v31): each is one more line here once DF-VAL has the cell.
|
||||
SET_DEFAULTS = {
|
||||
@@ -298,6 +327,7 @@ SET_DEFAULTS = {
|
||||
("hip", "iq3_s"): SetDefault("dflash2", True, None, "gfx1151"),
|
||||
("hip", "unsloth-ud-q4_k_xl"): SetDefault("dflash2", True, None, "gfx1151"),
|
||||
("hip", "unsloth-ud-iq4_xs"): SetDefault("dflash2", True, None, "gfx1151"),
|
||||
("sycl", "iq3_xxs"): SetDefault("dflash2", True, None, "arc_a", "bf16sel"),
|
||||
}
|
||||
MODEL_PREFIX = "qwen3.8-flash-next-"
|
||||
|
||||
@@ -324,6 +354,12 @@ def tuned_entry(backend: str | None, model_name: str | None) -> SetDefault | Non
|
||||
return entry if entry is not None and entry.drafter == "dflash2" and entry.tuned else None
|
||||
|
||||
|
||||
def tuned_variant(backend: str | None, model_name: str | None) -> str | None:
|
||||
"""Which tuned file this set on this engine family uses (``selq4`` / ``bf16sel``), or None: no tuned entry."""
|
||||
entry = tuned_entry(backend, model_name)
|
||||
return entry.pack if entry is not None else None
|
||||
|
||||
|
||||
def tuned_conf_for(backend: str | None, model_name: str | None) -> float | None:
|
||||
"""The ``--draft-conf`` the tuned pack runs at for this set (Metal 0.7), or None: no tuned entry, or the entry keeps the backend's own conf."""
|
||||
entry = tuned_entry(backend, model_name)
|
||||
@@ -353,6 +389,8 @@ def tuned_applies(backend: str | None, model_name: str | None, archs: Any = None
|
||||
arch = first_arch(archs)
|
||||
if entry.where == "gfx1151":
|
||||
return arch == "gfx1151"
|
||||
if entry.where == "arc_a":
|
||||
return arch == "arc_a"
|
||||
if entry.where == "resident":
|
||||
if arch == "sm_121":
|
||||
return True
|
||||
@@ -401,9 +439,9 @@ def converted_path(data_dir: str | Path) -> Path:
|
||||
return Path(data_dir) / FOLDER / CONVERTED_NAME
|
||||
|
||||
|
||||
def tuned_path(data_dir: str | Path) -> Path:
|
||||
"""Where the tuned drafter lives (next to the stock packs)."""
|
||||
return Path(data_dir) / FOLDER / TUNED_NAME
|
||||
def tuned_path(data_dir: str | Path, variant: str | None = None) -> Path:
|
||||
"""Where the tuned drafter lives (next to the stock packs); ``variant``: selq4 (default) or bf16sel."""
|
||||
return Path(data_dir) / FOLDER / tuned_pack(variant).name
|
||||
|
||||
|
||||
def sha256_of(path: Path) -> str:
|
||||
@@ -445,10 +483,11 @@ def converted_ok(data_dir: str | Path | None, *, size: int | None = None, sha256
|
||||
return False
|
||||
|
||||
|
||||
def tuned_ok(data_dir: str | Path | None) -> bool:
|
||||
def tuned_ok(data_dir: str | Path | None, variant: str | None = None) -> bool:
|
||||
"""Is the tuned drafter here and exactly the pinned bytes (size, then SHA-256 once; the answer is kept in a marker beside it, as for the converted pack)? A short,
|
||||
changed or corrupt file is simply "no": the stock pack (or the MTP) is used."""
|
||||
return converted_ok(data_dir, size=TUNED_BYTES, sha256=TUNED_SHA256, name=TUNED_NAME)
|
||||
changed or corrupt file is simply "no": the stock pack (or the MTP) is used. ``variant``: selq4 (default) or bf16sel."""
|
||||
pin = tuned_pack(variant)
|
||||
return converted_ok(data_dir, size=pin.size, sha256=pin.sha256, name=pin.name)
|
||||
|
||||
|
||||
def uses_tuned(backend: str | None, model_name: str | None) -> bool:
|
||||
@@ -520,7 +559,10 @@ def pack_path(data_dir: str | Path, engine: str | os.PathLike[str] | None = None
|
||||
verified, and `engine` reads the Q4_0 selector (it is that format): the stock pack stays the fallback. `tuned`: whether this card qualifies (tuned_applies; None = the entry alone)."""
|
||||
if tuned is None:
|
||||
tuned = uses_tuned(backend, model_name)
|
||||
if engine is not None and tuned and tuned_ok(data_dir) and engine_reads_selector_q4(engine):
|
||||
variant = tuned_variant(backend, model_name) or "selq4"
|
||||
if tuned and variant == "bf16sel" and tuned_ok(data_dir, variant):
|
||||
return tuned_path(data_dir, variant) # the bf16-selector file: any engine that runs DFlash2 reads it
|
||||
if engine is not None and tuned and variant == "selq4" and tuned_ok(data_dir) and engine_reads_selector_q4(engine):
|
||||
return tuned_path(data_dir)
|
||||
if engine is not None and converted_ok(data_dir) and engine_reads_selector_q4(engine):
|
||||
return converted_path(data_dir)
|
||||
@@ -568,7 +610,7 @@ def card_vram_mib(cfg: dict[str, Any], backend: str | None, archs: Any = None) -
|
||||
def drafter_ready(data_dir: str | Path | None, model_name: str | None = None, backend: str | None = None) -> bool:
|
||||
"""Is a drafter file for this start on the computer: a stock pack (pack_ready), or, where the set has a tuned entry, the verified tuned pack."""
|
||||
try:
|
||||
return pack_ready(data_dir) or (bool(data_dir) and uses_tuned(backend, model_name) and tuned_ok(data_dir))
|
||||
return pack_ready(data_dir) or (bool(data_dir) and uses_tuned(backend, model_name) and tuned_ok(data_dir, tuned_variant(backend, model_name)))
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
@@ -918,7 +960,7 @@ def needs_tuned(mode: Any, *, klass: str = "other", model_name: str | None = Non
|
||||
"""Would this choice use DFlash2 with the tuned drafter (this set has an entry in SET_DEFAULTS) and is that file not here yet? (Setup, Load and `strata drafting fetch`
|
||||
fetch it, once; offline they skip it and the stock pack or the MTP runs.)"""
|
||||
return (choice_of(mode, model_name=model_name, family=family, backend=backend, archs=archs) == "dflash2"
|
||||
and tuned_applies(backend, model_name, archs, args=args, vram_mib=vram_mib) and bool(data_dir) and not tuned_ok(data_dir))
|
||||
and tuned_applies(backend, model_name, archs, args=args, vram_mib=vram_mib) and bool(data_dir) and not tuned_ok(data_dir, tuned_variant(backend, model_name)))
|
||||
|
||||
|
||||
def needs_mtp(mode: Any, *, klass: str = "other", model_name: str | None = None, family: str | None = None, backend: str | None = None,
|
||||
@@ -1023,7 +1065,7 @@ def apply(cfg: dict[str, Any], *, klass: str = "other", data_dir: str | Path | N
|
||||
if decision.drafter == "dflash2":
|
||||
qualifies = tuned_applies(backend, cfg.get("model_name"), archs, args=strip_mtp_flags(strip_draft_flags(args)), vram_mib=vram_mib)
|
||||
pack = pack_path(data_dir, engine, model_name=cfg.get("model_name"), backend=backend, tuned=qualifies)
|
||||
if Path(pack) != tuned_path(data_dir) and not pack_ready(data_dir): # (only the tuned pack is here and this engine cannot read it: no drafter file for it)
|
||||
if Path(pack) != tuned_path(data_dir, tuned_variant(backend, cfg.get("model_name"))) and not pack_ready(data_dir): # (only the tuned pack is here and this engine cannot read it: no drafter file for it)
|
||||
decision = Decision(decision.asked, "mtp", NOT_DOWNLOADED) if mtp_here is not False else Decision(decision.asked, "off", NONE_HERE)
|
||||
if decision.drafter == "off":
|
||||
cfg["args"] = strip_mtp_flags(strip_draft_flags(args))
|
||||
@@ -1036,7 +1078,7 @@ def apply(cfg: dict[str, Any], *, klass: str = "other", data_dir: str | Path | N
|
||||
base = strip_mtp_flags(strip_draft_flags(args))
|
||||
flags = list(engine_flags(pack, vocab, form))
|
||||
kept_conf = _flag_value(mine, "--draft-conf")
|
||||
tuned_conf = tuned_conf_for(backend, cfg.get("model_name")) if Path(pack) == tuned_path(data_dir) else None # Metal: the conf the tuned pack was measured with; CUDA / HIP: None, the backend's own conf stays
|
||||
tuned_conf = tuned_conf_for(backend, cfg.get("model_name")) if Path(pack) == tuned_path(data_dir, tuned_variant(backend, cfg.get("model_name"))) else None # Metal: the conf the tuned pack was measured with; CUDA / HIP: None, the backend's own conf stays
|
||||
flags[flags.index("--draft-conf") + 1] = kept_conf if kept_conf is not None else f"{tuned_conf if tuned_conf is not None else conf_for(backend, slots_of(base, vram_mib)):g}"
|
||||
if _flag_value(mine, "--spec") is None:
|
||||
base = _without_flag(base, "--spec") # the DFlash2 window; the person's own --spec stays
|
||||
|
||||
@@ -41,12 +41,14 @@ def plan(data_dir: str | Path, engine: str | os.PathLike[str] | None = None, *,
|
||||
the graphics memory DFlash2 alone takes on this computer (0.72 with the Q4_0 selector, which the engine reads and setup makes, else 0.89) and ``selq4`` says which.
|
||||
For a set with a tuned drafter (drafting.SET_DEFAULTS) the download is that 0.34 GB file, and it counts as missing until it is here."""
|
||||
tuned = drafting.tuned_applies(backend, model_name, archs, args=args, vram_mib=vram_mib)
|
||||
ready = drafting.tuned_ok(data_dir) if tuned else drafting.pack_ready(data_dir)
|
||||
gb = 0.0 if ready else (drafting.TUNED_GB if tuned else drafting.DOWNLOAD_GB)
|
||||
variant = drafting.tuned_variant(backend, model_name)
|
||||
pin = drafting.tuned_pack(variant)
|
||||
ready = drafting.tuned_ok(data_dir, variant) if tuned else drafting.pack_ready(data_dir)
|
||||
gb = 0.0 if ready else (pin.gb if tuned else drafting.DOWNLOAD_GB)
|
||||
if ready:
|
||||
text = "The DFlash2 drafter is already on this computer."
|
||||
elif tuned:
|
||||
text = (f"The DFlash2 drafter is {drafting.TUNED_GB:.2f} GB to download, from Strata's signed update feed, Apache-2.0 (a copy of {drafting.REPO} that Strata tuned). "
|
||||
text = (f"The DFlash2 drafter is {pin.gb:.2f} GB to download, from Strata's signed update feed, Apache-2.0 (a copy of {drafting.REPO} that Strata tuned). "
|
||||
f"It needs about {drafting.vram_gb(data_dir, engine):.1f} GB of graphics memory, less than the MTP's layer, which is not loaded beside it.")
|
||||
else:
|
||||
text = (f"The DFlash2 drafter is {drafting.DOWNLOAD_GB:.1f} GB to download (it is packed to {drafting.PACK_GB:.2f} GB for the engine and the "
|
||||
@@ -185,13 +187,16 @@ def _feed_source(feed: str | None = None) -> str:
|
||||
return os.environ.get(update_cmd.ENV_FEED) or update_cmd.default_feed()
|
||||
|
||||
|
||||
def tuned_from_feed(*, feed: str | None = None, backend: str | None = None, size: int | None = None, sha256: str | None = None) -> tuple[str, int, str] | None:
|
||||
def tuned_from_feed(*, feed: str | None = None, backend: str | None = None, size: int | None = None, sha256: str | None = None, name: str | None = None,
|
||||
variant: str | None = None) -> tuple[str, int, str] | None:
|
||||
"""(address, size, sha256) of the tuned drafter as the signed feed lists it (member ``drafters``), or None: the feed cannot be read (offline, the host is down: silent), has no
|
||||
such entry for this engine family, or lists other bytes than the ones this Strata was measured with (pinned size and SHA-256: then it is another drafter, not ours).
|
||||
A feed that does not verify is DraftingError: a bad signature, an expired feed. A build that trusts no key (a source checkout from before the keys) is silent."""
|
||||
from strata_control import signing
|
||||
want_size = drafting.TUNED_BYTES if size is None else size
|
||||
want_sha = drafting.TUNED_SHA256 if sha256 is None else sha256
|
||||
pin = drafting.tuned_pack(variant)
|
||||
want_size = pin.size if size is None else size
|
||||
want_sha = pin.sha256 if sha256 is None else sha256
|
||||
want_name = name or pin.name
|
||||
source = _feed_source(feed)
|
||||
try:
|
||||
loaded = feedmod.fetch(source, signing.load_trusted_keys(), timeout=FEED_TIMEOUT, channel="stable")
|
||||
@@ -200,7 +205,7 @@ def tuned_from_feed(*, feed: str | None = None, backend: str | None = None, size
|
||||
return None
|
||||
raise DraftingError(f"The update feed could not be trusted: {exc}") from None
|
||||
for entry in loaded.drafters:
|
||||
if entry.name == drafting.TUNED_NAME and (backend or drafting.TUNED_BACKEND) in entry.backends:
|
||||
if entry.name == want_name and (backend or drafting.TUNED_BACKEND) in entry.backends:
|
||||
if entry.size != want_size or entry.sha256 != want_sha:
|
||||
return None
|
||||
return loaded.url(entry.url), entry.size, entry.sha256
|
||||
@@ -228,16 +233,17 @@ def provide_licence(data_dir: str | Path) -> bool:
|
||||
|
||||
|
||||
def ensure_tuned(data_dir: str | Path, *, progress: Progress | None = None, cancel: threading.Event | None = None, url: str | None = None,
|
||||
size: int | None = None, sha256: str | None = None, name: str | None = None, feed: str | None = None, throttle: bool = False, backend: str | None = None) -> Path | None:
|
||||
size: int | None = None, sha256: str | None = None, name: str | None = None, feed: str | None = None, throttle: bool = False, backend: str | None = None, variant: str | None = None) -> Path | None:
|
||||
"""Make the tuned drafter (drafting.TUNED_NAME, 340 MB) exist under ``data_dir`` and return its path. It is found in the signed feed (``feed``: a URL or folder; default
|
||||
STRATA_UPDATE_FEED or the project's release feed), unless ``url`` or STRATA_DFLASH2_TUNED_URL names the file directly. None when it cannot be had without anything being wrong:
|
||||
the feed or the address does not answer (no internet, the host is down), the feed does not list the file, or it answers with an error page. Resumable (transfer.download continues a kept partial file). A complete
|
||||
file that is not the pinned bytes is deleted and DraftingError says so; an interrupted download keeps its partial file and raises DraftingError. The licence text and the
|
||||
notice are copied beside it. The stock pack is never touched. The keyword arguments are for tests."""
|
||||
report = progress or (lambda *_: None)
|
||||
want_size = drafting.TUNED_BYTES if size is None else size
|
||||
want_sha = drafting.TUNED_SHA256 if sha256 is None else sha256
|
||||
file_name = name or drafting.TUNED_NAME
|
||||
pin = drafting.tuned_pack(variant)
|
||||
want_size = pin.size if size is None else size
|
||||
want_sha = pin.sha256 if sha256 is None else sha256
|
||||
file_name = name or pin.name
|
||||
out = Path(data_dir) / drafting.FOLDER / file_name
|
||||
if drafting.converted_ok(data_dir, size=want_size, sha256=want_sha, name=file_name):
|
||||
provide_licence(data_dir)
|
||||
@@ -250,7 +256,7 @@ def ensure_tuned(data_dir: str | Path, *, progress: Progress | None = None, canc
|
||||
else: # the normal way: the signed feed names the file; nothing answers offline
|
||||
if throttle and _recent_miss(data_dir): # a launch asked a short while ago and got nothing: no wait, no second try
|
||||
return None
|
||||
found = tuned_from_feed(feed=feed, backend=backend, size=want_size, sha256=want_sha)
|
||||
found = tuned_from_feed(feed=feed, backend=backend, size=want_size, sha256=want_sha, name=file_name, variant=variant)
|
||||
_note_miss(data_dir, found is None)
|
||||
if found is None:
|
||||
return None
|
||||
@@ -288,7 +294,7 @@ def ensure_for(data_dir: str | Path, *, model_name: str | None, backend: str | N
|
||||
if drafting.tuned_applies(backend, model_name, archs, args=args, vram_mib=vram_mib):
|
||||
tuned_error: DraftingError | None = None
|
||||
try:
|
||||
got = ensure_tuned(data_dir, progress=progress, cancel=cancel, feed=feed, throttle=throttle, backend=backend)
|
||||
got = ensure_tuned(data_dir, progress=progress, cancel=cancel, feed=feed, throttle=throttle, backend=backend, variant=drafting.tuned_variant(backend, model_name))
|
||||
except DraftingError as exc:
|
||||
got, tuned_error = None, exc
|
||||
if got is not None:
|
||||
|
||||
@@ -520,7 +520,7 @@ class CudaAndHip(Fetch):
|
||||
self.assertFalse(drafting.tuned_applies("sycl", name, ["arc_a"], args=self.args, vram_mib=None))
|
||||
self.assertFalse(drafting.tuned_applies("sycl", name, ["arc_a"], args=self.args, vram_mib=8192))
|
||||
self.drop_tuned()
|
||||
self.assertNotIn("sycl", {b for e in drafting.SET_DEFAULTS for b in e[:1]})
|
||||
self.assertNotIn(("sycl", "iq3_s"), drafting.SET_DEFAULTS)
|
||||
|
||||
def test_their_confidences_are_exactly_what_they_were(self):
|
||||
"""The conf of every box class, with the tuned file here and without it, against the numbers CONF_STEPS and BACKEND_CONF have always given."""
|
||||
@@ -631,6 +631,191 @@ class CudaAndHip(Fetch):
|
||||
self.assertIsNone(drafting.card_vram_mib({"gpu": 0}, "cuda", ["sm_120"]), "a driver that does not answer")
|
||||
|
||||
|
||||
IQ3XXS = "qwen3.8-flash-next-iq3_xxs"
|
||||
BF16_BYTES = b"tuned-bf16sel-pack-" * 150_000 # 2.85 MB, stands in for the 522 MB file
|
||||
|
||||
|
||||
class Arc(Fetch):
|
||||
"""Owner 11-06 ~11:30 "Yes for Arc": the SYCL 0.2.11 engine refuses the Q4_0-selector pack, so Arc gets its OWN tuned file (bf16 selector codebooks, 522,458,112 bytes) for IQ3_XXS, the set
|
||||
DF-VAL measured on the A750, at Arc's current conf 0.6. Every other Arc set stays on the stock pack; CUDA / HIP / Metal never see the bf16sel file, SYCL never sees the selq4 one."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
pins = mock.patch.multiple(drafting, TUNED_BF16_BYTES=len(BF16_BYTES), TUNED_BF16_SHA256=hashlib.sha256(BF16_BYTES).hexdigest())
|
||||
pins.start()
|
||||
self.addCleanup(pins.stop)
|
||||
self.sycl_exe = self.root / "strata-sycl"
|
||||
self.sycl_exe.write_bytes(b"--mtp-draft-vocab FILE (or --mtp DIR ... --draft-fallback") # reads bf16 selector codebooks only
|
||||
|
||||
def put_bf16(self, content=BF16_BYTES):
|
||||
(self.data / "dflash2" / drafting.TUNED_BF16_NAME).write_bytes(content)
|
||||
|
||||
def arc(self, name=IQ3XXS, **extra):
|
||||
cfg = self.cfg(name, **extra)
|
||||
decision = drafting.apply(cfg, data_dir=self.data, backend="sycl", archs=["arc_a"], engine=self.sycl_exe)
|
||||
return decision, cfg["args"]
|
||||
|
||||
def two_entry_feed(self, sub="two", bf16_backends=("sycl",), selq4_backends=("metal", "cuda", "hip")):
|
||||
out = self.root / sub
|
||||
entries = self.root / (sub + "-entries")
|
||||
out.mkdir(parents=True, exist_ok=True)
|
||||
for name, content, backends in ((drafting.TUNED_NAME, TUNED_BYTES, selq4_backends), (drafting.TUNED_BF16_NAME, BF16_BYTES, bf16_backends)):
|
||||
if not backends:
|
||||
continue
|
||||
(out / name).write_bytes(content)
|
||||
ft.pack_drafter(out / name, entries, version="1", backends=list(backends))
|
||||
(entries / name).unlink(missing_ok=True)
|
||||
ft.build_feed(out, key=ft._load_key(self.keys / "feed-key.json"), sequence=1, drafters_dir=entries)
|
||||
return out
|
||||
|
||||
def test_the_pins(self):
|
||||
self.assertEqual(drafting.tuned_pack("bf16sel").name, "qwen3.8-flash-next-dflash2.strata1.q4_0-bf16sel.pack")
|
||||
self.assertNotEqual(drafting.tuned_pack("bf16sel").name, drafting.tuned_pack("selq4").name)
|
||||
self.assertEqual(drafting.tuned_pack("selq4").name, drafting.TUNED_NAME)
|
||||
self.assertEqual(drafting.tuned_pack(None), drafting.tuned_pack("selq4"))
|
||||
self.assertTrue(drafting.tuned_pack("selq4").selector_q4 and not drafting.tuned_pack("bf16sel").selector_q4)
|
||||
|
||||
def test_the_real_pins(self):
|
||||
with mock.patch.multiple(drafting, TUNED_BF16_BYTES=522458112, TUNED_BF16_SHA256="34ca17fee701ff088b6069acc35a26661d237953f5d114be0a3f7dae3ec5cda9"):
|
||||
pin = drafting.tuned_pack("bf16sel")
|
||||
self.assertEqual((pin.size, pin.sha256, pin.gb), (522458112, "34ca17fee701ff088b6069acc35a26661d237953f5d114be0a3f7dae3ec5cda9", 0.52))
|
||||
self.assertEqual(pin.size, drafting.PACK_BYTES, "the same format and size as the stock Q4_0 pack (bf16 selector)")
|
||||
self.assertNotEqual(pin.sha256, drafting.PACK_SHA256, "other weights: not the stock pack")
|
||||
self.assertNotEqual(pin.sha256, drafting.tuned_pack("selq4").sha256)
|
||||
|
||||
def test_iq3_xxs_on_arc_uses_the_bf16sel_pack_at_arcs_own_conf(self):
|
||||
self.put_stock()
|
||||
self.put_bf16()
|
||||
d, args = self.arc()
|
||||
self.assertEqual((d.drafter, d.note), ("dflash2", ""))
|
||||
self.assertEqual(flag(args, "--draft-model"), str(drafting.tuned_path(self.data, "bf16sel")))
|
||||
self.assertEqual((flag(args, "--draft-conf"), flag(args, "--spec")), ("0.6", "6"))
|
||||
self.assertEqual(drafting.BACKEND_CONF["sycl"], 0.6)
|
||||
(self.data / "dflash2" / drafting.TUNED_BF16_NAME).unlink()
|
||||
(self.data / "dflash2" / (drafting.TUNED_BF16_NAME + ".ok")).unlink()
|
||||
d2, args2 = self.arc()
|
||||
self.assertEqual(flag(args2, "--draft-model"), str(self.data / "dflash2" / drafting.PACK_NAME), "without the file: the stock pack")
|
||||
self.assertEqual(flag(args, "--draft-conf"), flag(args2, "--draft-conf"), "only the pack changes")
|
||||
strip = lambda a: [x for i, x in enumerate(a) if not (i and a[i - 1] == "--draft-model")] # noqa: E731
|
||||
self.assertEqual(strip(args), strip(args2))
|
||||
|
||||
def test_no_other_arc_set_and_no_other_arc_class_gets_it(self):
|
||||
self.put_stock()
|
||||
self.put_bf16()
|
||||
self.put_tuned()
|
||||
for name in (IQ3S, Q4, V31, OLD_XS, Q5, GYRO, "qwen3.8-flash-next-q2_0"):
|
||||
d, args = self.arc(name)
|
||||
self.assertEqual(flag(args, "--draft-model"), str(self.data / "dflash2" / drafting.PACK_NAME), name)
|
||||
self.assertFalse(drafting.tuned_applies("sycl", name, ["arc_a"]), name)
|
||||
for arch in ("arc_b", "arc_a_pro", "intel_igpu", "", "sm_120"):
|
||||
self.assertFalse(drafting.tuned_applies("sycl", IQ3XXS, [arch] if arch else []), arch)
|
||||
|
||||
def test_sycl_never_gets_the_selq4_file(self):
|
||||
self.put_stock()
|
||||
self.put_tuned() # only the selq4 file is here
|
||||
for name in (IQ3XXS, IQ3S, Q4, V31):
|
||||
d, args = self.arc(name)
|
||||
self.assertEqual(flag(args, "--draft-model"), str(self.data / "dflash2" / drafting.PACK_NAME), name)
|
||||
self.assertNotEqual(flag(args, "--draft-model"), str(drafting.tuned_path(self.data)), name)
|
||||
self.put_bf16() # both are here: the bf16sel one
|
||||
d, args = self.arc()
|
||||
self.assertEqual(flag(args, "--draft-model"), str(drafting.tuned_path(self.data, "bf16sel")))
|
||||
# even an engine that reads the Q4_0 selector gets the bf16sel pack on SYCL, never the other
|
||||
cfg = self.cfg(IQ3XXS)
|
||||
drafting.apply(cfg, data_dir=self.data, backend="sycl", archs=["arc_a"], engine=self.exe)
|
||||
self.assertEqual(flag(cfg["args"], "--draft-model"), str(drafting.tuned_path(self.data, "bf16sel")))
|
||||
self.assertEqual(drafting.tuned_variant("sycl", IQ3XXS), "bf16sel")
|
||||
|
||||
def test_cuda_hip_and_metal_never_get_the_bf16sel_file(self):
|
||||
self.put_stock()
|
||||
self.put_bf16()
|
||||
bf16 = str(drafting.tuned_path(self.data, "bf16sel"))
|
||||
for hardware, name in ((L620, IQ3S), (SPARK, V31), (STRIX, Q4), (P2003, IQ3S), (R9700, IQ3S), (L620, IQ3XXS), (STRIX, IQ3XXS), (SPARK, IQ3XXS)):
|
||||
d, args = self.apply_on_hw(hardware, name)
|
||||
self.assertNotEqual(flag(args, "--draft-model"), bf16, (hardware[0], name))
|
||||
self.assertFalse(drafting.tuned_applies(hardware[1], name, hardware[2], args=self.args, vram_mib=hardware[3]) and drafting.tuned_variant(hardware[1], name) == "bf16sel")
|
||||
cfg = self.cfg(Q4)
|
||||
drafting.apply(cfg, data_dir=self.data, backend="metal", archs=[], engine=self.exe)
|
||||
self.assertNotEqual(flag(cfg["args"], "--draft-model"), bf16)
|
||||
self.assertEqual({k[0] for k, v in drafting.SET_DEFAULTS.items() if v.tuned and v.pack == "bf16sel"}, {"sycl"})
|
||||
self.assertEqual({k[0] for k, v in drafting.SET_DEFAULTS.items() if v.tuned and v.pack == "selq4"}, {"metal", "cuda", "hip"})
|
||||
# and pack_path itself never returns it for a selq4 entry, whatever the engine reads
|
||||
self.put_tuned()
|
||||
for backend, name in (("cuda", IQ3S), ("hip", Q4), ("metal", Q4)):
|
||||
self.assertEqual(drafting.pack_path(self.data, self.exe, model_name=name, backend=backend, tuned=True), drafting.tuned_path(self.data), backend)
|
||||
|
||||
def apply_on_hw(self, hardware, name):
|
||||
_label, backend, archs, vram = hardware
|
||||
cfg = self.cfg(name)
|
||||
d = drafting.apply(cfg, data_dir=self.data, backend=backend, archs=archs, engine=self.exe, vram_mib=vram)
|
||||
return d, cfg["args"]
|
||||
|
||||
def test_the_fetch_for_arc(self):
|
||||
feed = self.two_entry_feed()
|
||||
(self.data / "dflash2").mkdir(parents=True, exist_ok=True)
|
||||
self.assertTrue(drafting.needs_tuned("auto", model_name=IQ3XXS, backend="sycl", archs=["arc_a"], data_dir=self.data))
|
||||
for name in (IQ3S, Q4, V31):
|
||||
self.assertFalse(drafting.needs_tuned("auto", model_name=name, backend="sycl", archs=["arc_a"], data_dir=self.data), name)
|
||||
seen = []
|
||||
with mock.patch.object(drafting_fetch, "ensure", side_effect=AssertionError("stock fetched")):
|
||||
got = drafting_fetch.ensure_for(self.data, model_name=IQ3XXS, backend="sycl", archs=["arc_a"], feed=str(feed), progress=lambda *a: seen.append(a))
|
||||
self.assertEqual(got, drafting.tuned_path(self.data, "bf16sel"))
|
||||
self.assertTrue(drafting.tuned_ok(self.data, "bf16sel"))
|
||||
self.assertFalse(drafting.tuned_path(self.data).exists(), "the selq4 file was not fetched for SYCL")
|
||||
self.assertEqual(got.read_bytes(), BF16_BYTES)
|
||||
self.assertTrue((self.data / "dflash2" / "LICENSE-dflash2-tuned").is_file())
|
||||
self.assertFalse(drafting.needs_tuned("auto", model_name=IQ3XXS, backend="sycl", archs=["arc_a"], data_dir=self.data))
|
||||
|
||||
def test_the_other_platforms_fetch_their_own_file_from_the_same_feed(self):
|
||||
feed = self.two_entry_feed(sub="both")
|
||||
for hardware, name in ((L620, IQ3S), (STRIX, Q4)):
|
||||
for f in (self.data / "dflash2").glob("*strata1*"):
|
||||
f.unlink()
|
||||
got = drafting_fetch.ensure_for(self.data, model_name=name, backend=hardware[1], archs=hardware[2], args=self.args, vram_mib=hardware[3], feed=str(feed))
|
||||
self.assertEqual(got, drafting.tuned_path(self.data), hardware[0])
|
||||
self.assertFalse(drafting.tuned_path(self.data, "bf16sel").exists(), hardware[0])
|
||||
for f in (self.data / "dflash2").glob("*strata1*"):
|
||||
f.unlink()
|
||||
mac = drafting_fetch.ensure_for(self.data, model_name=Q4, backend="metal", feed=str(feed))
|
||||
self.assertEqual(mac, drafting.tuned_path(self.data))
|
||||
self.assertFalse(drafting.tuned_path(self.data, "bf16sel").exists())
|
||||
|
||||
def test_a_feed_without_the_sycl_entry_gives_arc_the_stock_drafter(self):
|
||||
feed = self.two_entry_feed(sub="no-sycl", bf16_backends=())
|
||||
with mock.patch.object(drafting_fetch, "ensure", return_value=Path("/stock")) as stock:
|
||||
got = drafting_fetch.ensure_for(self.data, model_name=IQ3XXS, backend="sycl", archs=["arc_a"], feed=str(feed))
|
||||
self.assertEqual(got, Path("/stock"))
|
||||
stock.assert_called_once()
|
||||
only_selq4_for_sycl = self.two_entry_feed(sub="wrong", bf16_backends=(), selq4_backends=("sycl",))
|
||||
with mock.patch.object(drafting_fetch, "ensure", return_value=Path("/stock")):
|
||||
got = drafting_fetch.ensure_for(self.data, model_name=IQ3XXS, backend="sycl", archs=["arc_a"], feed=str(only_selq4_for_sycl))
|
||||
self.assertEqual(got, Path("/stock"), "a feed that (wrongly) lists the selq4 file for sycl is not what Arc asks for: it asks for the bf16sel name")
|
||||
self.assertFalse(drafting.tuned_path(self.data).exists())
|
||||
|
||||
def test_a_wrong_bf16sel_file_is_not_used_and_a_bad_download_is_deleted(self):
|
||||
self.put_stock()
|
||||
self.put_bf16(b"x" * len(BF16_BYTES))
|
||||
self.assertFalse(drafting.tuned_ok(self.data, "bf16sel"))
|
||||
d, args = self.arc()
|
||||
self.assertEqual(flag(args, "--draft-model"), str(self.data / "dflash2" / drafting.PACK_NAME))
|
||||
(self.data / "dflash2" / drafting.TUNED_BF16_NAME).unlink()
|
||||
feed = self.two_entry_feed(sub="bad")
|
||||
(feed / drafting.TUNED_BF16_NAME).write_bytes(b"z" * len(BF16_BYTES))
|
||||
with self.assertRaises(drafting_fetch.DraftingError) as caught:
|
||||
drafting_fetch.ensure_tuned(self.data, feed=str(feed), backend="sycl", variant="bf16sel")
|
||||
self.assertIn("safety check", str(caught.exception))
|
||||
self.assertFalse(drafting.tuned_path(self.data, "bf16sel").exists())
|
||||
|
||||
def test_the_plan_says_0_52_gb_for_arc_and_the_conf_tables_are_unchanged(self):
|
||||
self.assertEqual(drafting_fetch.plan(self.data, model_name=IQ3XXS, backend="sycl", archs=["arc_a"])["gb"], 0.52)
|
||||
self.assertEqual(drafting_fetch.plan(self.data, model_name=IQ3S, backend="sycl", archs=["arc_a"])["gb"], drafting.DOWNLOAD_GB)
|
||||
self.assertEqual(drafting_fetch.plan(self.data, model_name=IQ3S, backend="cuda", archs=["sm_121"])["gb"], 0.34)
|
||||
self.assertEqual(drafting.CONF_STEPS, ((12000, 0.35), (7500, 0.5), (3000, 0.7), (0, 0.8)))
|
||||
self.assertEqual(drafting.BACKEND_CONF, {"sycl": 0.6, "metal": 0.5})
|
||||
self.assertEqual((drafting.DRAFT_CONF, drafting.SPEC_WINDOW), (0.35, 6))
|
||||
self.assertIsNone(drafting.tuned_conf_for("sycl", IQ3XXS), "no conf of its own: Arc's 0.6 stays")
|
||||
|
||||
|
||||
class SetupOnAMac(Base):
|
||||
"""metal/setup_mac.fetch_drafter: the line appears when a download starts, never offline; the MTP stays the fallback."""
|
||||
|
||||
|
||||
Reference in new issue
Block a user