Commit 27e5139b authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: rung A - debug-save fetches last-cycle-only + own profile stage

Design 3-A4i rung A (2026-07-16 handoff): the 00:25:48 gate profile's
'leanMeasure other' (26.1 ms/call, 43% of post) was unprofiled debug-save
data motion (pose_corr_save/pose_img_save). Changes:
- leanFitScene passes corr_pd_out/img_out only on the LAST outer cycle in
  fixed-cycle mode (legacy convergence mode keeps every-cycle so an early
  exit still fills the holders).
- New DEBUG_FETCH profile stage wraps perSensorImagesFromTD, the no-MB
  debug re-convert, and fetchNormalizedPD, so debug data motion can never
  hide in 'leanMeasure other' again (it joins measureAccounted).
Armed pose_corr capture unaffected (fetch keyed on isArmed() unchanged).
Expected gate: poses/records byte-exact, hyperstacks identical, capacity
~3.9 -> ~5.5 scenes/s in the debug config.
Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
parent 13db0146
......@@ -222,13 +222,14 @@ public class CuasPoseRT {
static final int DEBIAS_UPLOAD = 12;
static final int PEAK_D2H = 13;
static final int PEAK_UNPACK = 14;
static final int MEASURE_OTHER = 15;
static final int LMA_PREPARE = 16;
static final int LMA_RUN = 17;
static final int LMA_GPU_PRODUCTS = 18;
static final int LMA_CPU_REMAINDER = 19;
static final int POSE_UPDATE = 20;
static final int NUM_STAGES = 21;
static final int DEBUG_FETCH = 15; // debug-save data motion (PD/composite), own stage so it can never hide in "other" (rung A) // By Claude on 07/16/2026
static final int MEASURE_OTHER = 16;
static final int LMA_PREPARE = 17;
static final int LMA_RUN = 18;
static final int LMA_GPU_PRODUCTS = 19;
static final int LMA_CPU_REMAINDER = 20;
static final int POSE_UPDATE = 21;
static final int NUM_STAGES = 22;
static final String [] LABELS = {
"post-conditioning total",
" motion-blur setup",
......@@ -245,6 +246,7 @@ public class CuasPoseRT {
" de-bias map upload/clear",
" peak kernel+D2H",
" peak unpack (Java)",
" debug-save fetch (PD+img)", // By Claude on 07/16/2026
" leanMeasure other",
" LMA prepare (CPU)",
" LMA run total",
......@@ -672,14 +674,17 @@ public class CuasPoseRT {
0, // sensor_mask_inter = 0: convert only, return before correlate
ImageDtt.THREADS_MAX,
debugLevel);
if (rtProfile != null) measureAccounted += rtProfile.addElapsed(RtPoseProfile.CONVERT_GEOMETRY, profileStart);
// DEBUG (img_out): re-convert with erase_clt=1 so non-task tiles are NaN (interCorrTD
// converts with erase=-1, leaving the PREVIOUS scene's tiles outside the selection -
// harmless for correlation, ghosts in a render). Same LPFs/tasks/offsets - identical
// task-tile content, only the background differs. By Claude on 07/04/2026.
// Timed as DEBUG_FETCH, not CONVERT_GEOMETRY (rung A). By Claude on 07/16/2026.
if (img_out != null) {
profileStart = (rtProfile != null) ? rtProfile.start() : 0L;
gpuQuad.execConvertDirect(false, null, 1);
if (rtProfile != null) measureAccounted += rtProfile.addElapsed(RtPoseProfile.DEBUG_FETCH, profileStart);
}
if (rtProfile != null) measureAccounted += rtProfile.addElapsed(RtPoseProfile.CONVERT_GEOMETRY, profileStart);
resident_tasks = false;
}
// 3. the consolidation bridge: GPU v1 chain (JNA backend, on-device, OOB-filtered)
......@@ -707,9 +712,14 @@ public class CuasPoseRT {
else CuasTD.consolidateToSlot0(gpuQuad, cons_tasks, // By Claude on 07/12/2026
clt_parameters.curt.oob_soft, clt_parameters.curt.oob_hard);
if (rtProfile != null) measureAccounted += rtProfile.addElapsed(RtPoseProfile.CONSOLIDATE, profileStart);
// DEBUG (img_out): render the composite the correlator sees (the weighted average)
// DEBUG (img_out): render the composite the correlator sees (the weighted average).
// Timed as DEBUG_FETCH: debug-save data motion, ~20-24 ms/call in the 00:25:48
// profile, was hiding in "leanMeasure other" (rung A, design 2026-07-16).
// By Claude on 07/16/2026.
if (img_out != null) {
profileStart = (rtProfile != null) ? rtProfile.start() : 0L;
img_out[0] = com.elphel.imagej.cuas.CuasMotion.perSensorImagesFromTD(gpuQuad, false)[0];
if (rtProfile != null) measureAccounted += rtProfile.addElapsed(RtPoseProfile.DEBUG_FETCH, profileStart);
}
// 4. single conj-multiply: only sensor 0 (holding the average) vs the center ref
final double [] col_weights = scene.isMonochrome() ?
......@@ -781,10 +791,13 @@ public class CuasPoseRT {
"recenter="+clt_parameters.curt.pose_recenter+", debias="+clt_parameters.curt.pose_debias+
") - PD stays on the GPU");
}
// PD crosses only when actually consumed
// PD crosses only when actually consumed. Timed as DEBUG_FETCH: debug-save data
// motion (~2-4 ms/call), was hiding in "leanMeasure other" (rung A). By Claude on 07/16/2026.
double [][] corr_pd = null;
if ((corr_pd_out != null) || PoseCorrExport.isArmed()) {
profileStart = (rtProfile != null) ? rtProfile.start() : 0L;
corr_pd = TDCorrTile.fetchNormalizedPD(gpuQuad, corr_indices);
if (rtProfile != null) measureAccounted += rtProfile.addElapsed(RtPoseProfile.DEBUG_FETCH, profileStart);
if (corr_pd == null) {
System.out.println("leanMeasure(): fetchNormalizedPD returned null for scene "+scene.getImageName());
return null;
......@@ -1088,11 +1101,21 @@ public class CuasPoseRT {
clt_parameters.curt.pose_lambda : clt_parameters.ilp.ilma_lambda; // By Claude on 07/12/2026
int nlma = 0;
for (; nlma < max_cycles; nlma++) {
// Rung A (design 2026-07-16): the debug holders are documented "last cycle"
// products - with fixed cycles pass them ONLY on the last cycle (3 of 4 debug
// fetches per scene were pure overwrite waste = the bulk of the 43% "leanMeasure
// other" in the 00:25:48 profile). Legacy convergence mode (fixed_cycles==0)
// keeps every-cycle passing so an early exit still leaves the holders filled.
// By Claude on 07/16/2026.
final boolean debug_cycle = (fixed_cycles <= 0) || (nlma == (max_cycles - 1));
cm = leanMeasure(
clt_parameters, image_dtt, center_CLT, scene,
center_disparity, pXpYD_center, selection,
scene_xyzatr0[0], scene_xyzatr0[1], margin,
mb_vectors, mb_tau, mb_max_gain, corr_pd_out, img_out, debugLevel);
mb_vectors, mb_tau, mb_max_gain,
debug_cycle ? corr_pd_out : null,
debug_cycle ? img_out : null,
debugLevel);
if (cm == null) {
PoseCorrExport.sceneFailed(scene); // drop a partial pose_corr capture (armed only) // By Claude on 07/13/2026
return null;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment