tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

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()