C内核按库功能拆解,编译结果缓存区构建,编译过程与已有缓存结果对照功能实现
This commit is contained in:
1 parent
aa4951b14e
commit
151e6e4b97
30 files changed
+4856
-604
No files matched your search
@@ -33,6 +33,76 @@ NEW_CALL = '''double base=area*p*cm/sqrt(T),K=pow(4*base/den,2)*d/length;
|
||||
return sign*native_pipe_resistance(K,rr,den/4,NULL)*den/4;'''
|
||||
|
||||
|
||||
def pipe_source_path(native: Path) -> Path:
|
||||
"""Locate executable pipe formulas, never a modular aggregation entry."""
|
||||
module = native / 'components/modules/pipe.c'
|
||||
legacy = native / 'components/kernels.c'
|
||||
if module.is_file():
|
||||
target = module
|
||||
elif (native / 'components/modules').exists():
|
||||
raise ValueError(f'Incomplete modular native snapshot: {module} is missing')
|
||||
else:
|
||||
target = legacy
|
||||
if not target.is_file():
|
||||
raise ValueError(f'Native snapshot has no audited pipe source: {native}')
|
||||
source = target.read_text()
|
||||
if source.count('double native_pipe_resistance(') != 1 or source.count('double native_pipe_flow(') != 1:
|
||||
raise ValueError(f'Unsupported pipe source layout: {target}; refusing an unmodified or uninstrumented run')
|
||||
return target
|
||||
|
||||
|
||||
def working_native_paths() -> list[str]:
|
||||
return sorted('native/' + path.relative_to(ROOT / 'native').as_posix()
|
||||
for path in (ROOT / 'native').rglob('*') if path.is_file())
|
||||
|
||||
|
||||
def build_snapshot(program, native: Path, cache: Path, *, required_sources=()):
|
||||
"""Build exact snapshot sources and verify the modified files were compiled.
|
||||
|
||||
Historical monolithic trees retain their original set of C translation
|
||||
units. This temporary selector override is confined to the standalone
|
||||
manual process; production source selection is always restored afterwards.
|
||||
An incompatible old model/runtime ABI fails compilation explicitly.
|
||||
"""
|
||||
native = native.resolve()
|
||||
pipe = pipe_source_path(native)
|
||||
required = (pipe, *required_sources)
|
||||
old_native = builder.NATIVE
|
||||
old_selector = getattr(builder, '_runtime_sources', None)
|
||||
legacy = pipe.name == 'kernels.c'
|
||||
try:
|
||||
builder.NATIVE = native
|
||||
if legacy and old_selector is not None:
|
||||
builder._runtime_sources = lambda _: sorted(native.rglob('*.c'))
|
||||
elif not legacy and old_selector is None:
|
||||
raise ValueError('A modular snapshot requires the incremental native source selector; use its matching checkout')
|
||||
selected = (builder._runtime_sources(program) if old_selector is not None
|
||||
else sorted(native.rglob('*.c')))
|
||||
if any(path.resolve() not in {source.resolve() for source in selected} for path in required):
|
||||
raise ValueError('The model/build selector does not compile the modified pipe/RHS source; refusing a misleading run')
|
||||
try:
|
||||
build = builder.build_native(program, cache_dir=cache)
|
||||
except RuntimeError as exc:
|
||||
raise RuntimeError(
|
||||
f'Cannot build this native snapshot ({native}). Its source layout or model/runtime ABI may be incompatible; '
|
||||
'use matching compiler/runtime revisions. No benchmark was executed.'
|
||||
) from exc
|
||||
recorded = build.manifest.get('sourceHashes', {})
|
||||
for path in required:
|
||||
suffix = 'native/' + path.resolve().relative_to(native).as_posix()
|
||||
matches = [digest for name, digest in recorded.items()
|
||||
if name == suffix or name.replace('\\', '/').endswith('/' + suffix)]
|
||||
if matches != [sha256(path.read_bytes()).hexdigest()]:
|
||||
if hasattr(build, 'close'):
|
||||
build.close()
|
||||
raise ValueError(f'Build manifest does not prove the modified source was compiled: {suffix}')
|
||||
return build
|
||||
finally:
|
||||
builder.NATIVE = old_native
|
||||
if old_selector is not None:
|
||||
builder._runtime_sources = old_selector
|
||||
|
||||
|
||||
def main():
|
||||
parser=argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('input',type=Path)
|
||||
@@ -42,7 +112,8 @@ def main():
|
||||
args=parser.parse_args()
|
||||
if args.runs<1:parser.error('--runs must be positive')
|
||||
out=args.output_dir.resolve();out.mkdir(parents=True,exist_ok=True)
|
||||
if (out/'summary.json').exists():parser.error('Choose a fresh output directory')
|
||||
if (out/'summary.json').exists() or any((out/name).exists() for name in ('fixed-point','previous-newton','guarded-newton')):
|
||||
parser.error('Choose a fresh output directory; existing variant sources must not be mixed')
|
||||
revision=subprocess.check_output(['git','rev-parse',args.baseline_ref],cwd=ROOT,text=True).strip()
|
||||
xml,doc=load_input(args.input)
|
||||
program=compile_native_program(compile_system_xml_network(doc))
|
||||
@@ -55,16 +126,16 @@ def main():
|
||||
try:
|
||||
for variant in ('fixed-point','previous-newton','guarded-newton'):
|
||||
directory=out/variant
|
||||
for name in paths:
|
||||
variant_paths = working_native_paths() if variant == 'guarded-newton' else paths
|
||||
for name in variant_paths:
|
||||
if variant=='guarded-newton':data=(ROOT/name).read_bytes()
|
||||
else:data=subprocess.check_output(['git','show',f'{revision}:{name}'],cwd=ROOT)
|
||||
target=directory/name;target.parent.mkdir(parents=True,exist_ok=True);target.write_bytes(data)
|
||||
if variant=='fixed-point':
|
||||
target=directory/'native/components/kernels.c';source=target.read_text()
|
||||
target=pipe_source_path(directory/'native');source=target.read_text()
|
||||
if source.count(NEW_CALL)!=1:raise ValueError('Baseline pipe flow layout does not match the audited fixed-point substitution')
|
||||
target.write_text(source.replace(NEW_CALL,OLD_ITERATION))
|
||||
builder.NATIVE=directory/'native'
|
||||
variants[variant]=builder.build_native(program,cache_dir=out/'cache')
|
||||
variants[variant]=build_snapshot(program,directory/'native',out/'cache')
|
||||
finally:builder.NATIVE=original_native
|
||||
rows=[]
|
||||
for index in range(args.runs+1):
|
||||
@@ -80,7 +151,9 @@ def main():
|
||||
summary={'baselineRef':revision,'input':str(args.input.resolve()),
|
||||
'inputSha256':sha256(args.input.read_bytes()).hexdigest(),'xmlSha256':sha256(xml).hexdigest(),
|
||||
'settings':vars(config),'sampleStep':doc.simulation.sample_step,'rows':rows,
|
||||
'variants':{name:{'sourceSha256':sha256((out/name/'native/components/kernels.c').read_bytes()).hexdigest(),
|
||||
'variants':{name:{'sourceSha256':sha256(pipe_source_path(out/name/'native').read_bytes()).hexdigest(),
|
||||
'pipeSource':str(pipe_source_path(out/name/'native').relative_to(out/name)),
|
||||
'nativeSourceHashes':build.manifest['sourceHashes'],
|
||||
'buildKey':build.manifest['buildKey'],
|
||||
'medianSolveSeconds':statistics.median(row['solveSeconds'] for row in rows if row['variant']==name and row['run']>0),
|
||||
'medianProcessSeconds':statistics.median(row['processWallSeconds'] for row in rows if row['variant']==name and row['run']>0)}
|
||||
|
||||
Reference in new issue
Block a user