Skip to content

ci: Bump Megatron-Bridge to 5ed9799 - #4022

Merged
terrykong merged 10 commits into
mainfrom
ci/bump-mbridge-5ed9799-20260904-070613
Sep 7, 2026
Merged

ci: Bump Megatron-Bridge to 5ed9799 #4022
terrykong merged 10 commits into
mainfrom
ci/bump-mbridge-5ed9799-20260904-070613

Conversation

@cspades

@cspades cspades commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

What does this PR do ?

Replaces: #3991

  • Another attempt of bumping Megatron-Bridge while fixing a variety of issues from the bump (and already present in main branch...).
    • bump A seg-faulting log prob test case for Megatron inference (PP > 2 and async scheduling).
      • Megatron inference now uses async scheduling by default.
    • bump Deactivate cpu_initialization, which is a new default from Megatron-Bridge.
    • main Relax a NotImplementedError from da39e17.
    • bump Fix a dopple-ganger socket forked (via async checkpointing) from a port reservation that is stealing Megatron inference requests with the new replicate inference servers for Megatron-Inference.
      • This is solved by storing the port, not the socket, with the Megatron generation mixins.
    • main Fix a Gym regression introduced by 7036e5d.

Details

  • Extra socket forked from the reserved port for Gym (when using async checkpointing) that acts as a doppleganger for Megatron inference servers.
    • To support overlapped init with Gym and non-colocated, we need to reserve a port, which we do by creating a socket using HeldPortReservation. We hand the port reserved by the socket to Gym.
    • At some point before rollouts begin, a child process is forked from the same process with the socket reservation. So now we have 2 sockets, HeldPortReservation closing the original one doesn't close the second one, which ends up being a dopple-ganger of sorts.
    • Megatron policy/generation initialization then grabs the reserved socket (just for its reserved port) for HTTP front-end initialization.
    • Gym then sends inference requests over the reserved port, which includes the HTTP front-ends as well as the dopple-ganger which doesn't do anything with those requests. Then Gym rollouts hang forever waiting for the result of the requests it sent to the dopple-ganger.

Issues

List issues that this PR closes (syntax):

Usage

  • You can potentially add a usage example below
# Add a code snippet demonstrating how to use this

Before your PR is "Ready for review"

Pre checks:

  • Make sure you read and followed Contributor guidelines
  • Did you write any new necessary tests?
  • Did you run the unit tests and functional tests locally? Visit our Testing Guide for how to run tests
  • Did you add or update any necessary documentation? Visit our Document Development Guide for how to write, build and test the docs.

Additional Information

  • ...

cspades and others added 5 commits September 5, 2026 20:28
Signed-off-by: nemo-ci-bot <nemo-ci-bot@nvidia.com>
…blocker.

Signed-off-by: Cory Ye <cye@nvidia.com>
Signed-off-by: Cory Ye <cye@nvidia.com>
Signed-off-by: Cory Ye <cye@nvidia.com>
@cspades cspades self-assigned this Sep 6, 2026
@cspades
cspades requested review from a team as code owners September 6, 2026 03:55
@copy-pr-bot

copy-pr-bot Bot commented Sep 6, 2026

Copy link
Copy Markdown

Auto-sync is disabled for ready for review pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: 2c27735 (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

@cspades
cspades force-pushed the ci/bump-mbridge-5ed9799-20260904-070613 branch from 2c27735 to 16180e3 Compare September 6, 2026 04:09
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: 16180e3 (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: f7d3c1d (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: 5429641 (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

Signed-off-by: Cory Ye <cye@nvidia.com>
@cspades
cspades requested a review from a team as a code owner September 6, 2026 04:56
@cspades

cspades commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test 9e91bbd

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: 9e91bbd (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

@cspades cspades added the CI:L1 Run doctests, unit tests, and functional tests label Sep 6, 2026
@cspades

cspades commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test 9e91bbd

@svcnvidia-nemo-ci

Copy link
Copy Markdown
Contributor

Superseded by a newer MBridge bump PR.

@cspades cspades reopened this Sep 6, 2026
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: 9e91bbd (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

@cspades
cspades requested review from a team as code owners September 6, 2026 15:46
@cspades

cspades commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test e9f51b0

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: e9f51b0 (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

@cspades
cspades force-pushed the ci/bump-mbridge-5ed9799-20260904-070613 branch from e9f51b0 to b997d39 Compare September 6, 2026 16:45
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: b997d39 (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

@cspades

cspades commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test b997d39

@cspades
cspades force-pushed the ci/bump-mbridge-5ed9799-20260904-070613 branch from b997d39 to b99ee92 Compare September 6, 2026 17:01
@cspades

cspades commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test b99ee92

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: b99ee92 (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

Signed-off-by: Cory Ye <cye@nvidia.com>
@cspades
cspades force-pushed the ci/bump-mbridge-5ed9799-20260904-070613 branch from b99ee92 to 571229c Compare September 6, 2026 18:22
@cspades

cspades commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test 571229c

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: 571229c (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

Signed-off-by: Cory Ye <cye@nvidia.com>
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Submodule Fast-Forward Check Results

Check based on commit: 28f4d08 (PR #4022 from ci/bump-mbridge-5ed9799-20260904-070613)

✅ Submodules that are properly updated:

Megatron-Bridge: ✅ PR branch is ahead of main branch (fast-forward)

All submodule changes look good! ✨

@cspades

cspades commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Ran the last test case in L1 single controller manually (Hydra config ++) to skip waiting hours for the full CI:

uv run --no-sync bash ./tests/functional/grpo_async_gym_single_controller.sh ++token_capture.enabled=true

✓ Merged data written to /opt/nemo-rl/tests/functional/grpo_async_gym_single_controller/metrics.json
Installed 4 packages in 69ms
                                                                                                       Metric Checks                                                                                                        
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Status              ┃ Check                                                                                                         ┃ Value                                                      ┃ Message               ┃
┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ PASS                │ median(data["train/gen_kl_error"]) < 1.3                                                                      │ 0.0010955703328363597                                      │                       │
│ PASS                │ max(data["train/reward"]) > 0                                                                                 │ 0.5                                                        │                       │
│ PASS                │ max(data["train/finalize/total_ms"]) > 0                                                                      │ 226.58016967773438                                         │                       │
└─────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────┴───────────────────────┘

Comment thread tests/unit/environments/test_nemo_gym_health.py Outdated
Comment thread 3rdparty/Megatron-Bridge-workspace/Megatron-Bridge
Comment thread nemo_rl/environments/nemo_gym.py
Comment thread tests/unit/models/generation/test_megatron_generation.py
# Adoption occurs only at HTTP startup, after model initialization
# can no longer leak the listener into long-lived child processes.
assert holder._sock.fileno() == -1
assert reserved_socket.getsockname()[1] == port

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.

1 action item.

TL;DR — the rewrite dropped the post-adoption create_connection, which was the only assertion that tested whether the port is still accepting connections after the handoff — the exact property the test's docstring says it exists to check.

The test states the contract about itself, in its docstring at L169-L175:

the worker adopts that same socket through the fd handoff — the port is never released in between — and the server falls back to a fresh port only when nothing was reserved.

Nothing left in the test checks the middle clause. At the base commit it was checked by connecting to the port after adoption, with the holder's own copy already closed — test_megatron_generation_parse.py#L205-L209 @ a366bc8 (linked at the base, since these lines no longer exist at head):

        assert holder._sock.fileno() == -1
        assert reserved.getsockname()[1] == port
        with socket.create_connection(("127.0.0.1", port), timeout=5):
            pass

The rewrite keeps the first two lines and drops the connect. Those two do not cover it. holder._sock.fileno() == -1 proves the holder closed its copy. getsockname()[1] == port proves the adopted object is bound to the right port. Neither proves the socket is still listening and accepting — a socket can be bound with no live accept queue. "Never released" is a property about the port still being alive, and the connect was the only assertion that tested that.

The remaining connect at L191-L194 runs before adoption, so it only proves the holder was listening.

The timing of that handoff is what this PR changes, and this test is what guards the change — which makes this the wrong assertion to lose in this PR specifically.

AI-1

Suggested change
assert reserved_socket.getsockname()[1] == port
assert reserved_socket.getsockname()[1] == port
# Still accepting after the holder closed its copy: the port was
# never released across the handoff.
with socket.create_connection(("127.0.0.1", port), timeout=5):
pass

Restoring the connect is safe: start_text_gen_server is monkeypatched to a lambda that only records its kwargs, so nothing closes the socket during the test and the connection will succeed.

Not run locally — this file is @pytest.mark.mcore and needs a GPU/mcore environment, which the review side does not have.

@cspades cspades Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is a good catch, technically this socket should be holding onto the port as soon as HeldPortReservation() is initialized, so nothing else takes it, but low chance of anything stealing this port in a unit test env.

Comment thread nemo_rl/models/policy/workers/megatron_policy_worker.py
@terrykong
terrykong merged commit c0165c8 into main Sep 7, 2026
11 checks passed
@terrykong
terrykong deleted the ci/bump-mbridge-5ed9799-20260904-070613 branch September 7, 2026 00:11
sidsingh-nvidia added a commit to ArEsKay3/RL that referenced this pull request Sep 8, 2026
The worker adopted the driver-reserved listening socket in __init__, so a
live listening fd existed for the whole of model initialization. Anything
forked during init inherited a duplicate, and because the frontends bind
with SO_REUSEPORT, the kernel could route connections to a child that
never accepts HTTP requests -- an extra no-op endpoint from Gym's point
of view.

Keep only the port number through init and adopt the socket in
_setup_openai_api_server, immediately before the frontends start. The
port holder keeps it bound and listening until then, so the pre-published
URL still cannot be stolen and early Gym probes still queue rather than
being refused.

Ports as reserved per rank, so this defers the handoff for every frontend
the driver reserved, not just one.

Mirrors the same fix upstream in NVIDIA-NeMo#4022 (b38c38f), adapted
to the per-frontend reservation map on this branch.

Signed-off-by: Siddharth Singh <sidsingh@nvidia.com>
cspades pushed a commit to ArEsKay3/RL that referenced this pull request Sep 8, 2026
The worker adopted the driver-reserved listening socket in __init__, so a
live listening fd existed for the whole of model initialization. Anything
forked during init inherited a duplicate, and because the frontends bind
with SO_REUSEPORT, the kernel could route connections to a child that
never accepts HTTP requests -- an extra no-op endpoint from Gym's point
of view.

Keep only the port number through init and adopt the socket in
_setup_openai_api_server, immediately before the frontends start. The
port holder keeps it bound and listening until then, so the pre-published
URL still cannot be stolen and early Gym probes still queue rather than
being refused.

Ports as reserved per rank, so this defers the handoff for every frontend
the driver reserved, not just one.

Mirrors the same fix upstream in NVIDIA-NeMo#4022 (b38c38f), adapted
to the per-frontend reservation map on this branch.

Signed-off-by: Siddharth Singh <sidsingh@nvidia.com>
cspades pushed a commit to ArEsKay3/RL that referenced this pull request Sep 8, 2026
The worker adopted the driver-reserved listening socket in __init__, so a
live listening fd existed for the whole of model initialization. Anything
forked during init inherited a duplicate, and because the frontends bind
with SO_REUSEPORT, the kernel could route connections to a child that
never accepts HTTP requests -- an extra no-op endpoint from Gym's point
of view.

Keep only the port number through init and adopt the socket in
_setup_openai_api_server, immediately before the frontends start. The
port holder keeps it bound and listening until then, so the pre-published
URL still cannot be stolen and early Gym probes still queue rather than
being refused.

Ports as reserved per rank, so this defers the handoff for every frontend
the driver reserved, not just one.

Mirrors the same fix upstream in NVIDIA-NeMo#4022 (b38c38f), adapted
to the per-frontend reservation map on this branch.

Signed-off-by: Siddharth Singh <sidsingh@nvidia.com>
cspades pushed a commit to ArEsKay3/RL that referenced this pull request Sep 9, 2026
The worker adopted the driver-reserved listening socket in __init__, so a
live listening fd existed for the whole of model initialization. Anything
forked during init inherited a duplicate, and because the frontends bind
with SO_REUSEPORT, the kernel could route connections to a child that
never accepts HTTP requests -- an extra no-op endpoint from Gym's point
of view.

Keep only the port number through init and adopt the socket in
_setup_openai_api_server, immediately before the frontends start. The
port holder keeps it bound and listening until then, so the pre-published
URL still cannot be stolen and early Gym probes still queue rather than
being refused.

Ports as reserved per rank, so this defers the handoff for every frontend
the driver reserved, not just one.

Mirrors the same fix upstream in NVIDIA-NeMo#4022 (b38c38f), adapted
to the per-frontend reservation map on this branch.

Signed-off-by: Siddharth Singh <sidsingh@nvidia.com>
cspades pushed a commit to ArEsKay3/RL that referenced this pull request Sep 9, 2026
The worker adopted the driver-reserved listening socket in __init__, so a
live listening fd existed for the whole of model initialization. Anything
forked during init inherited a duplicate, and because the frontends bind
with SO_REUSEPORT, the kernel could route connections to a child that
never accepts HTTP requests -- an extra no-op endpoint from Gym's point
of view.

Keep only the port number through init and adopt the socket in
_setup_openai_api_server, immediately before the frontends start. The
port holder keeps it bound and listening until then, so the pre-published
URL still cannot be stolen and early Gym probes still queue rather than
being refused.

Ports as reserved per rank, so this defers the handoff for every frontend
the driver reserved, not just one.

Mirrors the same fix upstream in NVIDIA-NeMo#4022 (b38c38f), adapted
to the per-frontend reservation map on this branch.

Signed-off-by: Siddharth Singh <sidsingh@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI:L1 Run doctests, unit tests, and functional tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants