mcore-build-and-dependency

작성자: nvidia

Megatron-LM을 위한 컨테이너 기반 개발 환경 설정 및 의존성 관리. CI 컨테이너 획득 및 실행, uv 패키지 관리 등을 다룹니다.

npx skills add https://github.com/nvidia/megatron-lm --skill mcore-build-and-dependency

Build & Dependency Guide

The core principle: build and develop inside containers — the CI container ships the correct CUDA toolkit, PyTorch build, and pre-compiled native extensions (TransformerEngine, DeepEP, …) that cannot be reproduced on a bare host.

Answer-First Constants

For text-only dependency or container questions, give these repo-specific facts up front before the longer workflow:

  • Run dependency work inside the Megatron-LM CI container, not on the host.
  • The container venv is /opt/venv, already on PATH.
  • Default dev uses docker/.ngc_version.dev and the dev uv group; lts uses docker/.ngc_version.lts and the lts uv group. The container::lts PR label selects the LTS path; otherwise CI uses dev.
  • lts is opt-in only when the user explicitly asks for it. It is the older long-term-support base, not a routine second lane — never attach container::lts, build the LTS image, or run the lts uv group on your own initiative, not even for a container or dependency change.
  • Install commands inside the container: uv sync --locked --group dev --group test, uv sync --locked --only-group linting, or uv sync --locked --group lts --group test.
  • Dependency edits use uv add <package> followed by uv lock, both inside the container.
  • docker/Dockerfile.ci.dev has main and jet stages. The jet stage needs an internal secret; local/public builds should pass --target main.

Why Containers

Megatron-LM depends on CUDA, NCCL, PyTorch with GPU support, TransformerEngine, and optional components like ModelOpt and DeepEP. Installing these on a bare host is fragile and hard to reproduce. The project ships Dockerfiles that pin every dependency.

Use the container as your development environment. This guarantees:

  • Identical CUDA / NCCL / cuDNN versions across all developers and CI.
  • uv.lock resolves the same way locally and in CI.
  • GPU-dependent operations (training, testing) work out of the box.

dev vs lts

Two image variants exist, each with its own Dockerfile, selected by the container::lts PR label. The defining difference is the base container: dev tracks the latest NGC PyTorch release, while lts ("long-term support") pins the previous, still-supported NGC PyTorch/CUDA release. container::lts exists to verify a change still works on that older base — the dependency differences below follow from it, they are not the point.

VariantBase image pinDockerfileWhere deps liveWhen used
devdocker/.ngc_version.dev (latest NGC release)docker/Dockerfile.ci.devpyproject.toml dev extra (uv-resolved)Default — CI, local development, most PRs
ltsdocker/.ngc_version.lts (older long-term-support release)docker/Dockerfile.ci.ltsdocker/lts/requirements.txt (pinned, sourced from main's uv.lock at AUT-479)Backward-compat lane — verify the change still runs on the older NGC base; extras not carried on it (ModelOpt, the CUDA-13 TransformerEngine build) are dropped

LTS deps used to live in [project.optional-dependencies].lts in pyproject.toml. They were moved into docker/lts/requirements.txt so pyproject.toml can host meaningful module-level extras without colliding with the LTS pin set. To bump an LTS dependency, edit the version in docker/lts/requirements.txt and rebuild docker/Dockerfile.ci.lts.

Use dev for everything. lts is off-limits unless the user explicitly asks for it. CI runs dev by default, and that is the only variant you touch on your own initiative. Treat container::lts as a high barrier, not a fallback: do not attach the label, build docker/Dockerfile.ci.lts, or run the lts uv group unless the user has explicitly requested LTS validation — not even for a container or dependency change. When they do ask, container::lts verifies the change still works on the older long-term-support PyTorch/CUDA base that LTS users run. The @pytest.mark.flaky_in_dev marker skips tests in the dev environment; @pytest.mark.flaky skips them in lts.


Step 1 — Acquire an Image

Option A — NVIDIA-internal: pull a CI-built image

⚠️ Requires access to the internal GitLab instance. See @tools/trigger_internal_ci.md for setup (adding the git remote, obtaining a token).

The internal GitLab CI publishes images to its container registry. Derive the registry host from your configured gitlab remote — the same host you use for trigger_internal_ci.py:

# Derive host from your 'gitlab' remote:
GITLAB_HOST=$(git remote get-url gitlab | sed 's/.*@\(.*\):.*/\1/')

docker pull ${GITLAB_HOST}/adlr/megatron-lm/mcore_ci_dev:main

Option B — Build from scratch (works for everyone)

⚠️ Dockerfile.ci.dev has two stages: main and jet. The jet stage requires an internal build secret and will fail without it. Always pass --target main to stop at the public stage.

# dev image (default)
docker build \
  --target main \
  --build-arg FROM_IMAGE_NAME=$(cat docker/.ngc_version.dev) \
  --build-arg IMAGE_TYPE=dev \
  -f docker/Dockerfile.ci.dev \
  -t megatron-lm:local .

# lts image (uses a dedicated Dockerfile; no IMAGE_TYPE arg)
docker build \
  --target main \
  --build-arg FROM_IMAGE_NAME=$(cat docker/.ngc_version.lts) \
  -f docker/Dockerfile.ci.lts \
  -t megatron-lm:local-lts .

Which image variant is used is controlled by the PR label container::lts; absent that label, dev is used.


Step 2 — Launch the Container

Option A — Local Docker runtime

docker run --rm --gpus all \
  -v $(pwd):/workspace \
  -w /workspace \
  megatron-lm:local \
  bash -c "<your command>"

Option B — Slurm cluster (for those without a local Docker runtime)

NVIDIA clusters typically use Pyxis + enroot. Request an interactive session:

srun \
  --nodes=1 --gpus-per-node=8 \
  --container-image megatron-lm:local \
  --container-mounts $(pwd):/workspace \
  --container-workdir /workspace \
  --pty bash

For clusters that require a .sqsh archive first:

enroot import -o megatron-lm.sqsh dockerd://megatron-lm:local
srun \
  --nodes=1 --gpus-per-node=8 \
  --container-image $(pwd)/megatron-lm.sqsh \
  --container-mounts $(pwd):/workspace \
  --container-workdir /workspace \
  --pty bash

Dependency Management

Dependencies are declared in pyproject.toml. The venv lives at /opt/venv inside the container (already on PATH).

All uv operations must be run inside the container. Never run uv sync / uv pip install on the host.

uv Dependency Groups

GroupPurpose
trainingRuntime training extras
devFull dev environment (TransformerEngine, ModelOpt, …)
testpytest, coverage, nemo-run
lintingruff, black, isort, pylint
buildCython, pybind11, nvidia-mathdx

The previous lts extra has been emptied. LTS deps are pinned in docker/lts/requirements.txt rather than pyproject.toml. Do not add new packages under [project.optional-dependencies].lts.

Install commands (inside the container):

# Full dev + test environment
uv sync --locked --group dev --group test

# Linting only
uv sync --locked --only-group linting

The LTS environment is reproduced by building docker/Dockerfile.ci.lts end-to-end; there is no uv sync-only equivalent because the LTS deps no longer live in pyproject.toml. The LTS top-level pin set is in docker/lts/requirements.txt; bump versions there and rebuild the image.

Several dependencies are sourced directly from git (TransformerEngine, nemo-run, FlashMLA, Emerging-Optimizers, nvidia-resiliency-ext). The locked uv.lock file pins exact revisions; update it with uv lock when changing pyproject.toml.

Adding a New Dependency

Follow this three-step workflow:

  1. Acquire a container image — see Step 1 above.

  2. Launch the container interactively — see Step 2 above.

  3. Update the lock file inside the container, then commit it:

    # Inside the container:
    uv add <package>          # adds to pyproject.toml and resolves
    uv lock                   # regenerates uv.lock
    # Exit the container, then on the host:
    git add pyproject.toml uv.lock
    git commit -S -s -m "build: add <package> dependency"
    

Resolving a merge conflict in uv.lock

uv.lock is machine-generated; never resolve conflicts manually. Instead:

git checkout origin/main -- uv.lock   # take main's version as the base
# then inside the container:
uv lock                               # re-resolve on top of your pyproject.toml changes

Common Pitfalls

ProblemCauseFix
uv sync --locked failsDependency conflict or stale uv.lockRe-run uv lock inside the container and commit updated lock
ModuleNotFoundError after pip installpip installed outside the uv-managed venvUse uv add and uv sync, never bare pip install
uv: command not found inside containerWrong container imageUse the megatron-lm image built from Dockerfile.ci.dev
No space left on device during uv opsCache fills container's /root/.cache/Mount a host cache dir via -v $HOME/.cache/uv:/root/.cache/uv
docker build fails with secret-related errorDockerfile.ci.dev has a jet stage that requires an internal secretAdd --target main to stop before the jet stage
access forbidden when pullingRegistry URL includes an explicit port (e.g. :5005)Use ${GITLAB_HOST}/adlr/... with no port — the sed extracts the hostname only

nvidia의 다른 스킬

compileiq-debug
nvidia
무언가 잘못되었을 때 사용: Search()가 멈추거나, 모든 평가가 INVALID_SCORE를 반환하거나, 점수가 개선되지 않거나, 모든 설정이 동일한 숫자를 반환하거나, ptxas 오류 등이 발생할 때
create-github-pr
nvidia
gh CLI를 사용하여 GitHub 풀 리퀘스트를 생성합니다. 사용자가 새 PR을 만들거나, 코드 리뷰를 제출하거나, 풀 리퀘스트를 열고자 할 때 사용합니다. 트리거 키워드 -…
nemoclaw-maintainer-cross-issue-sweep
nvidia
다른 열린 이슈들을 스캔하여 주어진 PR이 함께 수정하거나 실수로 망가뜨릴 수 있는 이슈를 찾습니다. 인접 수정 기회와 모순 위험을 file:line…과 함께 출력합니다.
fhir-basics
nvidia
에이전트에게 FHIR R4 API의 작동 방식, 사용 가능한 리소스, 검색 매개변수를 사용한 쿼리 방법, 모든 응답 형식을 올바르게 파싱하는 방법을 가르칩니다…
compileiq-validate-result
nvidia
검색이 완료된 후, 속도 향상을 청구하거나 ACF를 발송하기 전에 사용합니다. dump_results CSV를 로드하고, 상위 K개 후보(단일 목표)를 추출합니다…
changelog-audit
nvidia
릴리스 전에 Warp CHANGELOG.md를 감사합니다: 누락된 항목 복구, 사용자 영향별 정렬, 항목 언어 다듬기, 줄 바꿈, (릴리스 브랜치 모드) 비교 업데이트…
maintain-dynamic-plugins
nvidia
NeMo Relay 동적 플러그인 로더, 매니페스트, Rust 네이티브 SDK, gRPC 워커 프로토콜, Python 워커 SDK, 문서, 테스트 및 릴리스 워크플로 커버리지를 유지 관리합니다.
dgx-diagnose
nvidia
일반적인 DGX Station GB300 문제 진단 — CUDA 충돌, 잘못된 GPU 타겟팅, vLLM/SGLang 컨테이너 버그, MIG 상태 문제, NVLink/Fabric Manager 오류,…