- Je berekent gewicht- en KV-payload zonder ze met echte bestandsgrootte of piek-RAM te verwarren.
- Je verifieert SHA-256-identiteit en selecteert alleen profielen met hetzelfde apparaat, dezelfde context en passende grenzen.
Een kleiner modelbestand past makkelijker op een apparaat, maar dat vertelt nog niet hoeveel geheugen de uitvoering piekt of hoe snel het eerste token verschijnt. Ook mag een oud cachebestand niet ongemerkt als een nieuwe modelvariant worden gebruikt. Je hebt daarom drie verschillende controles nodig.
De eerste telt theoretische bytes, de tweede controleert bestandsidentiteit en de derde vergelijkt passende meetprofielen. Denk aan een koffer, een bagagelabel en de werkelijke reisvoorwaarden: ieder beantwoordt een andere vraag. Je verbindt ze zonder een enkele maat alles te laten bewijzen.
Je oefent met kleine offline bestandjes en verzonnen profielen onder expliciete meetcondities. Voor een echte toepassing komen de bestanden uit een beheerde bron en de meetgegevens uit de beoogde omgeving.
1. Tel bits en bytes zorgvuldig
Laat P het aantal parameters zijn en b_w het aantal bits per gewicht. De minimale gewichtpayload W rondt het totale aantal bits naar hele bytes af. Vier bits per gewicht leveren bij drie gewichten dus twaalf bits: twee bytes, geen anderhalve byte als opslaguitkomst.
Een eenvoudige KV-cache bewaart keys en values voor T tokens, L lagen, H KV-heads en d waarden per head. De factor twee telt beide soorten tensors; b_c is de bitbreedte per cachewaarde. Onze cache gebruikt zestien of 32 bits, zodat deze deling hele bytes oplevert.
Neem twee tokens, één laag, één KV-head, dimensie drie en zestien cachebits. Dat zijn 24 cachebytes, naast twee gewichtbytes. De minimale som is 26 bytes; activaties, metadata, uitlijning en runtimebuffers zitten daar nog niet bij.
payload = tensor_payload(
3,4,2,1,1,3)
print(payload['weight_payload_bytes'])
print(payload['kv_payload_bytes'])
print(payload['minimum_bytes'])
# 2
# 24
# 26
Bij nul cachetokens blijft de gewichtpayload bestaan. Een MiB telt 2**20 bytes, terwijl een miljoen bytes een andere eenheid is. De rekenfunctie telt alleen: ze hoeft de geschatte tensors niet werkelijk te alloceren.
empty_cache = tensor_payload(
3,4,0,1,1,3)
print(empty_cache['minimum_bytes'])
# 2
012. Identiteit begint bij een expliciet manifest
Een bestandsnaam alleen vertelt niet welke inhoud je krijgt. Ons manifest noemt model, vaste revisie, variant, bestandsnamen, werkelijke bytegroottes en SHA-256-hashes. De kleine revisietags hieronder zijn oefenidentifiers; de controle doet geen netwerkverzoek.
blob = b'model-demo-v1'
row = dict(
name='weights.bin',bytes=len(blob),
sha256=hashlib.sha256(
blob).hexdigest())
manifest = dict(
model_id='lesson/demo',
revision='a'*40,dtype='q8',
files=[row])
blobs = {'weights.bin':blob}
verified = verify_artifacts(
manifest,blobs)
print(verified['verified_bytes'])
print(len(verified['cache_key']))
# 13
# 64
Controleer eerst de volledige begrensde set: ontbrekende of extra bestanden zijn ook een afwijking. Daarna moeten lengte en hash overeenkomen. De cache-identiteit bevat de canoniek gesorteerde metadata, zodat alleen een andere bestandsvolgorde geen nieuwe identiteit veroorzaakt.
Een andere revisie of variant hoort juist wel een andere cachekey te geven. Een matchende hash bewijst overeenkomst met het opgegeven manifest; de betrouwbaarheid van de uitgever blijft een aparte ontwerpkeuze. De functie opent of voert de bestandjes niet uit.
updated = dict(
manifest,revision='b'*40)
again = verify_artifacts(updated,blobs)
print(again['cache_key'] ==
verified['cache_key'])
# False
023. Vergelijk dezelfde meetcondities
Een snelle warme meting is geen vervanger voor een koude start op een ander apparaat. Vereis dezelfde promptlengte, generatielengte en cachetoestand, plus het beoogde fysieke apparaat en een beschikbare backend. Daarna pas vergelijk je download, piekgeheugen, snelheid en kwaliteit.
Kies grenzen voor fictieve waarnemingen onder dezelfde prompt-, generatie- en cachecondities. Bekijk daarna een afzonderlijke payloadberekening; die voorspelt de gemeten piek-RAM niet.
Gekozen: q8. 2 geschikt. Rangorde: kwaliteit, tokens/s, tijd tot eerste token, ID.
q8 · gekozen
WASM · demo-pc · 128 invoer / 16 uitvoertokens · koude cache
- Download
- 8 MiB
- Piek-RAM
- 160 MiB
- Eerste token
- 220 ms
- Tokens/s
- 20
- Kwaliteit
- 0,95
Voldoet aan alle voorwaarden.
q4
WEBGPU · demo-pc · 128 invoer / 16 uitvoertokens · koude cache
- Download
- 4 MiB
- Piek-RAM
- 90 MiB
- Eerste token
- 80 ms
- Tokens/s
- 55
- Kwaliteit
- 0,9
Voldoet aan alle voorwaarden.
ander-apparaat
WEBGPU · other-pc · 128 invoer / 16 uitvoertokens · koude cache
- Download
- 2 MiB
- Piek-RAM
- 60 MiB
- Eerste token
- 30 ms
- Tokens/s
- 80
- Kwaliteit
- 0,99
Afgewezen: ander apparaat.
warme-cache
WASM · demo-pc · 128 invoer / 16 uitvoertokens · warme cache
- Download
- 0 MiB
- Piek-RAM
- 120 MiB
- Eerste token
- 20 ms
- Tokens/s
- 30
- Kwaliteit
- 0,95
Afgewezen: andere prompt-, generatie- of cachecondities.
1.000.000 parameters, 4 lagen, 2 KV-koppen, kopdimensie 32 en 16-bitcache. De profielwaarnemingen hierboven blijven afzonderlijke fictieve gegevens.
- Gewichtpayload
- 1.000.000 B
- KV-payload
- 131.072 B
- Samen minimaal
- 1,079 MiB
De balk toont alleen de onderlinge verhouding en schaalt mee. Metadata, activaties en runtimebuffers ontbreken. Werkelijke bestanden en piek-RAM kunnen groter zijn.
Alle profielwaarden zijn verzonnen onderwijsdata. Prompt: 128 tokens; uitvoer: 16 tokens; koude cache; apparaat demo-pc. Download maximaal 10 MiB, minimaal 15 tokens/s. Geen benchmark van je eigen pc of een bestaand model. Een hashcontrole uit de les bevestigt alleen identiteit tegenover het gegeven manifest.
TTFT betekent tijd tot het eerste token (time to first token). Tokens per seconde beschrijft de gemeten generatiesnelheid; kwaliteit is hier een gegeven oefenscore waarbij hoger beter is. Dit fictieve q8-profiel gebruikt WASM.
context = dict(
input_tokens=128,
output_tokens=32,cold=True)
measurements = dict(
download_bytes=8*2**20,
peak_bytes=160*2**20,ttft_ms=220,
tokens_per_second=20,quality=.95)
profile = dict(
id='q8',device='demo-a',
backend='wasm',context=context,
measurements=measurements)
fast = dict(
profile,id='q4',backend='webgpu',
measurements=dict(
measurements,
download_bytes=4*2**20,
peak_bytes=90*2**20,ttft_ms=80,
tokens_per_second=55,
quality=.90))
Beide profielen passen hieronder binnen de gekozen grenzen. Onze selectieregel kiest eerst de hoogste kwaliteit, daarna throughput, daarna lagere TTFT en ten slotte ID. Daarom wint q8 hier, ook al is het fictieve q4-profiel sneller.
limits = dict(
max_download_bytes=10*2**20,
max_peak_bytes=200*2**20,
max_ttft_ms=250,
min_tokens_per_second=15,
min_quality=.85)
budget = dict(
device='demo-a',context=context,
available_backends=[
'wasm','webgpu'],
limits=limits)
decision = select_profile(
[profile,fast],budget)
print(decision['chosen_id'])
# q8
Als de latencygrens naar honderd gaat en de kwaliteitsgrens naar 0,92, past geen van beide. Geef dan None terug en bewaar de afwijsredenen. Een ongeschikt profiel aanwijzen zou de voorwaarden stilzwijgend veranderen.
strict = dict(
budget,limits=dict(
limits,max_ttft_ms=100,
min_quality=.92))
print(select_profile(
[profile,fast],strict)['chosen_id'])
# None
03Wat neem je mee?
- Theoretische payload en werkelijk piekgeheugen zijn verschillende metingen.
- Hashes binden inhoud aan een manifest, niet vertrouwen aan een uitgever.
- Vergelijk passende contexten en respecteer alle expliciete budgetten.
Hierna onderzoek je privacy, fairness en de betekenis van uitleg over een model.