优化 Jacobian 确定性复用并补充性能剖析与平台依赖文档
在单次 Jacobian 构建内按完整输入精确复用储气物性、PH 反算、密度和管路求根结果,保持原有求值副作用、差分政策与失败回退。八路模型求解 CPU 中位数减少 19.27%,循环和不循环的完整原始采样均与恢复基线一致。 增加独立的跨平台时间剖析工具,记录互斥阶段耗时、Newton/LU 统计、矩阵复用与内核复用,保存 UD00 两种工况的调查报告和机器可读汇总。 补充 Windows/Linux 运行、测试、原生编译和剖析所需依赖文档及索引,不修改依赖清单、版本锁或安装环境。 验证:8 项新增专项回归通过;2270 次完整 Jacobian 核对零差异;16 次剖析配对及预热运行保持完整数值一致。既有固定样本哈希失败和 Linux 实机验收限制见报告。
This commit is contained in:
1 parent
2b07d996cf
commit
1aac220084
26 files changed
+2293
-13
No files matched your search
@@ -0,0 +1,65 @@
|
||||
"""Check diagnostic scope accounting, including nested returns and goto cleanup."""
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from app.simulation.native_codegen.build import toolchain, platform_build_inputs, _command
|
||||
from tests.manual.profile_native_solver import instrument, PARTITION
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
HERE = ROOT / 'tests/manual'
|
||||
HARNESS = r'''
|
||||
#include "solver_profile.h"
|
||||
static int early(void) { PROFILE_SCOPE(P_RHS);return 7; }
|
||||
static void nested(void) {
|
||||
PROFILE_SCOPE(P_INTEGRATION);
|
||||
{ PROFILE_SCOPE(P_EVENT);if(early()==7)goto finished; }
|
||||
finished:
|
||||
profile_add(C_STEPS,0,3);
|
||||
profile_add(C_ERROR_FAILS,-1,1);
|
||||
}
|
||||
int main(void) {
|
||||
PROFILE_SCOPE(P_TOTAL);nested();profile_end(&profile_scope);profile_dump();return 0;
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
class SolverProfileTests(unittest.TestCase):
|
||||
def test_nested_early_return_and_goto_partition(self):
|
||||
compiler, sundials, _ = toolchain()
|
||||
flags, _, _, executable = platform_build_inputs(sundials)
|
||||
with tempfile.TemporaryDirectory() as name:
|
||||
directory = Path(name)
|
||||
(directory / 'harness.c').write_text(HARNESS, encoding='utf-8')
|
||||
_command([compiler, *flags, '-I', str(HERE), str(directory / 'harness.c'),
|
||||
str(HERE / 'solver_profile.c'), '-o', str(directory / executable)], log=[])
|
||||
environment = dict(os.environ, NATIVE_SOLVER_PROFILE=str(directory / 'profile.json'))
|
||||
subprocess.run([str(directory / executable)], env=environment, check=True, timeout=20)
|
||||
result = json.loads((directory / 'profile.json').read_bytes())
|
||||
scopes = result['scopes']
|
||||
self.assertEqual(result['counterErrors'], 1)
|
||||
self.assertEqual(result['counters']['accepted_steps'], 3)
|
||||
self.assertEqual(result['counters']['error_test_failures'], 0)
|
||||
for key in ('total', 'integration', 'event_detection', 'rhs'):
|
||||
self.assertEqual(scopes[key]['calls'], 1)
|
||||
self.assertEqual(set(scopes), {key for group in PARTITION.values() for key in group})
|
||||
self.assertEqual(len(scopes), sum(map(len, PARTITION.values())))
|
||||
self.assertAlmostEqual(sum(s['exclusiveSeconds'] for s in scopes.values()),
|
||||
scopes['total']['inclusiveSeconds'], places=9)
|
||||
self.assertTrue(all(s['exclusiveSeconds'] >= 0 for s in scopes.values()))
|
||||
|
||||
def test_instrumentation_rejects_missing_anchors(self):
|
||||
with tempfile.TemporaryDirectory() as name:
|
||||
directory = Path(name)
|
||||
(directory / 'include').mkdir()
|
||||
(directory / 'runtime').mkdir()
|
||||
(directory / 'runtime/common.c').write_text('/* incompatible runtime */')
|
||||
with self.assertRaisesRegex(RuntimeError, 'Cannot identify unique function'):
|
||||
instrument(directory)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user