优化 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
@@ -11,11 +11,15 @@
|
||||
#include <sunlinsol/sunlinsol_dense.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sundials/sundials_math.h>
|
||||
#ifndef MODEL_JACOBIAN_COLORED
|
||||
#define MODEL_JACOBIAN_COLORED 0
|
||||
#endif
|
||||
#ifndef MODEL_JACOBIAN_GAS_REUSE
|
||||
#define MODEL_JACOBIAN_GAS_REUSE 0
|
||||
#endif
|
||||
|
||||
typedef struct { void *solver; N_Vector scratch; } CvDense;
|
||||
static int cv_dense(void *context, double t, double *out) {
|
||||
@@ -30,6 +34,9 @@ typedef struct {
|
||||
N_Vector weights;
|
||||
SUNMatrix reference;
|
||||
int colored;
|
||||
#if MODEL_JACOBIAN_GAS_REUSE
|
||||
ModelJacobianWorkspace *jacobian_workspace;
|
||||
#endif
|
||||
} CvContext;
|
||||
static int cv_rhs(sunrealtype t, N_Vector y, N_Vector dy, void *context) {
|
||||
NativeRun *r=((CvContext *)context)->run;
|
||||
@@ -76,6 +83,28 @@ static int jac_rhs(CvContext *context, sunrealtype t, N_Vector y, N_Vector f) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MODEL_JACOBIAN_GAS_REUSE
|
||||
_Static_assert(NATIVE_JACOBIAN_STATS_COUNT==NATIVE_JACOBIAN_SCALAR_KINDS,"Jacobian counter layout must match the kernel tags");
|
||||
static int jac_rhs_reuse(CvContext *context,sunrealtype t,N_Vector y,N_Vector f) {
|
||||
if(!context->jacobian_workspace)return jac_rhs(context,t,y,f);
|
||||
NativeRun *r=context->run;
|
||||
if(!native_poll(r,r->final_time))return -1;
|
||||
r->jacobian_rhs++;r->nfev++;
|
||||
ModelJacobianWorkspace *workspace=context->jacobian_workspace;
|
||||
NativeJacobianGasStats before=workspace->stats;
|
||||
NativeJacobianScalars scalar_before=workspace->scalars;
|
||||
double outputs[NOUTPUTS];
|
||||
int ok=model_eval_jacobian_reuse(t,N_VGetArrayPointer(y),N_VGetArrayPointer(f),outputs,workspace);
|
||||
r->jacobian_gas_evaluations+=workspace->stats.evaluations-before.evaluations;
|
||||
r->jacobian_gas_reuses+=workspace->stats.reuses-before.reuses;
|
||||
for(int i=0;i<NATIVE_JACOBIAN_SCALAR_KINDS;i++) {
|
||||
r->jacobian_scalar_evaluations[i]+=workspace->scalars.evaluations[i]-scalar_before.evaluations[i];
|
||||
r->jacobian_scalar_reuses[i]+=workspace->scalars.reuses[i]-scalar_before.reuses[i];
|
||||
}
|
||||
return ok?0:1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Same perturbation and reciprocal-multiply order as SUNDIALS 7.4 dense DQ.
|
||||
* No constraints are set by this runtime. If that changes, carry their vector
|
||||
* into this context and apply CVODE's sign rule before enabling coloring. */
|
||||
@@ -119,7 +148,11 @@ static int colored_difference(CvContext *context, sunrealtype t, N_Vector y, N_V
|
||||
for (int color=0;color<MODEL_JACOBIAN_COLOR_COUNT;color++) {
|
||||
memcpy(test,state,NSTATES*sizeof(double));
|
||||
for (int j=0;j<NSTATES;j++) if (model_jacobian_column_color[j]==color) test[j]+=increments[j];
|
||||
#if MODEL_JACOBIAN_GAS_REUSE
|
||||
int flag=jac_rhs_reuse(context,t,trial,ftrial);
|
||||
#else
|
||||
int flag=jac_rhs(context,t,trial,ftrial);
|
||||
#endif
|
||||
if (flag) return flag;
|
||||
for (int j=0;j<NSTATES;j++) if (model_jacobian_column_color[j]==color) {
|
||||
double inverse=1.0/increments[j];
|
||||
@@ -146,7 +179,16 @@ static int cv_jacobian(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix matrix,
|
||||
/* The CVODE fy belongs to the ordinary RHS cache path. Recompute the
|
||||
baseline using the same deterministic path as every perturbed probe;
|
||||
mixing the two baselines would amplify cache roundoff by 1/increment. */
|
||||
#if MODEL_JACOBIAN_GAS_REUSE
|
||||
/* The baseline belongs only to this refresh. Events, later Newton
|
||||
iterations and another run must never inherit any of these entries. */
|
||||
if(context->colored) {
|
||||
if(context->jacobian_workspace)model_jacobian_begin(context->jacobian_workspace);
|
||||
flag=jac_rhs_reuse(context,t,y,tmp3);
|
||||
} else flag=jac_rhs(context,t,y,tmp3);
|
||||
#else
|
||||
flag=jac_rhs(context,t,y,tmp3);
|
||||
#endif
|
||||
if (flag) return flag;
|
||||
fy=tmp3;
|
||||
#endif
|
||||
@@ -245,6 +287,11 @@ int native_bdf(NativeRun *r) {
|
||||
CV_CHECK(CVodeSetMaxStep(solver,r->options.max_step));
|
||||
#if MODEL_JACOBIAN_COLORED
|
||||
if (valid_coloring()) {
|
||||
#if MODEL_JACOBIAN_GAS_REUSE
|
||||
/* Optional, caller-owned scratch. Allocation failure keeps the
|
||||
original canonical differences; large models do not grow stack. */
|
||||
context.jacobian_workspace=malloc(sizeof(*context.jacobian_workspace));
|
||||
#endif
|
||||
context.weights=N_VClone(y);
|
||||
allocation="N_VClone";
|
||||
if (!context.weights) goto allocation_failure;
|
||||
@@ -339,6 +386,9 @@ int native_bdf(NativeRun *r) {
|
||||
allocation_failure:
|
||||
native_fail(r,"allocation-failure",allocation,"Cannot allocate native solver resources.");
|
||||
cleanup:
|
||||
#if MODEL_JACOBIAN_GAS_REUSE
|
||||
free(context.jacobian_workspace);
|
||||
#endif
|
||||
if (initialized) cv_snapshot(r,solver);
|
||||
if (solver) { counters(r,solver); CVodeFree(&solver); }
|
||||
if (context.reference) SUNMatDestroy(context.reference);
|
||||
|
||||
@@ -52,6 +52,12 @@ static int write_result(NativeRun *r, const char *path, const char *index_path)
|
||||
json_string(f,r->status==0?"completed":r->status==1?"cancelled":"failed");
|
||||
fprintf(f,",\"message\":"); json_string(f,r->message);
|
||||
fprintf(f,",\"propertyWarnings\":"); native_property_warnings_json(r,f);
|
||||
fprintf(f,",\"jacobianReuse\":{\"gasEvaluations\":%lu,\"gasReuses\":%lu",
|
||||
r->jacobian_gas_evaluations,r->jacobian_gas_reuses);
|
||||
const char *reuse_names[]={"ph","density","pipe"};
|
||||
for(int i=0;i<NATIVE_JACOBIAN_SCALAR_KINDS;i++)
|
||||
fprintf(f,",\"%sEvaluations\":%lu,\"%sReuses\":%lu",reuse_names[i],r->jacobian_scalar_evaluations[i],reuse_names[i],r->jacobian_scalar_reuses[i]);
|
||||
fputc('}',f);
|
||||
fprintf(f,",\"solverControl\":{\"reason\":"); json_string(f,r->failure_reason?r->failure_reason:"");
|
||||
fprintf(f,",\"operation\":"); json_string(f,r->failure_operation?r->failure_operation:"");
|
||||
fprintf(f,",\"returnCode\":%d,\"sameTimeReturns\":%lu,\"maxSameTimeStreak\":%lu",
|
||||
|
||||
Reference in new issue
Block a user