Skip to content

feat(dpmodel): add adaptive Array API neighbor search#5889

Open
njzjz wants to merge 12 commits into
deepmodeling:masterfrom
njzjz:feat/adaptive-array-api-neighbor-list
Open

feat(dpmodel): add adaptive Array API neighbor search#5889
njzjz wants to merge 12 commits into
deepmodeling:masterfrom
njzjz:feat/adaptive-array-api-neighbor-list

Conversation

@njzjz

@njzjz njzjz commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

  • replace the default unconditional all-pairs neighbor search with an adaptive dense/cell-list dispatcher
  • keep the historical dense path for backend-specific small-system fast paths
  • implement compact Cartesian candidate generation with Array API operations for NumPy, PyTorch, eager JAX, TensorFlow graph mode, and Array API strict
  • reduce eager candidate selection from three global stable sorts plus a final scatter to two padded per-center stable sorts
  • retain compact sorting for traced execution, JAX accelerators, and imbalanced candidate distributions where padding or host shape extraction would regress performance
  • restrict automatic cell-list dispatch to validated NumPy CPU, PyTorch CPU/CUDA, JAX CPU/GPU, and TensorFlow CPU/GPU paths
  • treat unknown namespaces and explicitly unsupported devices conservatively; unplaced TensorFlow graphs use the later CPU/GPU crossover
  • preserve periodic images, virtual atoms, cutoff boundaries, pair exclusions, and stable equal-distance ordering
  • reuse one cross-backend correctness case in source/tests/consistent, running it on CPU and on an available GPU; TF2 remains opt-in through the existing environment variables
  • include no benchmark harness, raw benchmark data, generated plots, or development benchmark page in the final branch

JAX neighbor-list construction remains eager outside jit; traced full-builder calls retain the dense fallback. TensorFlow tf.function retains compact global sorting because a data-dependent maximum row width cannot safely define a graph allocation.

rcut=6 optimization impact

Cell-list time before and after the per-center selection optimization, on an AMD EPYC 7K62 CPU and NVIDIA RTX 5090:

Backend/device Scenario, N Baseline cell Optimized cell Speedup
NumPy CPU nonperiodic, 4096 95.44 ms 73.82 ms 1.29x
NumPy CPU periodic, 4096 131.58 ms 106.78 ms 1.23x
PyTorch CPU nonperiodic, 4096 48.99 ms 32.45 ms 1.51x
PyTorch CPU periodic, 4096 58.96 ms 36.39 ms 1.62x
JAX CPU nonperiodic, 4096 343.10 ms 195.81 ms 1.75x
JAX CPU periodic, 4096 427.43 ms 277.15 ms 1.54x
PyTorch GPU nonperiodic, 4096 2.165 ms 2.066 ms 1.05x
PyTorch GPU periodic, 4096 2.232 ms 2.131 ms 1.05x

JAX GPU keeps the compact path because extracting the padded row width onto the host caused a small regression near its crossover. TensorFlow graph mode also keeps the compact path.

Current GPU dense/cell validation

Representative measurements at the automatic dispatch region:

Backend Scenario, N Dense Cell Dense / cell
PyTorch nonperiodic, 8192 17.47 ms 2.14 ms 8.18x
PyTorch periodic, 1024 8.53 ms 2.12 ms 4.02x
JAX eager nonperiodic, 12288 65.51 ms 27.08 ms 2.42x
JAX eager periodic, 2048 67.41 ms 26.71 ms 2.52x
TensorFlow tf.function nonperiodic, 8192 65.39 ms 55.94 ms 1.17x
TensorFlow tf.function periodic, 1024 31.24 ms 12.44 ms 2.51x

NumPy has no GPU backend. The following plots are linked from the completed benchmark run for review only; the generated PNG files are not part of the final PR branch or diff.

Updated runtime comparison

Updated cell-list speedup

End-to-end comparison with vesin

These measurements start from the same local coordinates and box at rcut=6, density 0.05, and one float32 frame. DeePMD runs DefaultNeighborList.build with nsel=128, including periodic ghost extension and fixed-width stable distance ordering. vesin v0.6.0 runs full_list=True, sorted=False, and quantities="ij"; its variable-length unsorted edge output is lighter, so this comparison represents the benefit of a specialized native implementation rather than identical output work. Million-scale DeePMD CPU points use one measured build because each call takes tens to hundreds of seconds; GPU and smaller points use warmed medians.

Large-system DeePMD versus vesin comparison

CPU: vesin versus NumPy DeePMD

Scenario N vesin DeePMD DeePMD / vesin
nonperiodic 4,096 1.95 ms 71.37 ms 36.5x
nonperiodic 65,536 24.87 ms 1,498.03 ms 60.2x
nonperiodic 262,144 88.40 ms 6,530.66 ms 73.9x
nonperiodic 524,288 138.87 ms 12,898.03 ms 92.9x
nonperiodic 1,048,576 287.64 ms 29,045.22 ms 101.0x
nonperiodic 2,097,152 707.38 ms 66,869.85 ms 94.5x
nonperiodic 4,194,304 1,749.73 ms 248,476.93 ms 142.0x
nonperiodic 8,388,608 5,076.54 ms not run
periodic 4,096 1.94 ms 105.38 ms 54.4x
periodic 65,536 25.35 ms 1,932.09 ms 76.2x
periodic 262,144 87.12 ms 8,096.94 ms 92.9x
periodic 524,288 154.88 ms 17,061.01 ms 110.2x
periodic 1,048,576 291.81 ms 36,616.30 ms 125.5x
periodic 2,097,152 717.75 ms 79,908.49 ms 111.3x
periodic 4,194,304 1,772.73 ms 188,279.59 ms 106.2x
periodic 8,388,608 5,062.58 ms not run

DeePMD peak RSS was about 69.8/77.1 GiB at 2,097,152 and 140.7/153.9 GiB at 4,194,304 nonperiodic/periodic atoms. The 8,388,608-atom DeePMD runs were not attempted because linear memory extrapolation exceeds the 251 GiB host, while vesin completed both in about 5.1 seconds.

GPU: vesin CUDA versus PyTorch DeePMD

Scenario N vesin DeePMD DeePMD / vesin
nonperiodic 4,096 0.429 ms 1.906 ms 4.44x
nonperiodic 65,536 1.661 ms 8.318 ms 5.01x
nonperiodic 262,144 10.534 ms 32.788 ms 3.11x
nonperiodic 524,288 36.269 ms 65.294 ms 1.80x
nonperiodic 786,432 77.069 ms 98.738 ms 1.28x
nonperiodic 917,504 103.405 ms 115.011 ms 1.11x
nonperiodic 983,040 118.022 ms 127.030 ms 1.08x
nonperiodic 1,048,576 133.249 ms OOM
periodic 4,096 0.764 ms 3.541 ms 4.64x
periodic 65,536 1.753 ms 10.619 ms 6.06x
periodic 262,144 10.988 ms 38.660 ms 3.52x
periodic 524,288 38.181 ms 75.937 ms 1.99x
periodic 786,432 81.534 ms 113.771 ms 1.40x
periodic 851,968 94.794 ms 123.376 ms 1.30x
periodic 917,504 109.073 ms OOM

On the 31.36 GiB RTX 5090, DeePMD succeeded through 983,040 nonperiodic atoms at about 29.2 GiB peak allocated memory and through 851,968 periodic atoms at about 28.4 GiB; the next measured sizes OOMed. The gap to vesin narrows near this limit because vesin caps the CUDA cell grid at 8,192 cells, after which its runtime becomes close to quadratic:

N vesin CUDA nonperiodic vesin CUDA periodic
1,048,576 133.25 ms 140.47 ms
2,097,152 504.79 ms 532.50 ms
4,194,304 1,953.60 ms 2,060.71 ms
5,242,880 3,220.55 ms 3,387.46 ms
6,291,456 4,340.04 ms 4,578.98 ms
7,340,032 5,881.42 ms 6,199.46 ms
8,388,608 OOM OOM

At 4,194,304 atoms, vesin CPU (1.75/1.77 s) is already slightly faster than CUDA (1.95/2.06 s) because of that grid cap. Neighbor counts matched exactly at smaller sizes and differed by at most 63 cutoff-boundary pairs among roughly 190 million directed edges at 4,194,304 atoms. vesin converts coordinates to float64 internally, while DeePMD uses float32 here, so bit-identical cutoff membership is not expected.

Validation

  • repository-wide Ruff format check and lint passed (1675 files)
  • default common/consistent selection: 22 passed, 6 skipped, with 9 shared CPU subtests passed
  • PyTorch CPU/CUDA class through srun --gres=gpu:1: 6 passed, with 6 shared CPU/GPU subtests passed
  • JAX CPU/GPU class through srun --gres=gpu:1: 4 passed, with 6 shared CPU/GPU subtests passed
  • TF2 opt-in CPU/GPU class (DP_TEST_TF2_ONLY=1): 6 passed, with 6 shared CPU/GPU subtests passed
  • all repository hooks passed for the changed Python files

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

Add a Cartesian cell-list path for large systems while retaining the dense builder for backend-specific small-system fast paths. Cover NumPy, PyTorch, JAX eager, and TensorFlow graph execution, and include reproducible rcut=6 CPU/GPU benchmark data and plots.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 21, 2026 17:55
Comment thread source/tests/common/dpmodel/test_default_neighbor_list.py Fixed
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

DefaultNeighborList now adaptively selects dense or Cartesian cell-list neighbor construction using backend- and device-aware thresholds. The cell-list path preserves ordering, exclusions, padding, and output contracts, with deterministic common and cross-backend tests plus TensorFlow shape handling updates.

Changes

Adaptive neighbor-list implementation

Layer / File(s) Summary
Cell-list construction and dispatch
deepmd/dpmodel/utils/default_neighbor_list.py
Adds backend-aware dispatch checks, Cartesian cell binning, fixed-width neighbor selection, exclusion handling, and dense fallback integration.
Core neighbor-list correctness validation
source/tests/common/dpmodel/test_default_neighbor_list.py
Compares forced dense and cell-list results across periodicity, dtypes, exclusions, cutoff boundaries, ordering, padding, and thresholds.
Cross-backend neighbor-list validation
source/tests/consistent/test_default_neighbor_list.py
Validates Array API, PyTorch, JAX, and TensorFlow behavior, including gradients, tracing, device fallback, and dynamic shapes.
TensorFlow shape compatibility
deepmd/_vendors/ndtensorflow/_namespace.py
Uses static shape lists when computing dimensions for take and take_along_axis.

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

Sequence Diagram(s)

sequenceDiagram
  participant DefaultNeighborList
  participant DispatchChecks
  participant CellListBuilder
  participant DenseBuilder
  participant PairExclusion
  DefaultNeighborList->>DispatchChecks: inspect nloc, backend, device, periodicity
  DispatchChecks-->>DefaultNeighborList: choose cell-list or dense construction
  DefaultNeighborList->>CellListBuilder: build fixed-width neighbors
  CellListBuilder->>PairExclusion: apply pair exclusions
  DefaultNeighborList->>DenseBuilder: construct fallback neighbors when unsupported
Loading

Possibly related PRs

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: an adaptive Array API neighbor-search dispatcher in dpmodel.
✨ 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.

Actionable comments posted: 1

🧹 Nitpick comments (3)
doc/development/default-neighbor-list-benchmark.md (1)

84-101: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add an example command for the plotting script.

This section documents how to reproduce the CSV data but not the two embedded plots. Since plot_default_neighbor_list_benchmark.py is linked just above (line 38), consider adding a short example invocation here for completeness.

📝 Proposed addition
 srun --gres=gpu:1 python \
     source/tests/common/dpmodel/benchmark_default_neighbor_list.py \
     --backend jax --device gpu --scenario nonperiodic \
     --output result_jax_gpu_nonperiodic.csv

+Generate the plots from a directory of result_*.csv files:
+
+bash +python doc/development/plot_default_neighbor_list_benchmark.py <results-dir> +

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

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

In @doc/development/default-neighbor-list-benchmark.md around lines 84 - 101,
Add a short plotting example to the “Example commands” section, using the linked
plot_default_neighbor_list_benchmark.py script with a results-directory
argument for generating plots from result_*.csv files. Keep the existing CPU
and GPU benchmark commands unchanged.


</details>

<!-- cr-comment:v1:f7cd7a2855387dfded186913 -->

</blockquote></details>
<details>
<summary>doc/development/plot_default_neighbor_list_benchmark.py (2)</summary><blockquote>

`95-96`: _🎯 Functional Correctness_ | _🔵 Trivial_ | _⚡ Quick win_

**Legend built from a single axis in both `plot_runtime` and `plot_speedup`.** Both functions collect the shared figure legend's handles/labels from only the `("cpu", "nonperiodic")` axis; any series absent from that one panel (but present in another) silently disappears from the legend even though its line is drawn elsewhere.
- `doc/development/plot_default_neighbor_list_benchmark.py#L95-L96`: build the legend from the union of handles/labels across all four axes (e.g. iterate `axes.values()`, dedupe by label) instead of `axes[("cpu", "nonperiodic")]` alone.
- `doc/development/plot_default_neighbor_list_benchmark.py#L139-L140`: apply the same all-axes, deduplicated handle collection here.




<details>
<summary>♻️ Proposed shared helper</summary>

```diff
+def collect_legend(axes: dict[tuple[str, str], plt.Axes]) -> tuple[list, list]:
+    seen: dict[str, Any] = {}
+    for axis in axes.values():
+        handles, labels = axis.get_legend_handles_labels()
+        for handle, label in zip(handles, labels):
+            seen.setdefault(label, handle)
+    return list(seen.values()), list(seen.keys())

Then in plot_runtime and plot_speedup:

-    handles, labels = axes[("cpu", "nonperiodic")].get_legend_handles_labels()
+    handles, labels = collect_legend(axes)
🤖 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 `@doc/development/plot_default_neighbor_list_benchmark.py` around lines 95 -
96, Update plot_runtime at
doc/development/plot_default_neighbor_list_benchmark.py#L95-L96 and plot_speedup
at doc/development/plot_default_neighbor_list_benchmark.py#L139-L140 to build
shared legends from handles and labels collected across all axes.values(),
deduplicated by label, rather than only the ("cpu", "nonperiodic") axis. Reuse a
shared helper if appropriate, ensuring every plotted series appears once in both
legends.

14-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add matplotlib and pandas to the doc requirements, and require Matplotlib >=3.7 for loc="outside lower center". doc/requirements.txt doesn’t currently declare either package, and that legend placement was added in Matplotlib 3.7.0.

🤖 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 `@doc/development/plot_default_neighbor_list_benchmark.py` around lines 14 -
19, Add matplotlib and pandas to doc/requirements.txt, pinning or constraining
matplotlib to version 3.7.0 or newer so the benchmark’s outside-lower-center
legend placement is supported.
🤖 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 `@doc/development/plot_default_neighbor_list_benchmark.py`:
- Around line 95-96: Update the shared legend construction near axes[("cpu",
"nonperiodic")] so it collects and combines handles and labels from every
plotted panel in axes, rather than relying on a single panel. Preserve the
existing figure.legend placement and formatting while ensuring each series
present in any panel appears once in the shared legend.

---

Nitpick comments:
In `@doc/development/default-neighbor-list-benchmark.md`:
- Around line 84-101: Add a short plotting example to the “Example commands”
section, using the linked `plot_default_neighbor_list_benchmark.py` script with
a results-directory argument for generating plots from `result_*.csv` files.
Keep the existing CPU and GPU benchmark commands unchanged.

In `@doc/development/plot_default_neighbor_list_benchmark.py`:
- Around line 95-96: Update plot_runtime at
doc/development/plot_default_neighbor_list_benchmark.py#L95-L96 and plot_speedup
at doc/development/plot_default_neighbor_list_benchmark.py#L139-L140 to build
shared legends from handles and labels collected across all axes.values(),
deduplicated by label, rather than only the ("cpu", "nonperiodic") axis. Reuse a
shared helper if appropriate, ensuring every plotted series appears once in both
legends.
- Around line 14-19: Add matplotlib and pandas to doc/requirements.txt, pinning
or constraining matplotlib to version 3.7.0 or newer so the benchmark’s
outside-lower-center legend placement is supported.
🪄 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

Run ID: 8b567895-debc-4682-b23e-68e76aa8b9cd

📥 Commits

Reviewing files that changed from the base of the PR and between 126d64e and ed5ae86.

⛔ Files ignored due to path filters (3)
  • doc/development/default_neighbor_list_benchmark_rcut6.csv is excluded by !**/*.csv
  • doc/images/neighbor_list_rcut6_runtime_loglog.png is excluded by !**/*.png
  • doc/images/neighbor_list_rcut6_speedup_loglog.png is excluded by !**/*.png
📒 Files selected for processing (6)
  • deepmd/dpmodel/utils/default_neighbor_list.py
  • doc/development/default-neighbor-list-benchmark.md
  • doc/development/plot_default_neighbor_list_benchmark.py
  • doc/index.rst
  • source/tests/common/dpmodel/benchmark_default_neighbor_list.py
  • source/tests/common/dpmodel/test_default_neighbor_list.py

Comment thread doc/development/plot_default_neighbor_list_benchmark.py Outdated

Copilot AI 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.

Pull request overview

This PR updates DeePMD-kit’s dpmodel default neighbor-list construction to dispatch between the historical dense all-pairs method and a new Array-API-based Cartesian cell-list candidate search, aiming to preserve existing neighbor-list semantics while improving scalability on larger systems across backends.

Changes:

  • Added an adaptive dispatcher in DefaultNeighborList with backend/device/periodicity-specific crossover thresholds.
  • Implemented a compact cell-list neighbor search using Array API ops (NumPy/Torch/JAX eager/TF graph/array-api-strict) while preserving cutoff/virtual-atom/exclusion/ordering behavior.
  • Added comprehensive tests plus reproducible benchmark scripts, raw data, and documentation/plotting utilities for rcut=6.

Reviewed changes

Copilot reviewed 7 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
deepmd/dpmodel/utils/default_neighbor_list.py Implements adaptive dense vs cell-list dispatch and the Array-API cell-list builder.
source/tests/common/dpmodel/test_default_neighbor_list.py Validates dense vs cell-list equivalence, ordering, exclusions, and backend-specific behaviors.
source/tests/common/dpmodel/benchmark_default_neighbor_list.py Provides a reproducible benchmark harness for dense vs cell-list runtime comparisons.
doc/development/default-neighbor-list-benchmark.md Documents methodology and summarizes measured crossovers and scaling observations.
doc/development/default_neighbor_list_benchmark_rcut6.csv Adds the raw benchmark results used for plots and threshold selection rationale.
doc/development/plot_default_neighbor_list_benchmark.py Generates runtime and speedup plots from benchmark CSVs.
doc/index.rst Wires the new benchmark doc into the development documentation index.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.72727% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.70%. Comparing base (126d64e) to head (c642e8a).

Files with missing lines Patch % Lines
deepmd/dpmodel/utils/default_neighbor_list.py 96.70% 9 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5889      +/-   ##
==========================================
- Coverage   78.87%   78.70%   -0.18%     
==========================================
  Files        1054     1054              
  Lines      121770   122042     +272     
  Branches     4409     4409              
==========================================
+ Hits        96046    96053       +7     
- Misses      24158    24417     +259     
- Partials     1566     1572       +6     

☔ 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.

Normalize legacy TensorFlow dynamic dimensions in ndtensorflow indexing. Move all backend-specific neighbor-list coverage into the consistent test suite, with TF2 remaining opt-in, and address the benchmark plotting review feedback.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 22, 2026 02:01
@njzjz

njzjz commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

Pushed 13b05a3 to address the failed Python 3.10 shard and review feedback.

  • Fixed ndtensorflow take/take_along_axis with dynamic dimensions when TensorFlow uses legacy Dimension objects.
  • Moved all array-api-strict, PyTorch, JAX, and TF2 neighbor-list tests into source/tests/consistent. TF2 remains opt-in through DEEPMD_TEST_TF2=1 or DP_TEST_TF2_ONLY=1 and is skipped by default.
  • Updated both plot legends to combine all panels, added the plot reproduction command, and declared plotting dependencies.

Validation: common NumPy tests 7 passed; default consistent selection 4 passed and 2 TF2 tests skipped; TF2-only selection 2 passed; combined regular selection 11 passed and 2 skipped; all hooks passed on the six changed files; both benchmark plots regenerated successfully.

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

Comment thread source/tests/consistent/test_default_neighbor_list.py Fixed

@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

🤖 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/tests/consistent/test_default_neighbor_list.py`:
- Line 125: Update the test containing jax.config.update to preserve the prior
jax_enable_x64 setting and restore it during test cleanup, ensuring the
process-wide JAX dtype mode is unchanged for subsequent tests.
🪄 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

Run ID: 0f471318-4419-4204-a94c-eb8639ea261c

📥 Commits

Reviewing files that changed from the base of the PR and between ed5ae86 and 13b05a3.

📒 Files selected for processing (6)
  • deepmd/_vendors/ndtensorflow/_namespace.py
  • doc/development/default-neighbor-list-benchmark.md
  • doc/development/plot_default_neighbor_list_benchmark.py
  • doc/requirements.txt
  • source/tests/common/dpmodel/test_default_neighbor_list.py
  • source/tests/consistent/test_default_neighbor_list.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • doc/development/default-neighbor-list-benchmark.md
  • doc/development/plot_default_neighbor_list_benchmark.py

Comment thread source/tests/consistent/test_default_neighbor_list.py Outdated
Use one unittest import style and restore the process-wide JAX x64 setting after the neighbor-list consistency test.

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

Copilot AI 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.

Pull request overview

Copilot reviewed 10 out of 12 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 22, 2026 02:11

Copilot AI 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.

Pull request overview

Copilot reviewed 10 out of 12 changed files in this pull request and generated 2 comments.

Comment thread doc/development/plot_default_neighbor_list_benchmark.py Outdated
Comment thread doc/development/plot_default_neighbor_list_benchmark.py Outdated
Sort eager candidates in padded per-center rows to avoid three global candidate sorts and the final selection scatter. Keep compact sorting for traced graphs, JAX accelerators, and imbalanced candidate distributions. Remove benchmark documentation and generated data from the PR scope.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 22, 2026 04:43

Copilot AI 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.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment thread deepmd/dpmodel/utils/default_neighbor_list.py
Copilot AI review requested due to automatic review settings July 22, 2026 05:10

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 6 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 22, 2026 06:32

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread deepmd/dpmodel/utils/default_neighbor_list.py Outdated
Use the compact selection path when a PyTorch build does not expose torch.compiler.is_compiling. This preserves compatibility with older or reduced variants without risking a data-dependent allocation while tracing.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 22, 2026 07:15

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread deepmd/dpmodel/utils/default_neighbor_list.py Outdated
Keep placeholder coordinates from expanding or overflowing the Cartesian cell grid, including all-virtual frames. Reuse the backend consistency mixin to cover CPU and available accelerator implementations.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 22, 2026 07:58

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment thread source/tests/consistent/test_default_neighbor_list.py Outdated
Comment thread source/tests/common/dpmodel/test_default_neighbor_list.py Outdated
Generate fractional coordinates in the requested dtype so float32 common and backend consistency cases exercise the intended path.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 22, 2026 08:14

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Use bounded int32 candidate indices on measured eager backends, avoid scan-based iotas when shapes are concrete, and compact unreachable periodic images only beyond backend-specific crossover points.

Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 22, 2026 10:20
@njzjz

njzjz commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

Pushed c642e8a with only benchmark-positive optimizations.

Retained changes:

  • use arange instead of a full candidate scan when the eager shape is concrete;
  • use bounded int32 internal candidate indices only for NumPy/PyTorch, where A/B measurements improved;
  • compact unreachable periodic images only past backend-specific measured crossover points.

Discarded experiments:

  • unstable cell-key sorting: no measurable benefit;
  • unconditional GPU periodic compaction: regressed small/medium systems;
  • int32 candidate paths for JAX/TF: neutral or slower.

Representative rcut=6, density=0.05, nsel=128 results:

backend/device N scenario before after change
NumPy CPU 32,768 nonperiodic 724.7 ms 657.7 ms -9.2%
NumPy CPU 32,768 periodic 978.3 ms 786.2 ms -19.6%
PyTorch CUDA 65,536 nonperiodic 7.836 ms 5.749 ms -26.6%
PyTorch CUDA 65,536 periodic 9.977 ms 7.787 ms -21.9%

For periodic PyTorch CUDA at N=262,144, a same-process A/B measured full-image sorting at 29.65 ms / 7.394 GiB versus compact boundary-shell sorting at 27.56 ms / 6.925 GiB. The conservative compaction threshold is therefore 262,144 atoms; it remains disabled below that point and for JAX/TF accelerators.

On the 31.36 GiB RTX 5090, the previous maximum successes were about 983,040 nonperiodic and 851,968 periodic atoms. The updated implementation successfully built 1,179,648 nonperiodic and 1,048,576 periodic atoms.

Validation:

  • 87 passed in the common/model neighbor-list selection;
  • 19 passed with 21 CPU/GPU backend subtests under the TF2 opt-in environment;
  • all pre-commit hooks passed;
  • no unresolved review threads at the time of push.

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

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@njzjz
njzjz requested a review from wanghan-iapcm July 23, 2026 04:57

@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.

Nice work — the dense/cell-list equivalence holds up under scrutiny (checked cutoff boundary, stable tie-break, self-exclusion, virtual atoms, 27-cell completeness, frame separation, and the compaction pruning bound), and the _namespace.py as_list() change is a correct fix for the legacy Dimension(None) case, not a regression. No correctness issues found. A few non-blocking notes below — one test-coverage gap worth closing and two stale docstrings.

Comment thread deepmd/dpmodel/utils/default_neighbor_list.py
Comment thread deepmd/dpmodel/utils/default_neighbor_list.py Outdated
Comment thread deepmd/dpmodel/utils/default_neighbor_list.py
Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 23, 2026 12:00

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread source/tests/consistent/test_default_neighbor_list.py Outdated
Coding-Agent: Codex
Codex-Version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning-Effort: xhigh
Copilot AI review requested due to automatic review settings July 23, 2026 12:41

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment on lines +523 to +524
offsets = xp.asarray(_NEIGHBOR_CELL_OFFSETS, dtype=xp.int64, device=device)
query_cell = center_cell[:, :, None, :] + offsets[None, None, :, :]
Comment on lines +304 to +319
if array_api_compat.is_torch_array(coord):
import torch

# torch.export/compile must keep the compact path: converting the maximum
# candidate count to ``int`` would specialize an unbacked symbolic value.
# Keep unmeasured accelerator implementations on the compact path too.
device = array_api_compat.device(coord)
is_compiling = getattr(getattr(torch, "compiler", None), "is_compiling", None)
# Older or reduced PyTorch builds may not expose torch.compiler. Without
# a reliable tracing-state query, keep the dynamic compact path instead
# of risking a data-dependent Python allocation during compilation.
return (
device.type in ("cpu", "cuda")
and is_compiling is not None
and not is_compiling()
)
Comment on lines +249 to +259
center_start = xp.cumulative_sum(count_per_center) - count_per_center
edge_iota = _index_iota(center)
rank = edge_iota - xp.take(center_start, center, axis=0)
slot = center * max_candidates + rank

neighbor_rows = xp_scatter_sum(
xp.zeros((padded_size,), dtype=xp.int64, device=device),
0,
slot,
neighbor_ext + 1,
)
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.

5 participants