"""Sampled, exclusive timing of a COPY of the local-probe performance worker. Original numerical functions remain in the executable verbatim. Only sampled Jacobian callbacks use timing clones; ordinary residuals never reach a clone. No production source or existing experiment implementation is edited. """ from pathlib import Path from concurrent.futures import ThreadPoolExecutor import argparse, hashlib, json, os, re, shutil, statistics, subprocess, time import local_probe_experiment as experiment ROOT=experiment.ROOT SOURCE=ROOT/'test/local-probe-20260917/worker' OUT=ROOT/'test/local-probe-profile-direct-20260917' HERE=Path(__file__).parent replace=experiment.replace span=experiment.function_span write=experiment.write def function(source,name): a,b,e=span(source,name) return source[a:e] def annotate_tail(tail): """Fail closed for the reviewed generated model, not a general C parser. Stage ownership follows extended.py; declarations remain in original scope. Pipe argument PH inversion and accumulation belong to diagnostics; writes of diagnostic outputs belong to remaining_outputs. """ phase='PF_NODE';mode='node';pipe=False;result=['PF_PROBE(PF_NODE);'] counts={};transitions=[] for i,line in enumerate(tail.splitlines()): category=phase if mode=='node' and re.match(r'w\[\d+\] = [phq]\[\d+\];$',line):mode='port' if mode=='port' and not re.match(r'w\[\d+\] = [phq]\[\d+\];$',line):mode='mechanical' if mode=='mechanical' and line.startswith('dy[0]='):mode='gas' if line.startswith('for(int i=0;i=0 && !(eligible && valid))PF_MARK(PF_FULL_FALLBACK);\n int result=eligible && valid ?') return source+'\n'+clone+'\n'+wrapper+'\n',meta def instrument_support(source): reuse=function(source,'lp_reuse').replace('int lp_reuse(','int pf_reuse(',1) reuse=replace(reuse,'int contextual=lp_before[region]!=lp_after[region];', 'int contextual=lp_before[region]!=lp_after[region];\n if(contextual)PF_MARK(PF_CONTEXT);') assert reuse.count('{context_misses[lp_color]++;return 0;}')==2 reuse=reuse.replace('{context_misses[lp_color]++;return 0;}', '{context_misses[lp_color]++;PF_MARK(PF_DISPATCH);return 0;}') reuse=replace(reuse,'if(contextual){properties->count=after->count;', 'PF_MARK(PF_RESTORE);\n if(contextual){properties->count=after->count;') reuse=replace(reuse,'return 1;','PF_MARK(PF_DISPATCH);return 1;') wrappers=''' void pf_snapshot(int index,NativePropertyCache *p,NativePipeCache *c){ if(!needed[index] || captured[index]){lp_snapshot(index,p,c);return;} PF_MARK(PF_SNAPSHOT);lp_snapshot(index,p,c);PF_MARK(PF_BASELINE); } void pf_save(double *p,double *h,double *q,double *w,double *fb){ PF_MARK(PF_SNAPSHOT);lp_save(p,h,q,w,fb);PF_MARK(PF_BASELINE); } void lp_jac_time_end(uint64_t start,uint64_t end){jac_ticks+=end-start;jac_calls++;} ''' return source+'\n'+reuse+'\n'+wrappers def instrument_cv(source): rhs=function(source,'jac_rhs_reuse').replace('jac_rhs_reuse(', 'pf_jac_rhs_reuse(',1).replace('lp_eval(', 'pf_lp_eval(') colored=function(source,'colored_difference').replace('colored_difference(', 'pf_colored_difference(',1).replace('jac_rhs_reuse(', 'pf_jac_rhs_reuse(') colored=replace(colored,'if (SUNMatZero(matrix)) return -1;', 'PF_SCOPE(0,PF_ZERO);if (SUNMatZero(matrix)) return -1;PF_MARK(PF_OTHER);') colored=replace(colored,'lp_color=color;memcpy(test,state,NSTATES*sizeof(double));', 'PF_SCOPE(0,PF_PERTURB);lp_color=color;memcpy(test,state,NSTATES*sizeof(double));') colored=replace(colored,'#if MODEL_JACOBIAN_GAS_REUSE', 'PF_MARK(PF_OTHER);\n#if MODEL_JACOBIAN_GAS_REUSE') colored=replace(colored,'if (flag) return flag;','PF_SCOPE(0,PF_ASSEMBLY);if (flag) return flag;') colored=replace(colored,' }\n context->run->jacobian_colored_evals++;', ' PF_MARK(PF_OTHER);\n }\n context->run->jacobian_colored_evals++;') jac=function(source,'cv_jacobian_original').replace('cv_jacobian_original(', 'pf_cv_jacobian_original(',1).replace('jac_rhs_reuse(', 'pf_jac_rhs_reuse(').replace('colored_difference(', 'pf_colored_difference(') jac=replace(jac,'int flag=jac_increments(context,y,fy,increments);', 'PF_SCOPE(0,PF_INCREMENT);int flag=jac_increments(context,y,fy,increments);PF_MARK(PF_OTHER);') jac=replace(jac,'fy=tmp3;', 'PF_SCOPE(0,PF_OTHER);fy=tmp3;') a,b,e=span(source,'cv_jacobian');sig=source[a:b] wrapper=sig+'''{ lp_color=-1;uint64_t start=lp_tick();int selected=pf_select(); if(selected)pf_open(); int result=selected?pf_cv_jacobian_original(t,y,fy,matrix,user,tmp1,tmp2,tmp3):cv_jacobian_original(t,y,fy,matrix,user,tmp1,tmp2,tmp3); if(selected)pf_close(); uint64_t finish=lp_tick();lp_jac_time_end(start,finish); if(selected)pf_flush(start,finish); if(!result){lp_matrix(t,N_VGetArrayPointer(y),SUNDenseMatrix_Data(matrix));pf_validate_matrix(t,N_VGetArrayPointer(y),SUNDenseMatrix_Data(matrix));} return result; }''' return source[:a]+rhs+'\n'+colored+'\n'+jac+'\n'+wrapper+source[e:] def prepare(coarse=False): OUT.mkdir(exist_ok=True);work=OUT/('coarse-worker' if coarse else 'worker');work.mkdir(exist_ok=True) sources={p.name:p.read_text(encoding='utf-8') for p in SOURCE.glob('*.c')} before={k:hashlib.sha256(v.encode()).hexdigest() for k,v in sources.items()} sources['model.c'],boundaries=instrument_model(sources['model.c'],coarse) sources['local_probe_support.c']=instrument_support(sources['local_probe_support.c']) sources['cvode_solver.c']=instrument_cv(sources['cvode_solver.c']) sources['common.c']=replace(sources['common.c'],'lp_start();','lp_start();pf_initialize();') sources['common.c']=replace(sources['common.c'],'lp_finish();','lp_finish();pf_finish();') plan=json.loads((SOURCE.parent/'plan.json').read_text(encoding='utf-8')) affected=[[int(i in set(g['affectedOperations'])) for i in plan['order']] for g in plan['groups']] tables='const unsigned char pf_affected[LP_NC][LP_NO]={'+','.join('{'+','.join(map(str,a))+'}' for a in affected)+'};' sources['local_probe_profile.c']=(HERE/'local_probe_profile.c').read_text(encoding='utf-8').replace('/* PROFILE_TABLES */',tables) for name in ('model.h','local_probe.h'):shutil.copyfile(SOURCE/name,work/name) shutil.copyfile(HERE/'local_probe_profile.h',work/'local_probe_profile.h') cc,sun,_=experiment.builder.toolchain();flags,libs,dlls,exe=experiment.builder.platform_build_inputs(sun);flags+=['-DLP_OBSERVE=0'] started=time.perf_counter() def compile_one(item): i,(name,src)=item;path=work/name;path.write_text('#include "local_probe_profile.h"\n'+src,encoding='utf-8',newline='\n');obj=work/f'profile-{i}.o';log=[] experiment.builder._command([cc,*flags,'-I',str(work),'-I',str(experiment.builder.NATIVE/'include'),'-I',str(sun/'include'),'-c',str(path),'-o',str(obj)],log=log,timeout=180) return obj,log with ThreadPoolExecutor(max_workers=4) as pool:objects=list(pool.map(compile_one,enumerate(sources.items()))) log=[];experiment.builder._command([cc,*flags,*[str(o) for o,_ in objects],*experiment.builder.link_library_arguments(libs),'-lm','-o',str(work/exe)],log=log) for dll in dlls:shutil.copyfile(dll,work/dll.name) (work/'build.log').write_text('\n'.join(sum([x for _,x in objects],[])+log),encoding='utf-8') write(OUT/('build-coarse.json' if coarse else 'build.json'),dict(sourceHashes=before,sourceDirectory=str(SOURCE),boundaries=boundaries,seconds=time.perf_counter()-started)) print('BUILT',time.perf_counter()-started,flush=True) def run(label,stride=16,offset=0,control=False,matrices=False,coarse=False): work=OUT/label;work.mkdir(exist_ok=True) executable=(SOURCE if control else OUT/('coarse-worker' if coarse else 'worker'))/'model.exe' env=os.environ.copy();env.update(LOCAL_PROBE_MASK='0x7ffffff',PROBE_PROFILE_STRIDE=str(stride),PROBE_PROFILE_OFFSET=str(offset),PROBE_PROFILE_MATRICES=str(int(matrices)),PROBE_PROFILE_COARSE=str(int(coarse))) args=[str(executable),'--method','BDF','--start','0','--stop','10','--sample-step','.01','--max-step','1e30','--rtol','1e-8','--timeout','300', '--sample-file',str(work/'states.bin'),'--output-block-file',str(work/'outputs.bin'),'--output',str(work/'result.json')] start=time.perf_counter() with (work/'stderr.log').open('wb') as f: p=subprocess.run(args,cwd=work,env=env,stdout=subprocess.PIPE,stderr=f,timeout=330,creationflags=subprocess.CREATE_NO_WINDOW) elapsed=time.perf_counter()-start if p.returncode:raise RuntimeError((label,p.returncode,(work/'stderr.log').read_text()[-4000:])) r=json.loads((work/'result.json').read_text());diag=json.loads((work/'probe.json').read_text()) fields=('success','finalState','final','propertyWarnings','acceptedSteps','rejectedSteps','stateTransitions','solverStarts','nfev','njev','nlu','solveSeconds','solveCpuSeconds') record={k:r[k] for k in fields} for name in ('states','outputs','events','jacobians'): path=work/f'{name}.bin' if path.exists(): with path.open('rb') as f:record[name+'Sha256']=hashlib.file_digest(f,'sha256').hexdigest() record.update(label=label,stride=stride,offset=offset,control=control,matrices=matrices,coarse=coarse,processSeconds=elapsed,diagnostic=diag) write(work/'measurement.json',record) # Numerical gate on every run, including the sampling-density controls. reference=json.loads((SOURCE.parent/'all-run-0/measurement.json').read_text(encoding='utf-8')) exact=['statesSha256','outputsSha256','eventsSha256','finalState','final','propertyWarnings','acceptedSteps','rejectedSteps','stateTransitions','solverStarts','nfev','njev','nlu'] differences=[k for k in exact if record[k]!=reference[k]] differences += [k for k in ('newtonIterations','newtonConvergenceFailures','contextComparedBytes','contextCopiedBytes','modelCalls','groups') if diag[k]!=reference['diagnostic'][k]] assert not differences,(label,differences) if matrices: ref=SOURCE.parent/'all-audit/jacobians.bin' with ref.open('rb') as f:assert record['jacobiansSha256']==hashlib.file_digest(f,'sha256').hexdigest() print('RUN',label,'Jacobian',diag['jacobianSeconds'],'solve',r['solveSeconds'],'CPU',r['solveCpuSeconds'],'process',elapsed,'exact OK',flush=True) return record def batch(): run('control-warmup',control=True) run('profile-warmup',16,101) for i in range(5): jobs=[(f'control-{i}',0,0,True),(f'profile-{i}',16,i+17,False)] if i%2:jobs.reverse() for label,stride,offset,control in jobs:run(label,stride,offset,control) for i in range(2): run(f'disabled-{i}',0,i) run(f'density8-{i}',8,i+37) run(f'density32-{i}',32,i+71) if __name__=='__main__': p=argparse.ArgumentParser();p.add_argument('action',choices=['prepare','run','batch']);p.add_argument('--label',default='sample');p.add_argument('--stride',type=int,default=16);p.add_argument('--offset',type=int,default=0);p.add_argument('--control',action='store_true');p.add_argument('--matrices',action='store_true');p.add_argument('--coarse',action='store_true');a=p.parse_args() if a.action=='prepare':prepare(a.coarse) elif a.action=='batch':batch() else:run(a.label,a.stride,a.offset,a.control,a.matrices,a.coarse)