Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
291 changes: 289 additions & 2 deletions EXEs/cuda_mesh_state_report.cpp

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,9 @@ cuda_backend_stub_report: include/cuda/Cuda_backend.hpp \
cuda_mesh_state_report: include/cuda/Cuda_mesh_state.hpp \
include/cuda/detail/Cuda_mesh_state_core.hpp \
include/cuda/detail/Cuda_regular_geometry_cpu.hpp \
include/cuda/detail/Cuda_regular_membrane_cpu.hpp \
src/cuda/Cuda_regular_geometry_cpu.cpp \
src/cuda/Cuda_regular_membrane_cpu.cpp \
src/cuda/Cuda_mesh_state_common.cpp src/cuda/Cuda_mesh_state.cu \
EXEs/cuda_mesh_state_report.cpp
@command -v $(CUDA_NVCC) >/dev/null 2>&1 || \
Expand All @@ -364,18 +366,22 @@ cuda_mesh_state_report: include/cuda/Cuda_mesh_state.hpp \
-arch=$(CUDA_COMPUTE_ARCH) -code=$(CUDA_SM_CODE) \
-ccbin=$(CUDA_HOST_CXX) -Iinclude \
src/cuda/Cuda_regular_geometry_cpu.cpp \
src/cuda/Cuda_regular_membrane_cpu.cpp \
src/cuda/Cuda_mesh_state_common.cpp src/cuda/Cuda_mesh_state.cu \
EXEs/cuda_mesh_state_report.cpp \
-lcudart -o $(CUDA_MESH_STATE_REPORT)
@echo "Finished optional CUDA mesh-state report build, $(CUDA_MESH_STATE_REPORT)."

cuda_mesh_state_stub_report: include/cuda/Cuda_mesh_state.hpp \
include/cuda/detail/Cuda_regular_geometry_cpu.hpp \
include/cuda/detail/Cuda_regular_membrane_cpu.hpp \
src/cuda/Cuda_regular_geometry_cpu.cpp \
src/cuda/Cuda_regular_membrane_cpu.cpp \
src/cuda/Cuda_mesh_state_common.cpp src/cuda/Cuda_mesh_state_stub.cpp \
EXEs/cuda_mesh_state_report.cpp
$(CXX) -std=$(CXX_STD) -O3 -Iinclude \
src/cuda/Cuda_regular_geometry_cpu.cpp \
src/cuda/Cuda_regular_membrane_cpu.cpp \
src/cuda/Cuda_mesh_state_common.cpp src/cuda/Cuda_mesh_state_stub.cpp \
EXEs/cuda_mesh_state_report.cpp -o $(CUDA_MESH_STATE_STUB_REPORT)
@echo "Finished non-CUDA mesh-state stub report build, $(CUDA_MESH_STATE_STUB_REPORT)."
Expand Down
122 changes: 107 additions & 15 deletions analysis/cuda_mesh_state_report_rtx4050.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"allocation_epoch": 6,
"allocation_epoch": 12,
"allocation_free_balance": true,
"available": true,
"build": {
Expand Down Expand Up @@ -27,7 +27,7 @@
"compiled": true,
"cuda_required": true,
"device_ordinal": 0,
"final_allocations": 138,
"final_allocations": 384,
"final_resident_bytes": 0,
"geometry_cases": {
"boundary_ghost": {
Expand Down Expand Up @@ -94,24 +94,116 @@
"name": "NVIDIA GeForce RTX 4050 Laptop GPU"
},
"iterations": 20,
"membrane_cases": {
"boundary_ghost": {
"cpu_parity": true,
"max_abs_error": 0,
"pass": true,
"permutation_equal": true,
"recoverable": true,
"repeatable": true,
"structured_degeneracy": true
},
"curved": {
"cpu_parity": true,
"max_abs_error": 0,
"pass": true,
"permutation_equal": true,
"recoverable": true,
"repeatable": true,
"structured_degeneracy": true
},
"degenerate": {
"cpu_parity": true,
"max_abs_error": 0,
"pass": true,
"permutation_equal": true,
"recoverable": true,
"repeatable": true,
"structured_degeneracy": true
},
"natural": {
"cpu_parity": true,
"max_abs_error": 0,
"pass": true,
"permutation_equal": true,
"recoverable": true,
"repeatable": true,
"structured_degeneracy": true
},
"permuted": {
"cpu_parity": true,
"max_abs_error": 0,
"pass": true,
"permutation_equal": true,
"recoverable": true,
"repeatable": true,
"structured_degeneracy": true
},
"production_cpu": {
"cpu_parity": true,
"max_abs_error": 3.1086244689504383e-15,
"pass": true,
"permutation_equal": true,
"recoverable": true,
"repeatable": true,
"structured_degeneracy": true
}
},
"membrane_degeneracy_handled": true,
"membrane_max_abs_error": 3.1086244689504383e-15,
"membrane_repeatable": true,
"membrane_transactions": 120,
"memory_budget_bytes": 2659713024,
"no_warm_allocations": true,
"resident_bytes": 5504,
"resident_bytes": 7104,
"rollbacks": 60,
"status": "pass",
"successful_frees": 138,
"total_transactions": 120,
"transaction_epoch": 120,
"successful_frees": 384,
"total_transactions": 240,
"transaction_epoch": 240,
"transfers": {
"accepted_coordinates": {"bytes": 3456, "operations": 12},
"candidate_coordinates": {"bytes": 34560, "operations": 120},
"candidate_geometry": {"bytes": 0, "operations": 0},
"geometry_diagnostics": {"bytes": 4640, "operations": 480},
"numerical_plan": {"bytes": 12672, "operations": 18},
"parameters": {"bytes": 822, "operations": 18},
"reference_coordinates": {"bytes": 1728, "operations": 6},
"topology": {"bytes": 1742, "operations": 54}
"accepted_coordinates": {
"bytes": 6912,
"operations": 24
},
"candidate_coordinates": {
"bytes": 69120,
"operations": 240
},
"candidate_geometry": {
"bytes": 0,
"operations": 0
},
"candidate_membrane": {
"bytes": 0,
"operations": 0
},
"geometry_diagnostics": {
"bytes": 4640,
"operations": 480
},
"membrane_diagnostics": {
"bytes": 132160,
"operations": 1440
},
"numerical_plan": {
"bytes": 25344,
"operations": 36
},
"parameters": {
"bytes": 1644,
"operations": 36
},
"reference_coordinates": {
"bytes": 3456,
"operations": 12
},
"topology": {
"bytes": 3484,
"operations": 108
}
},
"transfers_complete": true,
"warmed_allocations": 138
"warmed_allocations": 384
}
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,21 @@ remains subject to the required pull-request review and owner merge approval.
Exit evidence: per-sample, per-face, per-occurrence, energy, curvature, and
normal parity against the actual CPU formula.

Implementation status (2026-08-03):
`codex/cuda-step5-regular-membrane-formula` implements the complete regular
bending, global-area-constraint, and global-volume-constraint sample algebra
as a candidate-only device operation. It consumes all seven packed weighted
rows and emits sample surface measures/curvatures/normals/bending energies,
face geometry/energy/curvature/unit normals, and canonical 12x9
per-occurrence force contributions. An independent packed CPU oracle is bound
directly to `Mesh::element_energy_force_regular()` for every face observable
and force component on a curved production mesh. The native RTX report covers
the six frozen fixtures for 20 repeats, including source-order permutation and
structured degenerate-sample recovery, without warmed allocations. Scatter,
vertex-force writes, `Mesh` publication, and production routing remain outside
this slice. Final status remains subject to pull-request review and owner merge
approval.

### Step 6 / PR 6: Deterministic source-keyed scatter

- Implement the reviewed incidence-based, fixed-order reduction into nine
Expand Down
64 changes: 47 additions & 17 deletions docs/cuda_mesh_state.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Persistent CUDA Mesh State, Transactions, And Geometry
# Persistent CUDA Mesh State, Geometry, And Regular Membrane Candidates

This document covers Steps 3 and 4 of the end-to-end CUDA residency program.
This document covers Steps 3 through 5 of the end-to-end CUDA residency program.
Step 3 added persistent storage and transaction control. Step 4 adds only the
eligible regular-face area/volume calculation and deterministic global
area/volume reductions. There is still no membrane-force formula, force
scatter, evaluator routing, or host `Mesh` publication.
area/volume reductions. Step 5 adds the complete regular membrane formula into
candidate buffers. There is still no force scatter, evaluator routing, or host
`Mesh` publication.

## Authority and ownership

Expand All @@ -14,8 +15,8 @@ translation unit; ordinary builds discover the structured non-CUDA stub.
Accepted host state remains authoritative until later routing steps.

The persistent groups are topology/incidence, numerical plan, parameters,
accepted/previous/candidate coordinates, reference coordinates, and candidate
geometry/status buffers. Every
accepted/previous/candidate coordinates, reference coordinates, candidate
geometry/status buffers, and membrane diagnostic/output buffers. Every
group is keyed by the corresponding `MeshPackGenerations` value. Equal
generations cause no allocation, copy, or synchronization. A changed group is
allocated geometrically, copied into staging, synchronized, and installed only
Expand Down Expand Up @@ -66,6 +67,26 @@ The second expression intentionally retains the existing legacy first-
component `dot_row` behavior. A device status rejects invalid indices or
nonfinite results before the candidate becomes validated.

`compute_candidate_membrane()` is an alternative candidate operation from
`CandidatePrepared`. It consumes all seven weighted rows and the packed
per-face spontaneous curvature plus global bending/area/volume parameters. It
emits, without scatter:

- per-sample surface measure, mean curvature, unit normal, and bending energy;
- per-face area, legacy volume, bending energy, integrated mean curvature, and
normalized face normal; and
- 12 occurrences x 9 components ordered as bending xyz, area xyz, volume xyz.

The device formula follows `Mesh::element_energy_force_regular()` including
the current half-quadrature convention, dual-basis derivatives, bending
gradient matrices, and global constraint factors. A structured status records
the first invalid source, degenerate sample, nonfinite intermediate, or
nonfinite output together with evaluated-face and sample indices. Such a
candidate enters `Failed`; `recover()` returns to the unchanged accepted state.
Unlike Step 4 geometry, a zero surface measure is invalid for Step 5 because
the force formula requires its inverse. No source incidence plan is consumed
and no vertex-indexed force buffer is written.

Commit rotates candidate into accepted, accepted into previous, and the old
previous slot into reusable candidate storage while advancing the accepted
coordinate generation without a mesh-sized copy. Rollback from any live
Expand All @@ -78,10 +99,10 @@ searches; it is not hidden or misclassified here.

Each transfer records attempted/completed operation and byte counts under a
stable reason: topology, numerical plan, parameters, accepted coordinates,
reference coordinates, candidate coordinates, candidate geometry storage, or
geometry diagnostics. Step 4 copies face/global outputs to the host only for
the explicit comparison API and report; those mesh-sized diagnostic copies are
classified and are not a production route. Allocation and
reference coordinates, candidate coordinates, candidate geometry or membrane
storage, and geometry or membrane diagnostics. Steps 4 and 5 copy outputs to
the host only for their explicit comparison APIs and reports; those diagnostic
copies are classified and are not a production route. Allocation and
transaction epochs, live bytes, allocation/free counts, synchronizations,
roles, generations, and the last outcome are also reportable.
`lastDirtyGroups` is reset at the start of each candidate-upload decision. A
Expand All @@ -107,7 +128,11 @@ curved production regular mesh at the `1.0e-12` gate. Injected kernel,
diagnostic-copy, and synchronization
failures and injected nonzero status, nonfinite face output, negative area, or
nonfinite totals remain recoverable without validating or changing accepted
state. The focused state suite passes 27/27 tests.
state. Step 5 additionally rejects injected kernel, diagnostic-copy,
synchronization, status, nonfinite-force, and zero-surface failures while
preserving accepted bytes and recoverability. Its independent packed CPU
oracle is compared directly with the production regular formula at the
per-face and per-occurrence levels.

The explicit native proof builds and runs with:

Expand All @@ -118,16 +143,21 @@ python3 scripts/run_cuda_mesh_state_report.py \

The native report executes the natural, permuted, sample-varying curved,
boundary/ghost, degenerate, and production-formula CPU-oracle fixtures on the
actual CUDA kernel. Each case runs 20 candidate geometry transactions and has
separate parity, structural, and bitwise-repeatability fields; the runner
rejects a report with any missing or false case field. The aggregate requires
`geometry_max_abs_error <= 1.0e-12` plus bitwise repeatability. It also closes
actual CUDA kernels. Each case runs 20 geometry and 20 membrane candidate
transactions. Membrane evidence binds every sample diagnostic, face
observable, and 12x9 occurrence contribution; the degenerate case must report
the structured failure and recover on every repeat. The runner rejects a
report with any missing or false case field. The aggregate requires both
geometry and membrane maximum error at or below `1.0e-12` plus bitwise
repeatability. It also closes
explicitly before declaring success and requires `Closed`, zero cleanup debt,
zero final resident bytes, and exact allocation/free balance. Geometry parity,
repeatability, and teardown are therefore part of the RTX pass predicate, not
informational fields or destructor side effects after reporting. The recorded
RTX proof covers 120 transactions with maximum error
`1.3877787807814457e-17`, no warmed allocations, and 138/138 balanced frees.
RTX proof covers 240 transactions. Its membrane maximum absolute error is
`3.1086244689504383e-15`; geometry remains
`1.3877787807814457e-17`. It has no warmed allocations and exact allocation/
free balance.

The non-CUDA contract is independently runnable with `--stub`. Native evidence
for the development RTX machine is recorded in
Expand Down
38 changes: 38 additions & 0 deletions include/cuda/Cuda_mesh_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ enum class TransferReason : std::size_t
CandidateCoordinates,
CandidateGeometry,
GeometryDiagnostics,
CandidateMembrane,
MembraneDiagnostics,
Count,
};

Expand Down Expand Up @@ -142,6 +144,41 @@ struct GeometryCandidateResult
bool ok() const noexcept { return error.ok(); }
};

enum class MembraneStatusCode : std::int32_t
{
None = 0,
InvalidSource = 1,
DegenerateSample = 2,
NonFiniteIntermediate = 3,
NonFiniteOutput = 4,
};

struct MembraneCandidateResult
{
std::vector<double> faceAreas;
std::vector<double> faceVolumes;
std::vector<double> faceBendingEnergies;
std::vector<double> faceMeanCurvatures;
std::vector<double> faceNormals;
std::vector<double> occurrenceForces;
std::vector<double> sampleSurfaceMeasures;
std::vector<double> sampleMeanCurvatures;
std::vector<double> sampleNormals;
std::vector<double> sampleBendingEnergies;
double totalArea = 0.0;
double totalVolume = 0.0;
std::uint64_t coordinateGeneration = 0;
MembraneStatusCode status = MembraneStatusCode::None;
std::uint64_t failedEvaluatedFace = 0;
std::uint32_t failedSample = 0;
DeviceStateError error;

bool ok() const noexcept
{
return error.ok() && status == MembraneStatusCode::None;
}
};

struct CudaMeshStateResult;

class CudaMeshState final
Expand All @@ -158,6 +195,7 @@ class CudaMeshState final
const std::vector<double> &coordinates,
std::uint64_t generation);
GeometryCandidateResult compute_candidate_geometry();
MembraneCandidateResult compute_candidate_membrane();
DeviceStateError mark_computing();
DeviceStateError mark_validated();
DeviceStateError commit();
Expand Down
Loading