Autoregressive requests can need different numbers of output tokens. If the active batch is locked until every request finishes, one early completion leaves a slot unused while another request waits. This activity executes padded CPU decoding under fixed-batch and per-token admission rules.
When you need this. You need to distinguish a scheduling mechanism from a serving benchmark. Trace which requests occupy the next model call and verify their generated tokens before interpreting a schedule with fewer logical iterations.
A decoding iteration runs one next-token step for each active request. The scheduler removes finished jobs and may admit waiting ones before the next iteration. Prefixes have different lengths, so the tensor batch is right-padded. A causal mask blocks future positions, a validity mask blocks padded keys, and the predictor gathers the last real position for each row.
The experiment reuses the byte-preserved trained checkpoint and tokenizer. At each logical tick it builds a tensor batch of complete current prefixes, computes one forward pass, selects argmax tokens and updates per-job completion budgets. Continuous admission fills available slots at the next iteration. The fixed policy waits until its entire active set is empty. Both recompute prefixes; neither uses a KV cache.
The copied trained parameters and tokenizer come from the existing story-model training lesson. Their original files remain unchanged.
Download the complete lab and enter quantization-and-batching/. Create an isolated Python environment and install its pinned dependency with python -m pip install -r requirements.txt. The computation uses CPU tensors; no pretrained model download, GPU or paid service is needed. The PyTorch installation guide covers platform-specific installation choices. Another library version requires rerunning the checks.
1. Keep padding out of the prediction
batched_logits() forms (batch, max_length, width) tensors. Masking padded keys prevents artificial padding tokens from influencing real positions. Gathering index length-1 prevents a padded query position from becoming the returned prediction. The two masks and the gather solve different problems.
test_batched_logits_match_individual_with_padding compares each returned vocabulary-logit vector with an independent decoder.forward call on its unpadded prefix. It uses absolute tolerance 1e-10 and relative tolerance 1e-8. Comparing only the two scheduler outputs would not detect a batching defect shared by both.
2. Follow the freed slot
python run.py batchingAll jobs in this fixture arrive at logical tick zero. Capacity is 2. Their token budgets are a: 2, b: 5, c: 1. The fixed schedule finishes at tick 6; continuous admission finishes at tick 5. These are authored-clock iterations, not seconds.
Request c is admitted at tick 5 in the fixed schedule and tick 2 in continuous admission. Its completion ticks are 6 and 3. Inspect the trace for the slot freed when request a finishes. The complete generated token lists match: true.
Read the complete implementation
"""Actual CPU weight quantization and token-step scheduling experiments.
The scheduler uses logical arrival ticks, not measured network latency.
"""
import copy
import json
import math
from pathlib import Path
import torch
import torch.nn.functional as F
import decoder
from bpe import Tokenizer
HERE=Path(__file__).resolve().parent
MATRICES=['Wq','Wk','Wv','Wo','W1','W2','W_out']
def parameters():
raw=json.loads((HERE/'params.json').read_text())
decoder.CONFIG['d']=len(raw['tok_emb'][0])
return {name:torch.tensor(value,dtype=torch.float64) for name,value in raw.items()}
def quantize(weight,bits):
if bits not in (4,8) or weight.ndim!=2 or min(weight.shape)<1 or not torch.isfinite(weight).all():
raise ValueError('finite matrix and 4 or 8 bits required')
qmax=2**(bits-1)-1
maximum=weight.abs().amax(1)
scales=torch.where(maximum==0,torch.ones_like(maximum),maximum/qmax)
q=(weight/scales[:,None]).round().clamp(-qmax,qmax).to(torch.int8)
if bits==8:
payload=bytes(q.view(torch.uint8).flatten().tolist())
else:
shifted=(q.flatten().to(torch.int16)+8).to(torch.uint8)
if len(shifted)%2:shifted=torch.cat((shifted,torch.tensor([8],dtype=torch.uint8)))
payload=bytes((shifted[::2] | (shifted[1::2]<<4)).tolist())
return {'bits':bits,'shape':list(weight.shape),'scales':scales.tolist(),'payload_hex':payload.hex()}
def dequantize(artifact):
bits=artifact['bits'];rows,cols=artifact['shape']
if bits not in (4,8) or type(rows) is not int or type(cols) is not int or rows<1 or cols<1:
raise ValueError('invalid quantized shape or width')
scales=torch.tensor(artifact['scales'],dtype=torch.float64)
if scales.shape!=(rows,) or not torch.isfinite(scales).all() or (scales<=0).any():
raise ValueError('invalid row scales')
data=bytearray.fromhex(artifact['payload_hex'])
required=rows*cols if bits==8 else (rows*cols+1)//2
if len(data)!=required:raise ValueError('quantized payload size mismatch')
packed=torch.tensor(list(data),dtype=torch.uint8)
if bits==8:q=packed.view(torch.int8).to(torch.float64)
else:q=torch.stack((packed&15,packed>>4),1).flatten()[:rows*cols].to(torch.float64)-8
return q.reshape(rows,cols)*scales[:,None]
def batched_logits(p,sequences):
if not sequences:raise ValueError('nonempty batch required')
for ids in sequences:decoder.inputs(p,ids,[0]*len(ids))
length=max(map(len,sequences));d=p['tok_emb'].shape[1]
ids=torch.zeros((len(sequences),length),dtype=torch.long)
sizes=torch.tensor([len(s) for s in sequences])
for i,sequence in enumerate(sequences):ids[i,:len(sequence)]=torch.tensor(sequence)
x=p['tok_emb'][ids]+p['pos_emb'][:length]
norm=lambda value,name:F.layer_norm(value,(d,),p[name+'_g'],p[name+'_b'],eps=decoder.model.EPS)
h=norm(x,'ln1');q,k,v=(h@p[name] for name in ['Wq','Wk','Wv'])
scores=(q@k.transpose(-1,-2))/math.sqrt(d)
causal=torch.ones(length,length,dtype=torch.bool).tril()
valid=torch.arange(length)[None,:]<sizes[:,None]
allowed=causal[None,:,:]&valid[:,None,:]
mixed=scores.masked_fill(~allowed,float('-inf')).softmax(-1)@v
x=x+mixed@p['Wo'];h=norm(x,'ln2')
x=x+F.relu(h@p['W1']+p['b1'])@p['W2']+p['b2']
logits=norm(x,'lnf')@p['W_out']+p['b_out']
return torch.stack([logits[i,n-1] for i,n in enumerate(sizes)])
def schedule(p,jobs,continuous=True,capacity=2):
if type(capacity) is not int or capacity<1:raise ValueError('positive capacity required')
if not isinstance(jobs,list) or not jobs or len(jobs)>64:
raise ValueError('1..64 jobs required')
if any(not isinstance(job,dict) or set(job)!={'id','arrival','prompt','tokens'} or not isinstance(job['id'],str) or not job['id'] for job in jobs):
raise ValueError('named jobs with arrival, prompt and tokens required')
if len({job['id'] for job in jobs})!=len(jobs):raise ValueError('unique job IDs required')
for job in jobs:
if type(job['arrival']) is not int or job['arrival']<0 or type(job['tokens']) is not int or job['tokens']<1:
raise ValueError('nonnegative arrival and positive token budget required')
decoder.inputs(p,job['prompt'],[0]*len(job['prompt']))
if len(job['prompt'])+job['tokens']>len(p['pos_emb']):raise ValueError('context budget exceeded')
pending=sorted(copy.deepcopy(jobs),key=lambda j:(j['arrival'],j['id']));active=[];done=[];ticks=[];tick=0
with torch.no_grad():
while pending or active:
if continuous or not active:
while pending and pending[0]['arrival']<=tick and len(active)<capacity:
job=pending.pop(0);job['generated']=[];job['admitted']=tick;active.append(job)
if not active:
tick=pending[0]['arrival'];continue
logits=batched_logits(p,[j['prompt']+j['generated'] for j in active])
tokens=logits.argmax(-1).tolist();ticks.append({'tick':tick,'active':[j['id'] for j in active]})
keep=[]
for job,token in zip(active,tokens):
job['generated'].append(token)
if len(job['generated'])==job['tokens']:
job['finished']=tick+1;done.append(job)
else:keep.append(job)
active=keep;tick+=1
return {'policy':'continuous admission' if continuous else 'fixed batch until all finish',
'capacity':capacity,'logical_ticks':tick,'batch_forward_calls':len(ticks),
'jobs':sorted(done,key=lambda j:j['id']),'trace':ticks}
def quantization_run():
p=parameters();tok=Tokenizer.load(HERE/'tokenizer.json');text='mia has a red hat.';ids=tok.encode(text)
baseline,_=decoder.forward(p,ids,[0]*len(ids));rows=[]
full=sum(value.numel()*value.element_size() for value in p.values())
for bits in [8,4]:
changed={name:value.clone() for name,value in p.items()};packed={}
for name in MATRICES:
packed[name]=quantize(p[name],bits);changed[name]=dequantize(packed[name])
logits,_=decoder.forward(changed,ids,[0]*len(ids))
payload=sum(len(bytes.fromhex(a['payload_hex']))+len(a['scales'])*8 for a in packed.values())
untouched=sum(value.numel()*value.element_size() for name,value in p.items() if name not in MATRICES)
rows.append({'bits':bits,'selected_matrices':MATRICES,'numeric_model_payload_bytes':payload+untouched,
'packed_matrix_bytes':payload,'unquantized_parameter_bytes':untouched,
'serialized_quantized_artifacts_bytes':len(json.dumps(packed).encode()),
'max_logit_error':(logits-baseline).abs().max().item(),
'changed_argmax_positions':int((logits.argmax(-1)!=baseline.argmax(-1)).sum()),
'positions':len(ids)})
return {'mode':'actual local CPU quantization, packing and dequantized inference on an existing trained checkpoint',
'input_text':text,'input_ids':ids,'full_precision_payload_bytes':full,'results':rows,
'scope':'Selected linear matrices only; scales remain float64. No integer kernel, AWQ, GPU speed or quality benchmark.'}
def batching_run():
p=parameters();tok=Tokenizer.load(HERE/'tokenizer.json')
jobs=[{'id':'a','arrival':0,'prompt':tok.encode('mia has'),'tokens':2},
{'id':'b','arrival':0,'prompt':tok.encode('zoe has'),'tokens':5},
{'id':'c','arrival':0,'prompt':tok.encode('ben has'),'tokens':1}]
fixed=schedule(p,jobs,False);continuous=schedule(p,jobs,True)
same=[j['generated'] for j in fixed['jobs']]==[j['generated'] for j in continuous['jobs']]
if not same:raise AssertionError('scheduling changed deterministic output')
return {'mode':'actual local CPU batched token decoding under authored logical arrival ticks',
'fixed':fixed,'continuous':continuous,'outputs_equal':same,
'scope':'Logical ticks are not wall-clock latency or throughput. Full-prefix recomputation; no paged KV cache or vLLM claim.'}{
"mode": "actual local CPU batched token decoding under authored logical arrival ticks",
"fixed": {
"policy": "fixed batch until all finish",
"capacity": 2,
"logical_ticks": 6,
"batch_forward_calls": 6,
"jobs": [
{
"id": "a",
"arrival": 0,
"prompt": [
58,
36
],
"tokens": 2,
"generated": [
33,
89
],
"admitted": 0,
"finished": 2
},
{
"id": "b",
"arrival": 0,
"prompt": [
61,
36
],
"tokens": 5,
"generated": [
33,
89,
79,
4,
67
],
"admitted": 0,
"finished": 5
},
{
"id": "c",
"arrival": 0,
"prompt": [
6,
39,
36
],
"tokens": 1,
"generated": [
33
],
"admitted": 5,
"finished": 6
}
],
"trace": [
{
"tick": 0,
"active": [
"a",
"b"
]
},
{
"tick": 1,
"active": [
"a",
"b"
]
},
{
"tick": 2,
"active": [
"b"
]
},
{
"tick": 3,
"active": [
"b"
]
},
{
"tick": 4,
"active": [
"b"
]
},
{
"tick": 5,
"active": [
"c"
]
}
]
},
"continuous": {
"policy": "continuous admission",
"capacity": 2,
"logical_ticks": 5,
"batch_forward_calls": 5,
"jobs": [
{
"id": "a",
"arrival": 0,
"prompt": [
58,
36
],
"tokens": 2,
"generated": [
33,
89
],
"admitted": 0,
"finished": 2
},
{
"id": "b",
"arrival": 0,
"prompt": [
61,
36
],
"tokens": 5,
"generated": [
33,
89,
79,
4,
67
],
"admitted": 0,
"finished": 5
},
{
"id": "c",
"arrival": 0,
"prompt": [
6,
39,
36
],
"tokens": 1,
"generated": [
33
],
"admitted": 2,
"finished": 3
}
],
"trace": [
{
"tick": 0,
"active": [
"a",
"b"
]
},
{
"tick": 1,
"active": [
"a",
"b"
]
},
{
"tick": 2,
"active": [
"b",
"c"
]
},
{
"tick": 3,
"active": [
"b"
]
},
{
"tick": 4,
"active": [
"b"
]
}
]
},
"outputs_equal": true,
"scope": "Logical ticks are not wall-clock latency or throughput. Full-prefix recomputation; no paged KV cache or vLLM claim.",
"refusal": "positive capacity required",
"command": [
"python",
"run.py",
"batching",
"--record"
],
"exit_status": 0,
"environment": {
"python": "3.12.8",
"torch": "2.14.1",
"platform": "macOS-27.0.1-arm64-arm-64bit"
},
"sources": {
"experiment.py": "1306ee38f04deea2060cdbf6fa7449da38279f9fe7be2eec8893d3a2afe8a9eb",
"decoder.py": "5706ca21af551b17ee54ca00f5a6011981b327e03b1e880b6712c06dd7d1c39a",
"vendor/model.py": "0d3d469afd5f35ef19b04e0b0587143c39f8fbca37d6154e6435c4ed4e8b80fc",
"run.py": "aaac2de2d29a3e5f70f654839dc454cd8ef0ac97fa14e870d245d28ab65d3022",
"test_experiment.py": "f9c08f86d6ce9f9a5d78dd6acf572f81431711992e709ac6106c17b90f76d04d",
"params.json": "26510c85e6e6bf6e9b1dd8766f20a062ce6da35eff4d50984f1b2aead774c1d5",
"tokenizer.json": "7478ffcb69ca5383828956b1d6db10f2ca6bc925abab7122e8da6f5d05e61657",
"bpe.py": "f2986e70b69224d9bae7694b085275d01d8cf0103b7f05399e8c9840a1679143"
}
}
run.py batching performs new local computation and leaves saved files unchanged. --record deliberately replaces this stage’s results and report. The raw record retains the command, exit status, runtime and implementation hashes.
Failure cases
| Boundary checked | Required behavior |
|---|---|
| Invalid job or capacity | Refuse invalid identities, budgets, capacity and context before admission. |
| Work admitted before arrival | Admit each request only when its declared logical arrival tick has been reached. |
| Padded output differs from individual inference | Compare each padded-batch output with an independent unpadded decoder call. |
A job cannot fit the context or capacity contract. The saved refusal is positive capacity required. test_invalid_job_identity_capacity_and_context_refused also checks duplicate job IDs, nonpositive token budgets, excessive context and Boolean token IDs. Refuse the request rather than allowing a malformed job to occupy the schedule.
A request has not arrived. test_idle_arrival_does_not_start_work_early uses a later-arrival fixture and checks that it is admitted only at its declared tick. The main comparison’s simultaneous arrivals do not test that boundary by themselves.
Run python -m unittest -v test_experiment.py. In a separate copy, delay request c’s arrival and predict its admission tick. Explain why changing arrival ticks can change the schedule without changing deterministic token predictions.
Interpret the result at its actual scope
Iteration-level scheduling is described in ORCA. This lab isolates the admission rule using a small padded CPU decoder; it does not reproduce ORCA’s distributed system or performance results. Logical ticks and forward-call counts are not wall-clock latency or throughput. There is no HTTP traffic, paged KV cache, GPU scheduler or vLLM implementation in this activity.
Check your understanding
Read the explanation
Admission is reconsidered between token steps rather than waiting for the whole active batch to finish.
References
Primary sources checked October 24, 2026. The saved local execution, rather than the cited research results, supplies the measurements above.