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");
......
......@@ -29,6 +29,7 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.cuas.CuasMotion;
import com.elphel.imagej.gpu.GPUTileProcessor;
import com.elphel.imagej.gpu.GpuQuad;
import com.elphel.imagej.gpu.TpTask; // By Claude on 07/12/2026
import com.elphel.imagej.tileprocessor.QuadCLT;
import ij.ImagePlus;
......@@ -54,6 +55,110 @@ import ij.ImagePlus;
*/
public class CuasTD {
public static final int TD_CHUNK = 4 * GPUTileProcessor.DTT_SIZE * GPUTileProcessor.DTT_SIZE; // one CLT tile (per color)
// OOB source-coordinate priority margins (roadmap 2c, frozen spec Andrey 07/12/2026):
// depth = distance of the per-sensor tile center to the nearest source-frame edge.
// SOFT ~12 px = MCLT 24x24 support overhang (defined-but-synthetic replicated rows) ->
// deprioritize: use only when no sensor has the tile deeper. HARD ~8 px = 16x16 core
// overhang -> always skip. 0 = disabled (v0-compatible). By Claude on 07/12/2026.
public static final double OOB_SOFT_DEFAULT = 12.0;
public static final double OOB_HARD_DEFAULT = 8.0;
/**
* CPU oracle of the consolidation TILE/SENSOR selection - the contract of the
* future index_consolidate (pass 1) + OOB priority (pass 2) GPU kernels
* (roadmap 2c). Inputs mirror the kernel: TWO task sets (motion-blur pair,
* tp_tasks[1] may be null = no-MB mode - same convention as
* GpuQuad.setInterTasksMotionBlur()), sets index-matched by tile txy (looked
* up, not by array position). Per tile:
* pass 1: the tile must be present (task != 0) in EVERY provided set,
* else mask = 0 (tile dropped);
* pass 2: per sensor, depth = min over provided sets of the distance of
* the sensor's tile center (TpTask.xy) to the nearest frame edge;
* depth < hard_margin -> sensor always skipped; if any sensor has
* depth >= soft_margin only those are kept, else the hard
* survivors serve as the last resort. NaN/undefined xy -> sensor
* excluded (when filtering is enabled). Margin 0 = that tier off;
* both 0 -> all-sensor mask (v0-compatible).
* By Claude on 07/12/2026, from Andrey's design.
*
* @param tp_tasks [2][]: task set 0 (required) + MB pair set or null
* @param num_sens number of sensors (mask width, LSB = sensor 0)
* @param tilesX tile grid width (tasks may be full-grid or compacted)
* @param tilesY tile grid height
* @param width source sensor frame width, px
* @param height source sensor frame height, px
* @param soft_margin ~12.0 (support overhang), 0 = disabled
* @param hard_margin ~8.0 (core overhang), 0 = disabled
* @return int[tilesY*tilesX]: bit s set = average sensor s; 0 = tile poisoned
*/
public static int [] oobSensorMasks(
final TpTask [][] tp_tasks,
final int num_sens,
final int tilesX,
final int tilesY,
final int width,
final int height,
final double soft_margin,
final double hard_margin) {
final int num_tiles = tilesY * tilesX;
final TpTask [][] by_nt = new TpTask [2][];
for (int nset = 0; nset < 2; nset++) {
if ((tp_tasks == null) || (nset >= tp_tasks.length) || (tp_tasks[nset] == null)) continue;
by_nt[nset] = new TpTask [num_tiles];
for (TpTask t : tp_tasks[nset]) if (t != null) {
by_nt[nset][t.getTileY() * tilesX + t.getTileX()] = t;
}
}
final boolean filter = (soft_margin > 0) || (hard_margin > 0);
final int all_mask = (num_sens >= 32) ? -1 : ((1 << num_sens) - 1);
final int [] masks = new int [num_tiles];
int no_xy_tiles = 0; // tiles that could not be geometry-filtered (missing xy)
for (int nt = 0; nt < num_tiles; nt++) {
boolean present = (by_nt[0] != null) || (by_nt[1] != null);
for (int nset = 0; nset < 2; nset++) if (by_nt[nset] != null) {
final TpTask t = by_nt[nset][nt];
present &= (t != null) && (t.getTask() != 0);
}
if (!present) continue; // mask stays 0 - tile dropped (pass-1 semantics)
if (!filter) {
masks[nt] = all_mask;
continue;
}
boolean have_xy = true;
for (int nset = 0; nset < 2; nset++) if ((by_nt[nset] != null) && (by_nt[nset][nt].getXY() == null)) {
have_xy = false;
}
if (!have_xy) { // no geometry - cannot filter, pass all (warn once below)
no_xy_tiles++;
masks[nt] = all_mask;
continue;
}
int soft_mask = 0, hard_mask = 0;
for (int s = 0; s < num_sens; s++) {
double depth = Double.POSITIVE_INFINITY; // min over the provided sets: OOB in EITHER MB pass = OOB
for (int nset = 0; nset < 2; nset++) if (by_nt[nset] != null) {
final float [] xy = by_nt[nset][nt].getXY()[s];
final double d = Math.min(Math.min(xy[0], xy[1]),
Math.min((width - 1) - xy[0], (height - 1) - xy[1]));
depth = Math.min(depth, Double.isNaN(d) ? Double.NEGATIVE_INFINITY : d);
}
if ((hard_margin <= 0) || (depth >= hard_margin)) {
hard_mask |= 1 << s;
if ((soft_margin > 0) && (depth >= soft_margin)) {
soft_mask |= 1 << s;
}
}
}
// priority, not rejection: deep sensors when any exist, else the soft-zone
// survivors as the last resort; nobody above hard -> 0 = poisoned tile
masks[nt] = ((soft_margin > 0) && (soft_mask != 0)) ? soft_mask : hard_mask;
}
if (no_xy_tiles > 0) {
System.out.println("CuasTD.oobSensorMasks(): WARNING - "+no_xy_tiles+
" tiles have no per-sensor xy (geometry filter skipped for them)");
}
return masks;
}
/**
* Consolidate per-sensor TD (CLT) data into a single averaged channel:
......@@ -73,14 +178,34 @@ public class CuasTD {
public static float [] consolidateSensorsTD(
final float [][] fclt,
final int [] counts) {
return consolidateSensorsTD(fclt, counts, null, 1); // v1 with no mask == bit-exact v0 // By Claude on 07/12/2026
}
/**
* v1 (roadmap 2c): same NaN-aware consolidation gated by per-TILE sensor masks
* (see {@link #oobSensorMasks}): only sensors with their mask bit set are
* accumulated; mask 0 = whole tile poisoned (all-NaN, count 0 - the v0
* whole-tile-poison semantics, never a synthetic average). sens_masks == null
* reproduces v0 bit-exactly (identical op order). By Claude on 07/12/2026.
*
* @param sens_masks null, or int[tilesY*tilesX] per-tile sensor mask
* @param colors chunk-to-tile mapping (chunk = tile*colors + color); 1 for LWIR
*/
public static float [] consolidateSensorsTD(
final float [][] fclt,
final int [] counts,
final int [] sens_masks,
final int colors) {
final int len = fclt[0].length;
final int num_chunks = len / TD_CHUNK;
final float [] avg = new float [len];
for (int chunk = 0; chunk < num_chunks; chunk++) {
final int offs = chunk * TD_CHUNK;
final int mask = (sens_masks != null) ? sens_masks[chunk / colors] : -1; // By Claude on 07/12/2026
int n = 0;
boolean first = true;
for (int nsens = 0; nsens < fclt.length; nsens++) {
if (((mask >> nsens) & 1) == 0) continue; // sensor OOB-excluded / tile dropped // By Claude on 07/12/2026
final float [] f = fclt[nsens];
if (Float.isNaN(f[offs])) continue; // sensor does not have this tile
n++;
......@@ -175,4 +300,94 @@ public class CuasTD {
}
return max_diff;
}
// ===================== OOB oracle self-test (headless, no GPU) =====================
// java -cp target/classes:<deps> com.elphel.imagej.cuas.rt.CuasTD
// Synthetic validation of oobSensorMasks() + masked consolidateSensorsTD() against
// the frozen 2c spec BEFORE any GPU run (the CuasLogFold pattern). Exit 0 = PASS.
// By Claude on 07/12/2026.
private static int test_fails = 0;
private static void check(boolean ok, String what) {
System.out.println((ok ? "PASS: " : "FAIL: ") + what);
if (!ok) test_fails++;
}
/** task with all sensors' tile centers at the given frame-edge depths */
private static TpTask testTask(int num_sens, int tx, int ty, int width, int height, double [] depths) {
final TpTask t = new TpTask(num_sens, tx, ty);
t.task = 1; // any nonzero = active (the practical GPU contract)
final float [][] xy = new float [num_sens][2];
for (int s = 0; s < num_sens; s++) { // depth from the LEFT edge, y centered (depth-neutral)
xy[s][0] = (float) depths[s];
xy[s][1] = height / 2.0f;
}
t.xy = xy;
return t;
}
public static void main(String [] args) {
final int NS = 4, TX = 4, TY = 2, W = 640, H = 512;
final double SOFT = OOB_SOFT_DEFAULT, HARD = OOB_HARD_DEFAULT;
final int ALL = (1 << NS) - 1;
// grid tiles: 0 all-deep | 1 mixed | 2 all-soft-zone | 3 all-below-hard |
// 4 missing in MB set | 5 task==0 in set 0 | 6 NaN xy sensor | 7 absent everywhere
final TpTask [] set0 = new TpTask [7];
final TpTask [] set1 = new TpTask [6]; // no entries for tiles 4 (dropped) and 7
set0[0] = testTask(NS, 0, 0, W, H, new double [] {100, 200, 300, 400});
set0[1] = testTask(NS, 1, 0, W, H, new double [] {100, 50, 10, 5}); // deep,deep,soft,below-hard
set0[2] = testTask(NS, 2, 0, W, H, new double [] { 9, 10, 11, 11.9}); // all soft-zone
set0[3] = testTask(NS, 3, 0, W, H, new double [] { 3, 5, 0, 7.9}); // all below hard
set0[4] = testTask(NS, 0, 1, W, H, new double [] {100, 100, 100, 100});
set0[5] = testTask(NS, 1, 1, W, H, new double [] {100, 100, 100, 100});
set0[5].task = 0; // inactive in set 0
set0[6] = testTask(NS, 2, 1, W, H, new double [] {100, 100, 100, 100});
set0[6].getXY()[1][0] = Float.NaN; // sensor 1 projection undefined
for (int i = 0; i < 4; i++) { // MB pair for tiles 0-3: same geometry shifted 1 px deeper
final TpTask s = set0[i];
final double [] d = new double [NS];
for (int ss = 0; ss < NS; ss++) d[ss] = s.getXY()[ss][0] + 1;
set1[i] = testTask(NS, s.getTileX(), s.getTileY(), W, H, d);
}
// NO set-1 entry for tile 4 (0,1) - the MB-drop case
set1[4] = testTask(NS, 1, 1, W, H, new double [] {100, 100, 100, 100}); // tile 5: active here, task==0 in set 0
set1[5] = testTask(NS, 2, 1, W, H, new double [] {100, 100, 100, 100}); // tile 6: MB entry with clean xy (NaN only in set 0)
// --- masks, MB mode ---
int [] m = oobSensorMasks(new TpTask [][] {set0, set1}, NS, TX, TY, W, H, SOFT, HARD);
check(m[0] == ALL, "tile 0: all sensors deep -> full mask (got "+m[0]+")");
check(m[1] == 0b0011, "tile 1: soft tier wins, soft-zone + below-hard dropped (got "+m[1]+")");
check(m[2] == ALL, "tile 2: nobody deep -> soft-zone last resort keeps all (got "+m[2]+")");
check(m[3] == 0, "tile 3: all below hard -> poisoned (got "+m[3]+")");
check(m[4] == 0, "tile 4: missing in MB set -> dropped (got "+m[4]+")");
check(m[5] == 0, "tile 5: task==0 in set 0 -> dropped (got "+m[5]+")");
check(m[6] == (ALL & ~0b10), "tile 6: NaN xy sensor excluded (got "+m[6]+")");
check(m[7] == 0, "tile 7: absent everywhere -> 0 (got "+m[7]+")");
// --- no-MB mode (set 1 null): tile 4 comes back, tile 5 still inactive ---
m = oobSensorMasks(new TpTask [][] {set0, null}, NS, TX, TY, W, H, SOFT, HARD);
check(m[4] == ALL, "no-MB: tile 4 present again (got "+m[4]+")");
check(m[5] == 0, "no-MB: tile 5 still task==0 (got "+m[5]+")");
// --- margins disabled = v0-compatible: every present tile gets the full mask ---
m = oobSensorMasks(new TpTask [][] {set0, set1}, NS, TX, TY, W, H, 0, 0);
check((m[1] == ALL) && (m[2] == ALL) && (m[3] == ALL), "margins 0: no geometry filtering");
check(m[4] == 0, "margins 0: pass-1 MB drop still applies (got "+m[4]+")");
// --- masked consolidation: sensor s constant s+1 per present tile ---
final int num_tiles = TX * TY;
final float [][] fclt = new float [NS][num_tiles * TD_CHUNK];
for (int s = 0; s < NS; s++) java.util.Arrays.fill(fclt[s], s + 1.0f);
java.util.Arrays.fill(fclt[2], 5 * TD_CHUNK, 6 * TD_CHUNK, Float.NaN); // sensor 2 absent on tile 5
final int [] masks = new int [] {ALL, 0b0011, ALL, 0, ALL, 0b0100, ALL, 0};
final int [] counts = new int [num_tiles];
final float [] avg = consolidateSensorsTD(fclt, counts, masks, 1);
check(Math.abs(avg[0] - 2.5f) < 1e-6, "avg tile 0 = mean(1..4) = 2.5 (got "+avg[0]+")");
check(Math.abs(avg[TD_CHUNK] - 1.5f) < 1e-6, "avg tile 1 = mean(1,2) = 1.5 (got "+avg[TD_CHUNK]+")");
check(Float.isNaN(avg[3 * TD_CHUNK]) && (counts[3] == 0), "tile 3 poisoned NaN, count 0");
check(Float.isNaN(avg[5 * TD_CHUNK]) && (counts[5] == 0), "tile 5: only allowed sensor absent -> NaN, count 0");
check(counts[0] == 4 && counts[1] == 2, "counts follow allowed+present sensors");
// --- null masks == v0 bit-exact ---
final float [] v0 = consolidateSensorsTD(fclt, null);
final float [] v1 = consolidateSensorsTD(fclt, null, null, 1);
boolean same = true;
for (int i = 0; i < v0.length; i++) same &= (v0[i] == v1[i]) || (Float.isNaN(v0[i]) && Float.isNaN(v1[i]));
check(same, "null masks reproduce v0 bit-exactly");
System.out.println(test_fails == 0 ? "CuasTD OOB oracle self-test: ALL PASSED"
: "CuasTD OOB oracle self-test: " + test_fails + " FAILED");
System.exit((test_fails == 0) ? 0 : 1);
}
}
......@@ -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