Commit eab1660e authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: avg_td_oob CPU oracle (2c OOB priority) + export + dropdown entry

CuasTD.oobSensorMasks() = the contract oracle of the future
index_consolidate (pass 1) + OOB priority (pass 2) kernels: input
TpTask[2][] (MB pair, [1] may be null = no-MB, matching
setInterTasksMotionBlur), sets matched by txy lookup; per tile - present
(task!=0) in EVERY provided set, else mask 0; per sensor - depth = min
over sets of tile-center distance to nearest frame edge; depth<hard
always skipped, any sensor >=soft -> only those, else hard survivors as
last resort; NaN xy excluded; margins 0 = tier off (frozen spec
soft~12/hard~8 @4e0db8b).
consolidateSensorsTD(fclt,counts,masks,colors): mask-gated average,
mask 0 = whole-tile NaN poison; null masks = bit-exact v0 (2-arg
delegates).
AvgTdExport.exportOob(): case carries RAW flattened task streams (exact
GPU struct layout, both sets) + margins in manifest + expected masks/
avg/counts.
KERNEL_TESTS += avg_td_oob; CuasRT.kernelTest case (set 1 = null until
the RT-chain MB wiring).
Headless self-test (java -cp ... cuas.rt.CuasTD): 18/18 PASSED
(tiering, MB drop, no-MB mode, NaN xy, poison, v0 bit-exact repro).
mvn -DskipTests clean package: OK.
Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
parent 189b7f39
......@@ -458,6 +458,23 @@ public class CuasRT {
CuasTD.validateConsolidation(gpuQuad, master_CLT, debugLevel); // imclt-linearity check + counts stats
break;
}
case "avg_td_oob": {
// clt_average_sensors v1 (roadmap 2c): OOB source-coordinate priority.
// Same conversion as avg_td; tasks handed over in the [2][] shape of the
// future index_consolidate contract (set 1 = MB pair, null here - the
// calibration-grid convert is single-pass; the real MB-pair export comes
// with the RT-chain wiring). Soft/hard margins travel in the manifest
// (frozen spec @ROADMAP 2c). By Claude on 07/12/2026.
final TpTask [][] tasks_out = new TpTask [1][];
if (!CuasMotion.convertFromData(clt_parameters, gpuQuad, phys.getOrigImageData(),
"-KERNEL-TEST-AVG-TD-OOB", tasks_out, ImageDtt.THREADS_MAX, debugLevel)) {
return;
}
AvgTdExport.exportOob(gpuQuad, false, new TpTask [][] {tasks_out[0], null},
CuasTD.OOB_SOFT_DEFAULT, CuasTD.OOB_HARD_DEFAULT,
dir_path, phys.getImageName(), debugLevel);
break;
}
default:
System.out.println("kernelTest(): unknown kernel test '"+kernel+
"' - update CuasRT.kernelTest() to match CuasRtParameters.KERNEL_TESTS");
......
......@@ -120,6 +120,105 @@ public class AvgTdExport {
}
}
/**
* Export a standalone test case for the clt_average_sensors v1 chain
* (roadmap 2c): index_consolidate (MB-pair tile selection) + OOB soft/hard
* priority + masked consolidation. The case carries the RAW flattened task
* streams (exact GPU struct layout, TpTask.asFloatArray) for BOTH motion-blur
* sets so the CUDA test exercises the real two-set indexing path, plus the
* CPU-oracle outputs: per-tile sensor masks (CuasTD.oobSensorMasks), the
* masked TD average and counts. Margins travel in the manifest (cases
* self-describing - frozen spec). By Claude on 07/12/2026.
*
* @param gpuQuad GPU instance with a current per-sensor TD
* @param use_ref use the reference-scene TD buffers
* @param tp_tasks [2][]: task set 0 (required) + MB pair set (tp_tasks[1]
* may be null = no-MB mode, same as setInterTasksMotionBlur)
* @param soft_margin OOB soft margin, px (~12.0; 0 = disabled)
* @param hard_margin OOB hard margin, px (~8.0; 0 = disabled)
* @param dir_path test-case directory, e.g. <model>/testdata/avg_td_oob
* @param comment provenance line (scene timestamp etc.)
* @param debugLevel debug level
* @return dir_path on success
*/
public static String exportOob(
GpuQuad gpuQuad,
boolean use_ref,
TpTask [][] tp_tasks,
double soft_margin,
double hard_margin,
String dir_path,
String comment,
int debugLevel) throws IOException {
final int dtt = GPUTileProcessor.DTT_SIZE;
final int [] wh = gpuQuad.getWH(use_ref);
final int tilesX = wh[0] / dtt;
final int tilesY = wh[1] / dtt;
final int colors = gpuQuad.num_colors;
final int num_sens = gpuQuad.num_cams;
final int num_tiles = tilesY * tilesX * colors;
final float [][] fclt = gpuQuad.getCltData(use_ref);
final int chunk = CuasTD.TD_CHUNK;
if (fclt[0].length != (num_tiles * chunk)) {
throw new IllegalStateException("AvgTdExport.exportOob: CLT length " + fclt[0].length +
" != tiles " + num_tiles + " * " + chunk);
}
// CPU oracle: pass-1 (MB-pair presence) + pass-2 (OOB priority) masks, then
// the masked NaN-aware average
final int [] masks = CuasTD.oobSensorMasks(
tp_tasks, num_sens, tilesX, tilesY, wh[0], wh[1], soft_margin, hard_margin);
final int [] counts = new int [num_tiles];
final float [] avg = CuasTD.consolidateSensorsTD(fclt, counts, masks, colors);
final float [] fcounts = new float [num_tiles];
for (int i = 0; i < num_tiles; i++) fcounts[i] = counts[i];
int n_full = 0, n_partial = 0, n_poison = 0;
final int all_mask = (1 << num_sens) - 1;
for (int m : masks) {
if (m == 0) n_poison++;
else if (m == all_mask) n_full++;
else n_partial++;
}
final float [] td_sens = new float [num_sens * num_tiles * chunk];
for (int nsens = 0; nsens < num_sens; nsens++) {
System.arraycopy(fclt[nsens], 0, td_sens, nsens * num_tiles * chunk, num_tiles * chunk);
}
try (TestDataWriter tdw = new TestDataWriter(dir_path, "avg_td_oob test case: " + comment)) {
tdw.prm("num_sensors", num_sens);
tdw.prm("tilesx", tilesX);
tdw.prm("tilesy", tilesY);
tdw.prm("colors", colors);
tdw.prm("img_width", wh[0]);
tdw.prm("img_height", wh[1]);
tdw.prm("soft_margin", soft_margin);
tdw.prm("hard_margin", hard_margin);
tdw.prm("has_mb", ((tp_tasks.length > 1) && (tp_tasks[1] != null)) ? 1 : 0);
tdw.buf("td_sens", td_sens, num_sens, tilesY, tilesX, colors, chunk);
for (int nset = 0; nset < 2; nset++) { // raw task streams, exact GPU layout
if ((nset >= tp_tasks.length) || (tp_tasks[nset] == null)) continue;
final TpTask [] tasks = tp_tasks[nset];
final int task_size = tasks[0].getSize();
final float [] ftasks = new float [tasks.length * task_size];
for (int i = 0; i < tasks.length; i++) {
tasks[i].asFloatArray(ftasks, i, false);
}
tdw.prm("task_size", task_size);
tdw.buf("ftasks" + nset, ftasks, tasks.length, task_size);
}
tdw.buf("expected_sens_masks", masks, tilesY, tilesX);
tdw.buf("expected_td_avg", avg, tilesY, tilesX, colors, chunk);
tdw.buf("expected_counts", fcounts, num_tiles);
if (debugLevel > -2) {
System.out.println("AvgTdExport.exportOob: wrote " + tdw.getDir() +
" (" + num_sens + " sensors, " + tilesY + "x" + tilesX + "x" + colors +
" tiles, soft/hard=" + soft_margin + "/" + hard_margin +
", masks: " + n_full + " full, " + n_partial + " partial, " +
n_poison + " poisoned)");
}
return tdw.getDir();
}
}
/**
* Import the C++ test results back and compare against the oracle
* reference stored in the same test-case directory (Java-side round-trip
......
......@@ -30,7 +30,7 @@ public class CuasRtParameters {
public boolean rend_test = false; // RT full-render product (CuasRender.testRenderSequence): per scene raw /jp4/ -> conditionSceneToGpu -> virtual-grid render at BORROWED stored pose+ERS rates -> -CUAS-RT-RENDER hyperstack [s00..s15, merged][scenes], comparable to -CUAS-INDIVIDUAL/MERGED-CUAS-DBG. NON-exclusive: runs AFTER the pose stage when both are ON (the pose stage is part of the RT cycle - Andrey 07/06/2026). // By Claude on 07/05/2026
public boolean log_test = false; // LoG A/B with the RT render (CuasRender): also save -CUAS-RT-RENDER-LOG-ORACLE (product convolved with the EXISTING pre-DNN pixel LoG, LINEAR alpha=1) and -CUAS-RT-RENDER-LOG-FOLDED (same render, LoG folded into the GPU aberration kernels via CuasLogFold - no pixel convolution; originals restored). The aberration+LoG kernel-fold validation (RT-seed step 1b). // By Claude on 07/06/2026
public boolean log_ident = false; // LoG ISOLATION test with the RT render (CuasRender): render with IDENTITY kernels (-CUAS-RT-RENDER-ID, aberrations skipped), pixel-LoG it (-ID-LOG-ORACLE), and render with PURE-LoG kernels (-LOG-ONLY). If -LOG-ONLY vs -ID-LOG-ORACLE residual persists, the fold/L0 is wrong; if it collapses to the wrap floor, the aberration-kernel interaction was responsible (Andrey 07/06/2026). // By Claude on 07/06/2026
public static final String[] KERNEL_TESTS = {"none", "avg_td"}; // GPU-kernel test registry: one dropdown entry per CUDA kernel under oracle validation (roadmap kernel ladder); add one name here + one case in CuasRT.kernelTest() per new kernel. // By Claude on 07/12/2026
public static final String[] KERNEL_TESTS = {"none", "avg_td", "avg_td_oob"}; // GPU-kernel test registry: one dropdown entry per CUDA kernel under oracle validation (roadmap kernel ladder); add one name here + one case in CuasRT.kernelTest() per new kernel. // By Claude on 07/12/2026
public String kernel_test = KERNEL_TESTS[0]; // GPU-kernel test to run this pass (EXCLUSIVE diagnostic, ONE kernel per Java run - Andrey 07/12/2026): run the kernel's CPU oracle on live GPU data and export a self-describing testdata case for the standalone NSight-debuggable CUDA test (tile_processor_gpu tests_bin/test_<kernel> --data <case> --tol 0). "none" = normal operation. // By Claude on 07/12/2026
public boolean show_kernels = false; // show selected convolution kernel
public boolean dbg_fpixels = true; // save the ORACLE debug renders during ingest (prepareFpixels): -CUAS-INDIVIDUAL-CUAS-DBG (an EXTRA per-sensor render pass, ~11GB) + -CUAS-MERGED-CUAS-DBG (save only - the merged render is the production input regardless). Was hardcoded. Turn OFF to save the render time and disk once the RT chain (-CUAS-RT-RENDER) is the trusted full render. // By Claude on 07/05/2026
......
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