feat(neighbors): support global mode-2 sparse batches - #112
Conversation
Add validated canonical global indexing for padded sparse neighbor batches across calculation, periodic, and derivative paths. Signed-off-by: Roman Zubatyuk <rzubatiuk@nvidia.com>
|
Reviewed the full diff with empirical verification on an L40S (torch 2.9.1+cu128). The design direction is right — validation-first, clean kernel generalization, good CUDA-subprocess assert testing, and the CUDA compiled mode-2 forward is clean (0 graph breaks, eager parity ~1e-5). Legacy B>1 local-index inputs are rejected loudly on every entry path; no silent-wrong path through the calculator. But one measured physics bug and several majors need fixing before merge. Blocker — Ewald/PME energies depend on the padding width. Major — shared Major — ConvSV einsum fallback can leak features across systems. The masked gather index is 0 — system 0's first real atom in the flattened layout — so the CPU/float64 branch is only correct because Major — non-finite dummy coordinates poison Ewald (NaN energy; PME/DSF unaffected). Mode 2 keeps every dummy row in the backend call, unlike mode 1 which strips them. Major — Major — validation is triplicated and measurably expensive. The identical 6-line gate is copy-pasted in Major — the parity tests cannot see the blocker. Every periodic parity test compares mode-2 against mode-2 (B=2 vs B=1); the only genuine cross-mode check is non-periodic DSF, which is immune because its parameters are explicit. Please add: mode-1 vs mode-2 Ewald/PME energy/force parity (would have caught the blocker immediately), a padding-width-invariance test (same system, N_real+1 vs N_real+8 padding), a CPU mixed-size periodic case, and a compiled mode-2 forward test asserting zero graph breaks plus eager parity. Major — breaking-change bookkeeping. The semver-breaking input contract gets a single CHANGELOG line under Also: the branch now conflicts with main ( Suggested order: fix the Ewald/PME parameter estimation first (with the parity + padding-invariance tests pinning it), then the cell expand and the compile-safe check; consolidate validation while touching those lines; rebase; relabel the changelog. |
isayev
left a comment
There was a problem hiding this comment.
The global packed mode-2 design is right and the kernel work is high quality — sentinel contract preserved, double-backward capacity fix correct, the no-host-sync regression test is exactly what this path needs. No numerical defects found. Requesting changes on five points that need to land before merge:
-
Periodic parity tests never leave mode 2.
_single_mode2_periodic_dataintests/test_mode2_periodic_backends.pybuilds a dict namedmode1but unsqueezes into a 3-D nbmat — a mode-2 singleton — and the same pattern repeats in the model/calculator/GPU parity tests, while the one pre-existing cross-mode calculator test was repurposed. A uniform mode-2 bug (shift sign, cell selection) passes the whole suite. Please add one flat mode-1 vs mode-2 anchor per backend (DSF/D3/Ewald/PME) with nonzero shifts — the flat periodic branch in_coul_nvalchemiis still there to serve as the reference. -
cutoff_coulomb/cutoff_dftd3are accepted but never consumed or checked. Mode 2 makes caller-supplied neighbor lists the only path, yet DSF still evaluates withself.dsf_rc, D3 with its smoothing radius, Ewald with its accuracy-derived cutoff. A list built with a smaller cutoff passes all structural validation and silently drops pairs — kcal/mol-scale. Consume the keys and check them against the module radii at mode-2 entry (and either validate or hard-document the s ⇒ −s edge-symmetry requirement). -
The DSF Hessian claim is untested. The FD reference in
test_global_mode2_periodic_hessian_diagonal_matches_independentdifferentiates the module energy directly, bypassingcalculate_hessian, and_periodic_fd_setuprejectsdsf— whiledocs/long_range.mdnow says DSF Hessians work. Since DSF's explicit term is autograd-detached, nothing proves its curvature isn't silently omitted. Add an absolute FD-vs-analytic test through the real calculator path, or change the table to No. -
Rebase onto current main needs care beyond the 4 textual conflicts (CHANGELOG, aev.py, calculator.py, tests/test_calculator.py). Main's AEV dispatch now gates the Warp kernel on
WARP_CUDA_AVAILABLE(CUDA torch + CPU-only warp-lang is a legal conda-forge solve); the new mode-2 branch checks only device+dtype, so a naive rebase crashes inwp.launchon those hosts. Fold the gate + one-time warning into the mode-2 d2features sub-branch, take main'skernels/__init__.pyand_init_warp_quietly()wholesale, and add main'sweightsmarker totests/test_mode2_cuda_validation.py(its subprocess loads registry weights). Full suite + GPU run after rebase —models/base.pyauto-merges cleanly over large unrelated changes, so a clean merge proves nothing. -
Hot-path validation cost. Full mode-2 validation runs in
AIMNet2Calculator.prepare_input, again inAIMNet2Base.prepare_input, and a third time in the Hessian probe — which also does a throwawayto_input_tensorsdevice transfer for every Hessian request, mode-2 or not. With the usual all-suffixes-aliased input that's hundreds of extra kernel launches per periodic MD step. Validate once per call chain, memoize by tensor identity, gate the O(B·N·M) content checks behind a trust/debug flag. Fine as a fast-follow if you prefer, but flagging it now since large-system MD is the point of this feature.
AIMNetCentral Pull Request
Description
This change adds canonical global-indexed mode-2 sparse neighbor matrices for batches containing molecules of different sizes. It lets callers supply padded batched neighbor lists while preserving correct short-range, long-range, periodic, derivative, and Hessian-vector-product behavior.
Mode-2 inputs are now validated before computation, including padded-center sentinels, per-system ownership, shift alignment, and neighbor-matrix suffix layout. This prevents invalid global indices from reaching CUDA kernels or periodic backends, where failures otherwise can be difficult to diagnose.
Type of Change
Changes Made
convert_mode2_local_to_globalfor callers migrating legacy local-index 3D matrices to the canonical global representation.Compatibility
aimnet.nbops.convert_mode2_local_to_globalbefore use.Testing
Checklist