Skip to content

perf(lmdb): parallelize batch decoding and support epoch-based schedules - #5914

Merged
OutisLi merged 11 commits into
deepmodeling:masterfrom
OutisLi:pr/lmdb-schedule
Jul 30, 2026
Merged

perf(lmdb): parallelize batch decoding and support epoch-based schedules#5914
OutisLi merged 11 commits into
deepmodeling:masterfrom
OutisLi:pr/lmdb-schedule

Conversation

@OutisLi

@OutisLi OutisLi commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • parallelize LMDB batch decoding across PT and PT-expt backends with bounded worker resources
  • add LMDB worker configuration and strengthen dataset/resource lifecycle handling
  • resolve backend-independent epoch-to-step schedules, including multi-task probabilities and distributed rank synchronization
  • cover LMDB decoding, scheduling, multitask, and distributed-training behavior with regression tests

Checks

No test suite was run per request; the changes were tested separately on another machine. Repository pre-commit style hooks passed while creating the cherry-pick commit.

Summary by CodeRabbit

  • New Features
    • Unified step scheduling for single- and multi-task training, deriving total steps and task sampling probabilities from config.
    • Faster LMDB training input pipeline with deterministic parallel batch iteration and config-driven decoding, plus a new LMDB batch loader for training.
  • Bug Fixes
    • Pinned epoch-to-step/run-length decisions for consistent distributed behavior across ranks.
    • Improved LMDB safety with reliable decoder/loader cleanup on failure and safer dataset merging/iterator lifecycle.
  • Documentation
    • Documented DP_LMDB_NUM_WORKERS override and auto-selection behavior.
  • Tests
    • Expanded coverage for step scheduling, LMDB decoding/batching correctness, distributed epoch consistency, and shutdown robustness.

OutisLi added 2 commits July 28, 2026 12:07
Decode same-nloc batches directly into preallocated arrays and use a bounded, rank-shared process pool so both PT and pt_expt can overlap deterministic LMDB reads with GPU work without duplicating dataset metadata. Centralize worker budgeting in DP_LMDB_NUM_WORKERS, preserve synchronous handling for small batches, and harden schema consistency, dtype promotion, path canonicalization, requirement freezing, and LMDB resource lifecycles across normal and exceptional exits.

Add regression coverage for serial/parallel parity, finite epochs, tail batches, shared pools, concurrent readers, merge failures, multi-task training, and cleanup behavior, and document the immutable-dataset and aggregate-worker contracts.
pt_expt accepted only an explicit numb_steps, so a run had to be sized in
steps even when the goal was a number of passes over the data. The
epoch-to-step conversion now lives in a backend-independent resolver that
pt uses as well, so both backends share the option validation, the
multi-task step split and the cross-rank pinning that keeps num_steps in
lockstep. A backend supplies only the epoch length of a task: pt reads its
sharded per-rank loader, while pt_expt divides the dataset-wide batch count
by the world size because every rank holds the complete data system, so an
epoch denotes one pass over the dataset in either backend.
Copilot AI review requested due to automatic review settings July 28, 2026 04: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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@dosubot dosubot Bot added the enhancement label Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 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

The PR adds shared epoch-based training schedule resolution and integrates it into both PyTorch trainers. It also introduces concurrent LMDB decoding, loader adapters, worker-count configuration, resource cleanup, LMDB merging changes, documentation, and regression tests.

Changes

Training scheduling and LMDB data pipelines

Layer / File(s) Summary
Shared training schedule resolution
deepmd/dpmodel/train/*, source/tests/common/dpmodel/test_train_schedule.py
Adds StepSchedule and resolve_step_schedule for single-task and multi-task step/probability calculation, including rank-synchronized epoch lengths and validation.
Config-driven LMDB decoding and lifecycle
deepmd/dpmodel/utils/lmdb_data.py, source/tests/common/dpmodel/test_lmdb_data.py
Adds normalized frame decoding, contiguous batch assembly, process-pool iteration, frozen data requirements, reader lifecycle handling, deterministic sampler epochs, and lease-safe LMDB merging.
LMDB worker configuration and loader adapters
deepmd/env.py, deepmd/pt/utils/lmdb_dataset.py, deepmd/pt_expt/utils/lmdb_dataset.py, doc/env.md, source/tests/pt/*, source/tests/pt_expt/test_lmdb_training.py
Adds automatic or environment-configured worker counts and routes PyTorch and pt_expt LMDB batches through LmdbBatchIterator with explicit cleanup.
Trainer scheduling and cleanup
deepmd/pt/train/training.py, deepmd/pt_expt/train/training.py, deepmd/pt_expt/entrypoints/main.py, source/tests/pt_expt/*
Both trainers consume the shared schedule resolver, synchronize distributed epoch-derived values, pass distributed sharding parameters, and close LMDB/data-system resources on normal and exceptional exits.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Trainer
  participant LmdbBatchDataLoader
  participant LmdbBatchIterator
  participant LmdbDataReader
  Trainer->>LmdbBatchDataLoader: create training loader
  LmdbBatchDataLoader->>LmdbBatchIterator: initialize sampler and workers
  LmdbBatchIterator->>LmdbDataReader: decode requested frames
  LmdbDataReader-->>LmdbBatchIterator: decoded batch arrays
  LmdbBatchIterator-->>LmdbBatchDataLoader: return merged batch
  Trainer->>LmdbBatchDataLoader: close in finally block
  LmdbBatchDataLoader->>LmdbBatchIterator: release executor
  LmdbBatchDataLoader->>LmdbDataReader: close reader
Loading

Possibly related PRs

Suggested labels: new feature

Suggested reviewers: njzjz

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main changes: LMDB batch decoding parallelization and epoch-based scheduling support.
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.
✨ 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.

Comment thread deepmd/pt/utils/lmdb_dataset.py Fixed
Comment thread source/tests/common/dpmodel/test_lmdb_data.py Fixed
@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.92655% with 43 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.05%. Comparing base (4f827cc) to head (0d18818).

Files with missing lines Patch % Lines
deepmd/dpmodel/utils/lmdb_data.py 94.09% 29 Missing ⚠️
deepmd/pt_expt/train/training.py 77.41% 7 Missing ⚠️
deepmd/pt/train/training.py 83.33% 5 Missing ⚠️
deepmd/pt/utils/lmdb_dataset.py 97.22% 1 Missing ⚠️
deepmd/pt_expt/utils/lmdb_dataset.py 97.50% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5914      +/-   ##
==========================================
- Coverage   79.21%   79.05%   -0.16%     
==========================================
  Files        1069     1070       +1     
  Lines      124070   124537     +467     
  Branches     4522     4528       +6     
==========================================
+ Hits        98278    98456     +178     
- Misses      24171    24463     +292     
+ Partials     1621     1618       -3     

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

@OutisLi
OutisLi requested review from njzjz and wanghan-iapcm July 28, 2026 06:37
Copilot AI review requested due to automatic review settings July 28, 2026 06:39

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@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: 4

🧹 Nitpick comments (2)
deepmd/dpmodel/train/schedule.py (1)

121-123: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Over-specification is rejected for multi-task but silently resolved for single-task. The docstring promises ValueError when the run length is over-specified, yet a single-task config with both numb_steps and numb_epoch returns early on numb_steps without a word. Either mirror the mutual-exclusivity check here or soften the docstring to state that numb_steps takes precedence.

Also applies to: 142-147

🤖 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 `@deepmd/dpmodel/train/schedule.py` around lines 121 - 123, Update the
schedule-building logic around the single-task early return and the
corresponding multi-task branch to enforce mutual exclusivity when both
num_steps and num_epoch are provided, raising ValueError as documented; do not
silently prioritize num_steps, and preserve normal behavior when only one option
is set.
source/tests/pt/test_lmdb_dataloader.py (1)

1068-1071: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

This shared-pool assertion can pass vacuously.

_executor stays None until a parallel-eligible batch is submitted (num_workers > 1 and len(indices) >= num_workers). If the multitask fixture's batch size is below 2, both sides are None and the identity check succeeds without proving pool sharing. Assert the executor is not None first.

♻️ Suggested strengthening
+        assert trainer.training_dataloader["model_1"]._batch_iterator.started
         assert (
             trainer.training_dataloader["model_1"]._batch_iterator._executor
             is trainer.training_dataloader["model_2"]._batch_iterator._executor
         )
🤖 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/tests/pt/test_lmdb_dataloader.py` around lines 1068 - 1071, Strengthen
the shared-pool assertion in the multitask dataloader test by first asserting
that the relevant batch iterator executor is not None, then retain the identity
assertion comparing the executors for model_1 and model_2. Use the existing
training_dataloader and _batch_iterator symbols without changing the sharing
behavior being tested.
🤖 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 `@deepmd/dpmodel/train/schedule.py`:
- Around line 121-130: Update the ValueError messages in the non-multi-task
schedule validation around StepSchedule to reference the actual numb_epoch
configuration key instead of training.num_epoch, while preserving the existing
numb_steps wording. Adjust the related test regex expectations in
test_train_schedule.py to accept the corrected key using the requested
num[b]?_epoch-compatible pattern.

In `@deepmd/dpmodel/utils/lmdb_data.py`:
- Around line 334-355: Update the min_pair_dist branch around
compute_min_pair_dist_single so it only computes when both “coord” and “atype”
are present in frame; otherwise populate min_pair_dist using the requirement’s
default value, preserving the existing dtype handling and find_min_pair_dist
marker.

In `@source/tests/pt_expt/test_training_ddp.py`:
- Around line 682-689: Update test_ranks_share_an_epoch to compute the expected
per-rank step count using the production ceil-based rounding rule, such as
math.ceil(nframes / 2), rather than floor division. Add the required math import
and keep both rank assertions aligned with this expected value.

In `@source/tests/pt_expt/utils/test_env.py`:
- Around line 15-29: Update test_lmdb_num_workers_partitions_node_budget to
monkeypatch os.sched_getaffinity with raising=False so it runs on platforms
where the attribute is absent. Refactor
test_lmdb_num_workers_rejects_invalid_override to use pytest.raises(ValueError),
adding the pytest import required by the module’s existing test style.

---

Nitpick comments:
In `@deepmd/dpmodel/train/schedule.py`:
- Around line 121-123: Update the schedule-building logic around the single-task
early return and the corresponding multi-task branch to enforce mutual
exclusivity when both num_steps and num_epoch are provided, raising ValueError
as documented; do not silently prioritize num_steps, and preserve normal
behavior when only one option is set.

In `@source/tests/pt/test_lmdb_dataloader.py`:
- Around line 1068-1071: Strengthen the shared-pool assertion in the multitask
dataloader test by first asserting that the relevant batch iterator executor is
not None, then retain the identity assertion comparing the executors for model_1
and model_2. Use the existing training_dataloader and _batch_iterator symbols
without changing the sharing behavior being tested.
🪄 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: 7ca39f2e-aa59-43fb-a3f7-3a2af68674c9

📥 Commits

Reviewing files that changed from the base of the PR and between 2f419f4 and 3e48ccb.

📒 Files selected for processing (17)
  • deepmd/dpmodel/train/__init__.py
  • deepmd/dpmodel/train/schedule.py
  • deepmd/dpmodel/utils/lmdb_data.py
  • deepmd/env.py
  • deepmd/pt/train/training.py
  • deepmd/pt/utils/lmdb_dataset.py
  • deepmd/pt_expt/train/training.py
  • deepmd/pt_expt/utils/lmdb_dataset.py
  • doc/env.md
  • source/tests/common/dpmodel/test_lmdb_data.py
  • source/tests/common/dpmodel/test_train_schedule.py
  • source/tests/pt/test_lmdb_dataloader.py
  • source/tests/pt_expt/test_lmdb_training.py
  • source/tests/pt_expt/test_multitask.py
  • source/tests/pt_expt/test_training.py
  • source/tests/pt_expt/test_training_ddp.py
  • source/tests/pt_expt/utils/test_env.py

Comment thread deepmd/dpmodel/train/schedule.py
Comment thread deepmd/dpmodel/utils/lmdb_data.py Outdated
Comment thread source/tests/pt_expt/test_training_ddp.py
Comment thread source/tests/pt_expt/utils/test_env.py Outdated
Copilot AI review requested due to automatic review settings July 28, 2026 07:42

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

Requesting changes for the inline LMDB epoch-order regression.

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

Comment thread deepmd/dpmodel/utils/lmdb_data.py Outdated
Copilot AI review requested due to automatic review settings July 28, 2026 14:50

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

Reviewed the parallel-decode path, the new shared step schedule, and the worker sizing.

One thing worth recording up front, since it was the property I most expected to break: batch contents and ordering are independent of worker count. _submit slices into contiguous chunks in worker order, [f.result() for f in ...] preserves submission order, and _merge_lmdb_chunks concatenates in list order -- so DP_LMDB_NUM_WORKERS is a pure performance knob and does not perturb training numerics. Three separate passes over the code agreed on that. The merge_lmdb refcount fix (try/finally: _close_lmdb(src_path) replacing a direct src_env.close() on a refcounted handle) and the pin_memory=DEVICE.type != "cpu" correction are both genuine fixes in passing.

Four findings below plus two coverage asks. The two correctness ones (the epoch counter and the pt_expt epoch length) are both confined to DDP, which is also why no existing test catches them -- the added distributed tests use mocked epoch_length callables and never cross an epoch boundary at world_size > 1.

None of this is blocking from my side; the rebase question is the one I would settle first.

Comment thread deepmd/dpmodel/utils/lmdb_data.py
Comment thread deepmd/dpmodel/utils/lmdb_data.py Outdated
Comment thread deepmd/dpmodel/utils/lmdb_data.py
Comment thread deepmd/pt_expt/train/training.py
Comment thread deepmd/dpmodel/utils/lmdb_data.py
Comment thread deepmd/env.py
OutisLi added 2 commits July 29, 2026 16:35
A run whose LMDB decoders were killed by the hangup of the session that
started it stopped after three epochs and sat there for twenty hours. The
training process was healthy and its main thread was waiting on a decode
that could never arrive: the pool's own manager thread was itself blocked
reading the partial result the dying decoder had left in the queue, so the
pool never declared itself broken and nothing ever raised.

Decoders no longer die of that hangup. A decoder is a background helper
that owns no terminal, so the signal carries no meaning for it while the
default disposition makes it fatal; it is ignored. The pool is built on
`spawn` rather than `forkserver` for the same reason, a fork server being
an unshielded intermediary whose own death is reported as the death of
every decoder it started, which breaks the pool however well the decoders
themselves are protected. Measured over two and sixteen workers: with a
fork server a full hangup leaves no decoder alive and the pool unusable,
while with `spawn` every decoder survives and the pool keeps serving.

Losing a decoder anyway -- to the memory killer, or to a signal no process
can ignore -- now costs throughput rather than the run. It reaches the
iterator at three points, and all three fall back to decoding in the
training process: the pool may refuse the submission, it may fail the
futures it holds, or it may go quiet, which a liveness check between waits
turns into the same outcome. The batch is re-decoded from the indices the
pending batch carries, which is exact, because decoding only reads frames
by key. Pool health lives on the shared pool entry, so a rank discovers
the loss once however many data tasks share it.

A pool stuck on a partial result also has to be dismantled rather than
waited on. The interpreter joins every pool manager thread before it
exits, so a run would otherwise complete its training, write its
checkpoints and then never terminate, which a scheduler records as a
timeout. Closing the write end the training process still holds delivers
the end of file that read is waiting for. Measured: thirty seconds and
counting before, two seconds to a clean exit after.

`signal.SIGHUP` is absent on Windows, where the shielding is skipped
rather than failing every decoder at startup.
Copilot AI review requested due to automatic review settings July 29, 2026 08:37

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@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: 2

🤖 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/common/dpmodel/test_lmdb_data.py`:
- Around line 1710-1744: Guard both signal-based tests,
test_decoders_survive_the_hangup_of_their_launching_session and
test_killing_the_real_decoders_does_not_stop_the_run, so they are skipped on
non-POSIX platforms before referencing signal.SIGHUP or signal.SIGKILL. Use the
suite’s existing unittest/platform conventions where available and leave their
POSIX behavior unchanged.
- Around line 1689-1701: Update the subprocess test setup around
_acquire_lmdb_executor and _release_lmdb_executor so it does not unconditionally
access the private entry.executor._result_queue._writer; guard the partial-frame
write with an appropriate hasattr check (or replace it with a supported
mechanism), while preserving the malformed partial-frame scenario when the
writer is available.
🪄 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: 48c5b852-5841-44d5-8226-bde4dab1f7fe

📥 Commits

Reviewing files that changed from the base of the PR and between 792245c and db10538.

📒 Files selected for processing (6)
  • deepmd/dpmodel/utils/lmdb_data.py
  • deepmd/pt/utils/lmdb_dataset.py
  • deepmd/pt_expt/utils/lmdb_dataset.py
  • source/tests/common/dpmodel/test_lmdb_data.py
  • source/tests/pt/test_lmdb_dataloader.py
  • source/tests/pt_expt/test_lmdb_training.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • deepmd/pt/utils/lmdb_dataset.py
  • source/tests/pt_expt/test_lmdb_training.py
  • source/tests/pt/test_lmdb_dataloader.py
  • deepmd/pt_expt/utils/lmdb_dataset.py
  • deepmd/dpmodel/utils/lmdb_data.py

Comment thread source/tests/common/dpmodel/test_lmdb_data.py
Comment thread source/tests/common/dpmodel/test_lmdb_data.py Outdated
Comment thread deepmd/dpmodel/utils/lmdb_data.py Dismissed
OutisLi added 2 commits July 29, 2026 18:11
… decode

Three defects in the parallel batch decoder surface once frames are grouped
by label availability.

The batch sequence is partitioned by that availability, so registering data
requirements must not follow a partition built without them. The pt_expt data
system tried to enforce this by rebuilding an iterator it no longer owns,
leaving a stale attribute behind and rebuilding nothing. The reader already
refuses a registration that follows any decode, and the sampler derives the
partition only when the first batch is drawn, so no batch state can precede
the call: the rebuild is unnecessary and the dead assignment goes. A test
pins the reader's refusal, which nothing covered.

Collation and preallocated decoding must agree on the batch they produce.
Collation emitted the availability flags ahead of the payload while the
preallocated path kept the frame's own key order, so the same batch was two
different mappings depending on which path built it. Availability is now
validated before collation begins and the batch is assembled in frame order,
which leaves the validation intact and the two paths interchangeable.

Frames were also grouped by an availability rule of their own, which could
disagree with the one collation enforces and turn a grouping miss into a
raise. Both now settle availability through the same predicate.
Copilot AI review requested due to automatic review settings July 29, 2026 10:27

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
source/tests/pt_expt/test_lmdb_training.py (1)

195-214: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Close every LmdbDataSystem created by these tests.

serial and the streaming reader remain open, while test_data_requirements_freeze_after_first_read starts a two-worker decoder pipeline without closing it. Use try/finally to close each system so test processes and LMDB handles cannot leak into later tests.

Also applies to: 216-247, 249-263

🤖 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/tests/pt_expt/test_lmdb_training.py` around lines 195 - 214, The tests
creating LmdbDataSystem instances must close every system, including serial,
streaming, and the two-worker decoder used by
test_data_requirements_freeze_after_first_read. Wrap each system’s usage in
try/finally and call its close method in finally, covering
test_streaming_batch_matches_frame_collation and the additional affected test
blocks.
🤖 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/pt_expt/test_lmdb_training.py`:
- Around line 303-310: Update the batch assertions in the LMDB training test to
flatten all frame IDs across every rank and batch, then use assertCountEqual
against range(8). Remove the first-two-batches-only overlap check or make the
aggregate assertion the sole validation so duplicates anywhere fail while full
coverage remains required.

---

Outside diff comments:
In `@source/tests/pt_expt/test_lmdb_training.py`:
- Around line 195-214: The tests creating LmdbDataSystem instances must close
every system, including serial, streaming, and the two-worker decoder used by
test_data_requirements_freeze_after_first_read. Wrap each system’s usage in
try/finally and call its close method in finally, covering
test_streaming_batch_matches_frame_collation and the additional affected test
blocks.
🪄 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: bd40e97c-2bbf-42cd-8610-61504c8053d1

📥 Commits

Reviewing files that changed from the base of the PR and between db10538 and 0ca3b5f.

📒 Files selected for processing (8)
  • deepmd/dpmodel/utils/lmdb_data.py
  • deepmd/pt_expt/entrypoints/main.py
  • deepmd/pt_expt/train/training.py
  • deepmd/pt_expt/utils/lmdb_dataset.py
  • source/tests/common/dpmodel/test_lmdb_data.py
  • source/tests/pt/test_lmdb_dataloader.py
  • source/tests/pt_expt/test_lmdb_training.py
  • source/tests/pt_expt/utils/test_env.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • deepmd/pt_expt/utils/lmdb_dataset.py
  • deepmd/pt_expt/train/training.py
  • source/tests/common/dpmodel/test_lmdb_data.py
  • source/tests/pt/test_lmdb_dataloader.py
  • deepmd/dpmodel/utils/lmdb_data.py

Comment thread source/tests/pt_expt/test_lmdb_training.py
@OutisLi
OutisLi requested a review from wanghan-iapcm July 29, 2026 10:32

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

Verified all six threads against the current head rather than the replies.

The rebase reconciled cleanly: #5839 is now in the history, its structural-key hoisting and availability-signature grouping survive, and add_data_requirement still invalidates the signature cache. Handling refresh_batch_count() on the distributed sampler was a good catch that I had not asked for -- the availability partitioning changes the batch count, so the sharding fix and the rebase genuinely interact there.

The two distributed fixes are the substantive ones and both are right. DistributedSameNlocBatchSampler.__len__ is now rank-independent with deterministic padding in _partition_batches, so ranks cross the epoch boundary together instead of drifting apart when the batch count is not divisible by the world size. And plumbing rank/world_size through to LmdbDataSystem fixes the pt_expt side properly -- keeping nbatches as the global count so ceil(total / world_size) still matches the local sampler length is exactly the invariant that keeps the epoch arithmetic honest.

test_distributed_batches_are_sharded_with_equal_epoch_lengths is a real regression test, not a placeholder: three global batches on two ranks is the non-divisible case, and asserting len(sampler) == [2, 2] fails on the old rank-dependent length, while the disjointness assertion fails on the old shared-seed sampler where both ranks drew identical batches. One test that fails for both reasons before the fix.

The four merge guards and the five worker-count branches are now exercised.

On the parallel-decode threshold: your reasoning is fine and I am not pressing it. One leftover, non-blocking -- doc/env.md still says "The next batch is prefetched while the current batch is consumed" one sentence before explaining that small batches decode synchronously, and the deferred path stores indices rather than a future, so there is no prefetch there either. Now that the synchronous fallback is a deliberate choice rather than an oversight, that sentence would be worth qualifying whenever you next touch the file.

Copilot AI review requested due to automatic review settings July 29, 2026 15:05

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

Requesting changes for two reproducible LMDB correctness and lifecycle issues. Details are inline.

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

Comment thread deepmd/pt_expt/utils/lmdb_dataset.py
Comment thread deepmd/dpmodel/utils/lmdb_data.py Outdated
Copilot AI review requested due to automatic review settings July 30, 2026 04:05

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

Reviewed current head 0d188183fb5ddd27dbe057fd4efe7fa42011b741. No blocking findings.

Validation:

  • ruff check . and ruff format --check .
  • 15 shared schedule tests
  • 79 shared LMDB tests, including decoder-loss and shutdown paths
  • 62 PyTorch LMDB adapter/training tests
  • 23 PyTorch Exportable LMDB and worker-configuration tests
  • 4 epoch/multitask/distributed schedule tests
  • CLI and PyTorch import smoke checks

The failed macOS arm64 wheel job is an infrastructure download failure (No buffer space available while fetching lmdb) after the wheel built, not a failure caused by this change.

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

@OutisLi
OutisLi enabled auto-merge July 30, 2026 05:02
@OutisLi
OutisLi added this pull request to the merge queue Jul 30, 2026
Merged via the queue into deepmodeling:master with commit 2e39220 Jul 30, 2026
66 of 69 checks passed
@OutisLi
OutisLi deleted the pr/lmdb-schedule branch July 30, 2026 12:53
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.

6 participants