优化 Jacobian 确定性复用并补充性能剖析与平台依赖文档

在单次 Jacobian 构建内按完整输入精确复用储气物性、PH 反算、密度和管路求根结果,保持原有求值副作用、差分政策与失败回退。八路模型求解 CPU 中位数减少 19.27%,循环和不循环的完整原始采样均与恢复基线一致。

增加独立的跨平台时间剖析工具,记录互斥阶段耗时、Newton/LU 统计、矩阵复用与内核复用,保存 UD00 两种工况的调查报告和机器可读汇总。

补充 Windows/Linux 运行、测试、原生编译和剖析所需依赖文档及索引,不修改依赖清单、版本锁或安装环境。

验证:8 项新增专项回归通过;2270 次完整 Jacobian 核对零差异;16 次剖析配对及预热运行保持完整数值一致。既有固定样本哈希失败和 Linux 实机验收限制见报告。
This commit is contained in:
ljz committed 2026-09-16 13:39:53 +08:00
1 parent 2b07d996cf
commit 1aac220084
26 files changed
+2293 -13

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
/* Included only by the instrumented private copy of cvode_solver.c.
* Public SUN solver ops wrap the unchanged implementations from the same
* CVODE library. No private CVODE layouts or substituted numerical kernels. */
#include <sunnonlinsol/sunnonlinsol_newton.h>
static int (*original_lu)(SUNLinearSolver,SUNMatrix);
static int (*original_solve)(SUNLinearSolver,SUNMatrix,N_Vector,N_Vector,sunrealtype);
static int (*original_newton)(SUNNonlinearSolver,N_Vector,N_Vector,N_Vector,sunrealtype,sunbooleantype,void *);
static SUNErrCode (*original_setsys)(SUNNonlinearSolver,SUNNonlinSolSysFn);
static SUNErrCode (*original_setsetup)(SUNNonlinearSolver,SUNNonlinSolLSetupFn);
static SUNNonlinSolSysFn original_residual;
static SUNNonlinSolLSetupFn original_setup;
static int profiled_lu(SUNLinearSolver ls,SUNMatrix a) {
PROFILE_SCOPE(P_LU);
int flag=original_lu(ls,a);if(flag)profile_add(C_LU_FAILURES,0,1);return flag;
}
static int profiled_solve(SUNLinearSolver ls,SUNMatrix a,N_Vector x,N_Vector b,sunrealtype tol) {
PROFILE_SCOPE(P_LSOLVE);
int flag=original_solve(ls,a,x,b,tol);if(flag)profile_add(C_SOLVE_FAILURES,0,1);return flag;
}
static int profiled_residual(N_Vector y,N_Vector f,void *mem) {
PROFILE_SCOPE(P_RESIDUAL);return original_residual(y,f,mem);
}
static int profiled_setup(sunbooleantype bad,sunbooleantype *current,void *mem) {
PROFILE_SCOPE(P_LSETUP);
long int before=0,after=0;
int first=CVodeGetNumJacEvals(mem,&before);
int flag=original_setup(bad,current,mem);
int last=CVodeGetNumJacEvals(mem,&after);
/* Count successful linear setups which actually reused the stored J.
This is unrelated to scalar/kernel memoization inside a fresh J. */
if(flag)profile_add(C_SETUP_FAILURES,0,1);
else profile_add(after==before?C_JAC_REUSES:C_JAC_REFRESHES,first||last,1);
return flag;
}
static SUNErrCode profiled_setsys(SUNNonlinearSolver nls,SUNNonlinSolSysFn fn) {
original_residual=fn;return original_setsys(nls,fn?profiled_residual:NULL);
}
static SUNErrCode profiled_setsetup(SUNNonlinearSolver nls,SUNNonlinSolLSetupFn fn) {
original_setup=fn;return original_setsetup(nls,fn?profiled_setup:NULL);
}
static int profiled_newton(SUNNonlinearSolver nls,N_Vector y0,N_Vector y,N_Vector w,
sunrealtype tol,sunbooleantype setup,void *mem) {
PROFILE_SCOPE(P_NEWTON);return original_newton(nls,y0,y,w,tol,setup,mem);
}
static SUNNonlinearSolver profile_attach_newton(N_Vector y,SUNContext ctx) {
SUNNonlinearSolver nls=SUNNonlinSol_Newton(y,ctx);
if(!nls)return NULL;
original_newton=nls->ops->solve;original_setsys=nls->ops->setsysfn;original_setsetup=nls->ops->setlsetupfn;
nls->ops->solve=profiled_newton;nls->ops->setsysfn=profiled_setsys;nls->ops->setlsetupfn=profiled_setsetup;
return nls;
}
static int profiled_cvode(void *solver,sunrealtype end,N_Vector y,sunrealtype *next,int task) {
PROFILE_SCOPE(P_CVODE);return CVode(solver,end,y,next,task);
}