float_quantize_measure.py (3695B)
1 #!/usr/bin/env python3 2 """Fresh-process cost baseline for an already validated quantizer artifact.""" 3 import argparse 4 import json 5 from pathlib import Path 6 import random 7 import statistics 8 9 from float_quantize import ROOT, BIAS, oracle, encoded 10 from float_multiply import Runner, sha 11 from base_workloads import encode as nat 12 from http_headers import pair, tree_list, expect 13 14 15 def main(): 16 p=argparse.ArgumentParser(description=__doc__) 17 p.add_argument('tricu',type=Path) 18 p.add_argument('--validated',type=Path,required=True) 19 p.add_argument('--directory',type=Path,required=True) 20 args=p.parse_args() 21 previous=json.loads((args.validated/'report.json').read_text()) 22 assert previous['complete'] and previous['runtime_sha256']==sha(args.tricu) 23 assert previous['compiler_sha256']==sha(ROOT/'bootstrap/build-stable.arboricx') 24 assert previous['harness_sha256']==sha(ROOT/'test/float_quantize.py') 25 bundle=args.validated/'quantize.arboricx' 26 assert sha(bundle)==previous['bundle_sha256'] 27 assert sha(ROOT/'bench/float-quantize.tri')==previous['sources']['driver.tri'] 28 root=args.directory.resolve();root.mkdir(parents=True,exist_ok=False) 29 runner=Runner(args.tricu,root,600,memory_mib=2048) 30 report=dict(complete=False,runtime_sha256=sha(args.tricu),compiler_sha256=previous['compiler_sha256'], 31 validated_report_sha256=sha(args.validated/'report.json'),bundle_sha256=sha(bundle), 32 harness_sha256=sha(Path(__file__)),oracle_sha256=sha(ROOT/'test/float_quantize.py'),samples=[],summaries=[]) 33 try: 34 pin=runner.imported(bundle,'quantize') 35 rng=random.Random(107453) 36 groups={ 37 'normal-106':[(rng.randrange(2**105,2**106),BIAS-104) for _ in range(16)], 38 'cancellation':[(i+1,BIAS-52) for i in range(16)], 39 'subnormal-midpoints':[(2**54+i,BIAS-1077) for i in range(16)], 40 'tiny-to-zero':[(i+1,BIAS-1126) for i in range(16)], 41 'overflow-midpoint':[((2**54-1)*8+i%5-2,BIAS+967) for i in range(16)]} 42 for rep in range(5): 43 schedule=list(groups);rng.shuffle(schedule) 44 for group in schedule: 45 rows=groups[group] 46 label=f'{group}-{rep}' 47 raw=tree_list([pair(nat(s),nat(n)) for n,s in rows]) 48 wanted=tree_list([encoded(oracle(n,s)) for n,s in rows]) 49 path=root/(label+'.input.tree');path.write_bytes(raw) 50 actual=runner.invoke(label,pin,'quantized',['--arg-tree-file',path,'--profile-full-result']) 51 expect(actual,wanted,label) 52 points={v['profile']:v for line in (root/(label+'.log')).read_text().splitlines() 53 if line.startswith('{') for v in [json.loads(line)]} 54 a,b=points['invoke-begin-1'],points['force-end-1'] 55 report['samples'].append(dict(group=group,repeat=rep,warmup=rep==0,size=len(rows), 56 wall_ns=b['wall_ns']-a['wall_ns'],allocated_bytes=b['allocated_bytes']-a['allocated_bytes'])) 57 for group in groups: 58 samples=[s for s in report['samples'] if s['group']==group and not s['warmup']] 59 row=dict(group=group,size=len(groups[group])) 60 for key in ['wall_ns','allocated_bytes']: 61 row[key]=statistics.median(s[key] for s in samples) 62 row[key+'_min']=min(s[key] for s in samples);row[key+'_max']=max(s[key] for s in samples) 63 report['summaries'].append(row);print(json.dumps(row),flush=True) 64 report['complete']=True 65 finally: 66 (root/'report.json').write_text(json.dumps(report,indent=2)+'\n') 67 68 69 if __name__=='__main__': main()