Skip to content

fix(tf): initialize NVNMD map outputs - #5847

Merged
njzjz merged 5 commits into
deepmodeling:masterfrom
njzjz-bot:fix/nvnmd-map-output-contract-5655
Jul 30, 2026
Merged

fix(tf): initialize NVNMD map outputs#5847
njzjz merged 5 commits into
deepmodeling:masterfrom
njzjz-bot:fix/nvnmd-map-output-contract-5655

Conversation

@njzjz-bot

@njzjz-bot njzjz-bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • correct MapFltNvnmd's stale three-input check to its registered four-input contract
  • validate table, gradient-table, and interval metadata before dimension/index arithmetic
  • zero-fill values outside every configured interval, including the corresponding input gradient

Why existing tests missed this

test_nvnmd_op.py directly covered the other NVNMD arithmetic primitives but not MapFltNvnmd. Normal descriptor and mapping-generation callers keep values inside generated table ranges, release builds compile out the stale DCHECK, and freshly allocated output pages often happen to contain zeros. Together those conditions hid both the invalid debug contract and skipped output writes.

The regression warms a large same-shaped output with nonzero values before evaluating out-of-range inputs, making allocator reuse expose the old behavior reliably instead of depending on fresh memory contents.

Validation

  • cmake --build source/build --target deepmd_op -j2
  • fresh build-tree TensorFlow op: TestOpMapFltNvnmd (2 passed; inherited TensorFlow session helper skipped)
  • ruff format .
  • ruff check .
  • clang-format dry run with --Werror
  • git diff --check

Fixes #5655

Coding agent: Codex
Codex version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning effort: xhigh

Summary by CodeRabbit

  • Bug Fixes
    • Added strict runtime input validation (input count, tensor ranks/shapes, table width and interval metadata rules) with clear error messages.
    • Improved output initialization to avoid uninitialized results.
    • Updated interval selection to use the first matching interval (fine-to-coarse), with consistent clamping at table edges.
  • Tests
    • Added/expanded tests covering clamp behavior, “first matching interval wins,” gradient correctness, and a comprehensive set of invalid-input cases.

Correct the MapFltNvnmd four-input contract, validate its table metadata, and
zero outputs that fall outside every mapping interval. Cover deterministic
allocator reuse, gradient behavior, and malformed table-gradient shapes.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
@dosubot dosubot Bot added the bug label Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@njzjz, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 15 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 207191e6-68ed-407e-9ebc-6e2e9ffacd3a

📥 Commits

Reviewing files that changed from the base of the PR and between 41edda9 and 1f117d2.

📒 Files selected for processing (2)
  • source/op/tf/map_flt_nvnmd.cc
  • source/tests/tf/test_nvnmd_op.py
📝 Walkthrough

Walkthrough

MapFltNvnmd now validates its four-input and tensor-shape contracts, checks interval metadata, initializes outputs, selects matching intervals deterministically, clamps out-of-range values, and adds comprehensive TensorFlow tests.

Changes

MapFltNvnmd runtime behavior

Layer / File(s) Summary
Runtime validation and deterministic mapping
source/op/tf/map_flt_nvnmd.cc
Adds runtime validation for inputs, shapes, table dimensions, and interval metadata; corrects input indexing, initializes outputs, prioritizes the first matching interval, and clamps out-of-range values.
TensorFlow behavior and contract tests
source/tests/tf/test_nvnmd_op.py
Tests clamping and gradients, overlapping interval precedence, minimal valid inputs, and invalid tensor, dimension, and interval metadata cases.

Estimated code review effort: 4 (Complex) | ~45 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: NVNMD map output initialization, with the input-contract fix as supporting detail.
Linked Issues check ✅ Passed The PR fixes the stale four-input contract, validates inputs, and defines out-of-range behavior with zero-filling plus tests, matching #5655.
Out of Scope Changes check ✅ Passed The added validation and interval-handling changes are all tied to the NVNMD map fix and its regression coverage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
source/op/tf/map_flt_nvnmd.cc (1)

117-134: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Interval metadata is parsed twice (validation loop here, then again in the main ss loop below).

Correctness looks solid — n0>=0 && n1<=shT.dim_size(0) prevents the OOB table read, and dx>0/n1>n0 avoid divide-by-zero and negative clamp indices. As an optional cleanup, consider extracting a small helper (e.g. a struct Interval { x0,x1,dx; int n0,n1; } parsed once per ss) so the same five floats aren't decoded from info in two separate loops.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/op/tf/map_flt_nvnmd.cc` around lines 117 - 134, Extract the repeated
interval metadata decoding into a small reusable representation, such as an
Interval struct, and parse each five-value entry from info once per ss. Reuse
the parsed x0, x1, dx, n0, and n1 values in both the validation loop and the
main ss processing loop, preserving the existing validation and mapping
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@source/op/tf/map_flt_nvnmd.cc`:
- Around line 117-134: Extract the repeated interval metadata decoding into a
small reusable representation, such as an Interval struct, and parse each
five-value entry from info once per ss. Reuse the parsed x0, x1, dx, n0, and n1
values in both the validation loop and the main ss processing loop, preserving
the existing validation and mapping behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6ef6e5ae-b840-4092-ba06-c22e30fbfc19

📥 Commits

Reviewing files that changed from the base of the PR and between 6c3b985 and 76dc26e.

📒 Files selected for processing (2)
  • source/op/tf/map_flt_nvnmd.cc
  • source/tests/tf/test_nvnmd_op.py

@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.85106% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.97%. Comparing base (4f827cc) to head (1f117d2).

Files with missing lines Patch % Lines
source/op/tf/map_flt_nvnmd.cc 80.85% 1 Missing and 8 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5847      +/-   ##
==========================================
- Coverage   79.21%   78.97%   -0.24%     
==========================================
  Files        1069     1069              
  Lines      124070   124088      +18     
  Branches     4522     4531       +9     
==========================================
- Hits        98278    97996     -282     
- Misses      24171    24472     +301     
+ Partials     1621     1620       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@wanghan-iapcm wanghan-iapcm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch on the real defect here — the stale DCHECK_EQ(3, ...) never fired in release while the op reads input(3), and the unwritten output cells genuinely returned allocator contents. The mechanics of the fix check out: the 4-input requirement matches REGISTER_OP, every rank check precedes the corresponding dim_size() read, the std::fill covers exactly the N*D*M index space the loop writes, and the interval invariants bound the table index tightly enough that no finite x can overflow it.

Two things to resolve before this merges — one semantic, one coverage. Details inline.

Comment thread source/op/tf/map_flt_nvnmd.cc Outdated
Comment thread source/op/tf/map_flt_nvnmd.cc
njzjz-bot added 2 commits July 27, 2026 12:11
Values outside every configured interval mapped to zero, which is a
legitimate embedding output rather than a sentinel and diverges from
MapTable.mapping() in mapt.py. Select the first containing interval per
element and clamp to its nearest edge instead, keeping y continuous and
matching the numpy twin. NvnmdConfig.get_s_range() only warns when the s
range exceeds the s2g table, so this path is reachable.

Cover every OP_REQUIRES site, including each sub-condition of the
per-interval table_info check.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
source/op/tf/map_flt_nvnmd.cc (1)

168-168: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Comment says "first interval" but the clamp uses the selected interval.

id = 0 yields idx = N0 of interval ss (the fall-through one is the last interval, not the first). Suggest "left edge of the selected interval" to match the code.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/op/tf/map_flt_nvnmd.cc` at line 168, Update the comment above the
below-table evaluation in the interval-selection logic to describe evaluating at
the left edge of the selected interval, replacing the inaccurate “first
interval” wording; leave the implementation unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/op/tf/map_flt_nvnmd.cc`:
- Around line 164-179: Update the interval-selection logic preceding the shown
clamp so NaN xi values are routed into the lower-bound path rather than reaching
int(id). Invert or otherwise adjust the first interval validation condition
while preserving existing finite-value behavior, ensuring id is always a valid
table interval before indexing table.

---

Nitpick comments:
In `@source/op/tf/map_flt_nvnmd.cc`:
- Line 168: Update the comment above the below-table evaluation in the
interval-selection logic to describe evaluating at the left edge of the selected
interval, replacing the inaccurate “first interval” wording; leave the
implementation unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 838ce316-ce89-4fef-8562-71412cc68dfd

📥 Commits

Reviewing files that changed from the base of the PR and between 76dc26e and 41edda9.

📒 Files selected for processing (2)
  • source/op/tf/map_flt_nvnmd.cc
  • source/tests/tf/test_nvnmd_op.py

Comment thread source/op/tf/map_flt_nvnmd.cc
Address the outstanding requested-change review comments.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
@njzjz
njzjz requested a review from wanghan-iapcm July 30, 2026 03:40
Resolve the test-file append conflict by retaining both the NVNMD map regressions and the new master neighbor-list tests.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh

@wanghan-iapcm wanghan-iapcm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both points are resolved, and I checked them against 1f117d224 rather than the replies.

Edge-clamping was the right call. The restructured loop picks the first containing interval and lets a non-matching value fall through to the widest one, so y stays continuous across the whole real line and the closest neighbor pairs no longer lose their force contribution. Above the table it reproduces mapt.py's idx_k = N1 - 1 with dxx_k = dx; below it, the left edge is the sensible continuous analogue given numpy wraps on a negative index there. idx stays inside N0 .. N1 - 1, and since the per-interval guard enforces N1 <= rows, the table read is bounded. Good that the comment now records the get_s_range() reachability argument rather than just the mechanics.

The guard coverage is exactly what I asked for: seven subTests for the interval field conditions, dedicated tests for the rank/width/length checks, and test_accepts_the_minimal_valid_inputs as a positive control over the shared fixture so each rejection isolates one cause. The positive control was not something I raised and it is the right way to build this.

On why the original defect was invisible: the old interval-outer pass only wrote elements that matched an interval, and no test fed an out-of-range x -- but even one that did would probably have passed, since a fresh allocation reads back as zero. test_out_of_range_values_clamp_to_the_table_edge handles both halves by warming the buffer with warm_x first, so a skipped write cannot masquerade as a correct zero. That test fails on the pre-PR code and also on the intermediate zero-fill version, which is what makes it a real regression test rather than a restatement.

The NaN commit is a genuine improvement I had not asked for. Writing the test as !(id >= 0) is the correct idiom -- every comparison against NaN is false, so the negation routes it to a valid edge instead of reaching the undefined int(id) conversion -- and the comment explains precisely that.

Unrelated to this diff: docs/readthedocs.org:deepmd is failing, but the PR touches only the op and its test, so that is infrastructure rather than anything to fix here.

@njzjz
njzjz added this pull request to the merge queue Jul 30, 2026
Merged via the queue into deepmodeling:master with commit 18cbfd8 Jul 30, 2026
57 of 58 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Code scan] Initialize MapFltNvnmd outputs and fix its input contract

3 participants