chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:18:33 +08:00
commit 4ececc111a
2017 changed files with 331736 additions and 0 deletions
Executable
+155
View File
@@ -0,0 +1,155 @@
---
# Refer to the following link for the explanation of each params:
# http://releases.llvm.org/8.0.0/tools/clang/docs/ClangFormatStyleOptions.html
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
# This is deprecated
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
# disabling the below splits, else, they'll just add to the vertical length of source files!
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: WebKit
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
# Kept the below 2 to be the same as `IndentWidth` to keep everything uniform
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 4
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
# Enabling comment reflow causes doxygen comments to be messed up in their formats!
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
# Be consistent with indent-width, even for people who use tab for indentation!
TabWidth: 4
UseTab: Never
+5
View File
@@ -0,0 +1,5 @@
[flake8]
ignore = E,F403,F405,F541,F841,W
select = E9,F,W6
per-file-ignores =
__init__.py:F401
@@ -0,0 +1,10 @@
---
name: CI failure report
about: Report a DeepSpeed CI failure
title: "{{ env.GITHUB_WORKFLOW }} CI test failure"
labels: ci-failure
assignees: ''
---
The Nightly CI for {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/actions/runs/{{ env.GITHUB_RUN_ID }} failed.
@@ -0,0 +1,43 @@
---
name: Bug report (compression)
about: Create a DeepSpeed compression related issue to help us improve
title: "[BUG]"
labels: bug,compression
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**ds_report output**
Please run `ds_report` to give us details about your setup.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**System info (please complete the following information):**
- OS: [e.g. Ubuntu 18.04]
- GPU count and types [e.g. two machines with x8 A100s each]
- Interconnects (if applicable) [e.g., two machines connected with 100 Gbps IB]
- Python version
- Any other relevant info about your setup
**Launcher context**
Are you launching your experiment with the `deepspeed` launcher, MPI, or something else?
**Docker context**
Are you using a specific docker image that you can share?
**Additional context**
Add any other context about the problem here.
@@ -0,0 +1,44 @@
---
name: Bug report (DeepSpeed-Chat)
about: Create a DeepSpeed-Chat related issue to help us improve
title: "[BUG]"
labels: bug,deepspeed-chat
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is. Please include which training step you are using and which model you are training.
**Log output**
If you used `train.py` to launch the application, please include the contents of the output log file.
**To Reproduce**
Steps to reproduce the behavior:
1. Command/Script to reproduce
2. What packages are required and their versions
3. How to run the script
4. ...
**Expected behavior**
A clear and concise description of what you expected to happen.
**ds_report output**
Please run `ds_report` to give us details about your setup.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**System info (please complete the following information):**
- OS: [e.g. Ubuntu 18.04]
- GPU count and types [e.g. two machines with x8 A100s each]
- (if applicable) what [DeepSpeed-MII](https://github.com/deepspeedai/deepspeed-mii) version are you using
- (if applicable) Hugging Face Transformers/Accelerate/etc. versions
- Python version
- Any other relevant info about your setup
**Docker context**
Are you using a specific docker image that you can share?
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[REQUEST]"
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
@@ -0,0 +1,41 @@
---
name: Bug report (inference)
about: Create a DeepSpeed inference related issue to help us improve
title: "[BUG]"
labels: bug,inference
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Simple inference script to reproduce
2. What packages are required and their versions
3. How to run the script
4. ...
**Expected behavior**
A clear and concise description of what you expected to happen.
**ds_report output**
Please run `ds_report` to give us details about your setup.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**System info (please complete the following information):**
- OS: [e.g. Ubuntu 18.04]
- GPU count and types [e.g. two machines with x8 A100s each]
- (if applicable) what [DeepSpeed-MII](https://github.com/deepspeedai/deepspeed-mii) version are you using
- (if applicable) Hugging Face Transformers/Accelerate/etc. versions
- Python version
- Any other relevant info about your setup
**Docker context**
Are you using a specific docker image that you can share?
**Additional context**
Add any other context about the problem here.
@@ -0,0 +1,43 @@
---
name: Bug report (training)
about: Create a DeepSpeed training related issue to help us improve
title: "[BUG]"
labels: bug,training
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**ds_report output**
Please run `ds_report` to give us details about your setup.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**System info (please complete the following information):**
- OS: [e.g. Ubuntu 18.04]
- GPU count and types [e.g. two machines with x8 A100s each]
- Interconnects (if applicable) [e.g., two machines connected with 100 Gbps IB]
- Python version
- Any other relevant info about your setup
**Launcher context**
Are you launching your experiment with the `deepspeed` launcher, MPI, or something else?
**Docker context**
Are you using a specific docker image that you can share?
**Additional context**
Add any other context about the problem here.
+306
View File
@@ -0,0 +1,306 @@
# Diff-based CI test selection
This document explains the diff-driven test-selection system that lets some GPU CI
workflows run only the tests a PR could affect, instead of the whole suite, while
still satisfying Required status checks.
It currently drives **`modal-torch-latest`** (which runs `tests/unit/v1/` on
[modal.com](https://modal.com) GPUs), but is built to drive more workflows from
one config — see [Adding a workflow](#adding-a-new-workflow).
- [TL;DR](#tldr)
- [Why](#why)
- [Moving parts](#moving-parts)
- [How a decision is made](#how-a-decision-is-made)
- [Driving it (as a contributor)](#driving-it-as-a-contributor)
- [Changing it (as a maintainer)](#changing-it-as-a-maintainer)
- [Security model](#security-model)
- [Failure modes & guarantees](#failure-modes--guarantees)
- [FAQ / troubleshooting](#faq--troubleshooting)
## TL;DR
- On a PR, `ci/tests_fetcher.py` diffs your branch against the base branch, traces
the import graph from your changed files to the impacted tests, and writes the
list to `ci/.test_selection/test_list.txt`.
- The workflow runs pytest on just that list. `push` to `master` and manual runs
always run everything.
- It is **fail-safe**: anything it can't reason about safely → run the *full* suite.
It never silently runs *fewer* tests than reality.
- Preview locally:
```bash
python ci/tests_fetcher.py --base origin/master # what would CI run?
python ci/tests_fetcher.py --base origin/master --explain # ...and why?
```
- Force a full run: put `[test all]` (or `[no filter]`) in a commit message.
## Why
`modal-torch-latest` is a **Required** check, so it must report a status on every
PR — which means we can't use GitHub's path filters (`on.<event>.paths`) to skip
it, because a skipped Required job blocks merges. Instead, the job always runs but
*selects* what to test: a docs-only PR resolves to "no impacted tests" and exits
fast (still green), while a PR touching a leaf module runs only the tests that
import it.
The design is a small, self-contained take on HuggingFace `transformers`'
`utils/tests_fetcher.py`.
## Moving parts
| File | Role |
| --- | --- |
| `.github/workflows/modal-torch-latest.yml` | The workflow: a `collect-tests` job (runs the fetcher) gating a `deploy` job (runs pytest on modal). |
| `ci/tests_fetcher.py` | The selector. AST-parses the repo, builds an import graph, decides `all` / `subset` / `none`, writes the test-list file, emits a job summary. |
| `ci/test_tests_fetcher.py` | Self-tests for the selector (pure stdlib; run in `collect-tests`). |
| `ci/torch_latest.py` | The modal runner. Reads the test-list file and feeds it to pytest. |
| `ci/.test_selection/test_list.txt` | The hand-off artifact (one pytest target per line). Git-ignored. |
### Job flow
```
pull_request_target / push / workflow_dispatch
┌─────────────┴─────────────┐
│ collect-tests │ (no secrets; AST-only)
│ checkout PR head │
│ restore ci/ from base │
│ self-test the fetcher │
│ run tests_fetcher.py │
│ → mode (all|subset|none) │
│ → upload test_list.txt │
└─────────────┬──────────────┘
│ needs:
┌────────────────────────────┐
│ deploy │ (has modal/HF secrets)
│ if mode != none (or manual │
│ / collector failed) │
│ checkout PR head │
│ restore ci/ from base │
│ download test_list.txt │
│ modal run ci.torch_latest │
└────────────────────────────┘
```
`mode` controls `deploy`:
- **`none`** → `deploy` is skipped. The Required status is still satisfied (a
skipped dependent job counts as success here).
- **`subset`** → `deploy` runs pytest on exactly the impacted files.
- **`all`** → `deploy` runs the whole scope (`tests/unit/v1`).
## How a decision is made
`TestSelector.select()` in `ci/tests_fetcher.py` runs these checks in order; the
first that matches wins:
1. **No base ref** (push / manual) → `all`.
2. **Base ref unresolvable** → `all`.
3. **No merge-base** with the base (e.g. shallow clone, unrelated history) → `all`.
A diff here would be wrong, so we never narrow on it.
4. **Commit message tag** `[test all]` / `[no filter]` anywhere on the branch → `all`.
5. **A changed file matches a run-all glob** (`COMMON_RUN_ALL_GLOBS` +
the workflow's `extra_run_all_globs`) → `all`. These are files too central or
too dynamic to narrow safely: CI scripts, build system, `csrc/`, `op_builder/`,
`accelerator/`, shared fixtures (`tests/unit/common.py`, `tests/conftest.py`,
`pytest.ini`), and core runtime hubs (`deepspeed/__init__.py`,
`deepspeed/runtime/engine.py`, `deepspeed/comm/**`, `deepspeed/accelerator/**`, …).
6. **A deleted module is still imported** by a surviving file (a dangling import
the graph can't follow) → `all`. A *clean* deletion (importers removed/updated
in the same PR) does **not** trigger this.
7. Otherwise, **narrow via the import graph** (below). If nothing is impacted →
`none`; if everything is → `all`; else → `subset`.
### The import graph
- Nodes are Python files under the package roots: `deepspeed/**` and the `unit`
test-helper package at `tests/unit/**`.
- An edge `A → B` means "B imports A". The selector walks **backwards** from each
changed file to every test that (transitively) imports it.
- **Opaque hub modules** (`OPAQUE_MODULES`: `deepspeed`, `deepspeed.comm`,
`deepspeed.accelerator`): almost every test imports `unit.common`, which imports
these. Their `__init__.py` files eagerly pull in huge subtrees, so if treated as
normal nodes *any* `deepspeed/**` change would fan out to the whole suite. We
therefore don't expand their `__init__` imports; instead, changes to the hubs
themselves are caught by the run-all globs in step 5.
- **`conftest.py`** changes select every test under that conftest's directory.
- **New test files** are selected directly (they have no importers yet).
### Dynamic edges (`DYNAMIC_EDGES`)
Some dependencies are wired at runtime (monkey-patching, plugin/registry lookup,
JIT-loaded ops, `deepspeed.initialize()`-time `replace_module` injection), so a
test can depend on code it never `import`s. `DYNAMIC_EDGES` is a curated map of
`changed-file glob → extra test-path globs` that patches these blind spots. It is
additive on top of the static graph (and is only consulted if step 5 didn't
already short-circuit to `all`).
## Driving it (as a contributor)
### Preview what CI will run
The fetcher is pure stdlib — no DeepSpeed/torch install needed, just `git`:
```bash
# Selection for your branch vs. the base branch
python ci/tests_fetcher.py --base origin/master
cat ci/.test_selection/test_list.txt
# Explain *why* each test was selected (prints import chains)
python ci/tests_fetcher.py --base origin/master --explain
```
`--explain` output looks like:
```
deepspeed/shared.py impacts:
tests/unit/v1/test_shared.py <- deepspeed/shared.py
tests/unit/v1/moe/test_moe.py <- tests/unit/v1/moe/test_moe.py <- deepspeed/shared.py
```
### Escape hatches
- **Force the full suite for a push:** include `[test all]` (or `[no filter]`)
anywhere in a commit message on the branch.
- **Touch an infra file:** any change to a run-all glob runs everything.
- **Found a missed test?** It's likely a runtime/dynamic dependency the static
graph can't see — add a `DYNAMIC_EDGES` entry (see below) and/or report it.
## Changing it (as a maintainer)
All knobs live in `ci/tests_fetcher.py`. After any change, run the self-tests:
```bash
python ci/test_tests_fetcher.py # standalone
# or: pytest ci/test_tests_fetcher.py
```
### Add a run-all trigger
Add a glob to `TestSelector.COMMON_RUN_ALL_GLOBS` (shared across workflows) or to
a specific workflow's `extra_run_all_globs`. Globs match repo-root-relative POSIX
paths; `dir/**` matches everything under `dir/`.
### Add a dynamic edge
Add to `TestSelector.DYNAMIC_EDGES`:
```python
DYNAMIC_EDGES = {
# changed-file glob : test-path globs to pull in when it changes
"deepspeed/module_inject/**": ("tests/unit/v1/moe/**",),
}
```
Keep entries conservative: too broad just wastes GPU time; too narrow misses
coverage. Prefer fixing it here over widening a run-all glob when only a slice of
tests is truly affected.
### Mark a module opaque
If a new universal hub starts fanning every change out to the whole suite, add it
to `OPAQUE_MODULES` and (usually) add the hub file itself to the run-all globs so
real changes to it still run everything.
### Add a new workflow
The engine is config-driven (`WORKFLOWS` registry of `WorkflowConfig`). To drive
another workflow:
1. Add an entry:
```python
WORKFLOWS["my-workflow"] = WorkflowConfig(
name="my-workflow",
test_scopes=("tests/unit/v2",), # dirs this workflow runs
extra_run_all_globs=(".github/workflows/my-workflow.yml",),
)
```
2. In that workflow's YAML, mirror `modal-torch-latest.yml`'s `collect-tests` job
and call the fetcher with `--workflow my-workflow`.
3. Point the runner at `ci/.test_selection/test_list.txt`.
4. Add coverage to `ci/test_tests_fetcher.py` if the scope/behavior differs.
### Add a self-test
`ci/test_tests_fetcher.py` builds throwaway git repos (`TmpRepo`) from a synthetic
`BASELINE` tree and asserts the resulting `mode`/`tests`. Add a `test_*` function
for any new behavior; it runs both standalone and under pytest, and executes in
the `collect-tests` CI job, so a broken selector is caught before it mis-picks
tests.
## Security model
The workflow triggers on **`pull_request_target`**, so it runs in the base repo's
context and the `deploy` job has the modal/HF **secrets** in scope. To keep PRs
from abusing that:
- `collect-tests` holds **no secrets** and only **AST-parses** (never executes)
the PR tree.
- **Both jobs restore `ci/` from the base branch** before using it:
- `collect-tests` runs the **base** selector + self-tests. This job decides
whether the Required `deploy` runs, so it must not trust the PR's own
`ci/tests_fetcher.py` — otherwise a PR could rewrite it to emit `mode=none`
and skip CI while still going green. The diff is computed from git history, so
a PR's `ci/` changes still appear in the diff and (via the base selector's
`ci/**` run-all glob) force a full run.
- `deploy` runs the **base** orchestration (which drives `modal run` with the
secrets), so a PR can't repoint it at the secrets to exfiltrate them.
In both jobs the PR's `deepspeed/` + `tests/` are what gets parsed/tested.
- The `pull_request_target` trigger types are `review_requested`,
`ready_for_review`, and `synchronize`. Because `synchronize` re-runs on every
push to an open PR (not just on a maintainer action), the maintainer review is a
mitigation, **not** an absolute barrier — the base-`ci/` restore above is the
primary protection for the secrets.
> **Consequence:** changes to `ci/*` (including `tests_fetcher.py` itself) take
> effect under `pull_request_target` only after they're **merged**. Validate
> `ci/*` changes via a `pull_request`-triggered run or the `modal` CLI locally.
>
> **Bootstrap:** when the base branch has no selector yet (the PR that introduces
> it), the restored base `ci/` won't contain `tests_fetcher.py`; `collect-tests`
> detects this and falls back to running the full suite.
## Failure modes & guarantees
The selector is built to **fail safe — to `all`, never to `none`**:
- Missing/unresolvable base, no merge-base, a parse error on a file, or **any
unexpected exception** in the selector → it falls back to the full suite (the
top-level handler in `main()` logs the traceback and sets `mode=all`).
- If `collect-tests` fails entirely, `deploy` still runs (and the workflow has an
explicit "fail if selection failed" guard) so a broken collector can't let a PR
pass without testing.
- The only way to run *fewer* tests is a clean, well-understood narrow decision;
every uncertain case widens to everything.
Every run writes a summary to the GitHub job summary (mode, reason, and the
selected files) so the decision is auditable from the Actions UI.
## FAQ / troubleshooting
**My PR shows `mode=none` but I changed code.**
Either the change is non-Python / out of the workflow's scope, or your edits
aren't committed (the fetcher diffs *committed* history, `merge-base..HEAD`).
**A relevant test wasn't selected.**
Likely a runtime/dynamic dependency. Confirm with `--explain`, then add a
`DYNAMIC_EDGES` entry. As a stop-gap, push with `[test all]`.
**Everything runs even for a tiny change.**
You touched a run-all glob (CI/build/shared fixture/core runtime), or a hub module
fanned out. Check the job summary's `reason`. If a hub over-fans, consider
`OPAQUE_MODULES`.
**It ran the full suite and the summary says "shallow clone?" / "no merge-base".**
The runner didn't have enough history to compute the diff. `collect-tests` uses
`fetch-depth: 0`; if you changed that, restore full history for the base.
+121
View File
@@ -0,0 +1,121 @@
# Test-selection — implementation state / handoff
Working notes for the diff-based CI test-selection system, so the work can be
resumed without re-deriving context. For *how the system works / how to use it*,
see [`TEST_SELECTION.md`](TEST_SELECTION.md); this file is only about the **state
of the implementation**.
_Last updated: 2026-06-18._
## Status: complete & locally verified; in review on PR #8077
The system is implemented end-to-end and passes local checks. Opened as
[deepspeedai/DeepSpeed#8077](https://github.com/deepspeedai/DeepSpeed/pull/8077)
(scoped to `modal-torch-latest` first; replicate to other workflows if accepted).
It has **not** yet run a live `subset`/`deploy` on modal, so the first real runs
should be watched.
### Review fixes applied (Codex bot, PR #8077)
- **P1 — run the selector from trusted code.** `collect-tests` now restores `ci/`
from the base branch before running the selector + self-tests, so a PR can't
rewrite `tests_fetcher.py` to emit `mode=none` and skip the Required check. (A
PR's `ci/` changes still show in the diff and force a full run via `ci/**`.)
Includes a bootstrap fallback: if base has no `tests_fetcher.py` yet, run all.
- **P1 — hidden-file artifact.** `actions/upload-artifact@v4` skips dot-prefixed
paths by default; `ci/.test_selection/` is one. Added `include-hidden-files:
true` so `deploy`'s download doesn't fail.
> Reminder: under `pull_request_target`, `deploy` restores `ci/` from the base
> branch, so changes under `ci/*` (the fetcher included) only take effect once
> **merged**. To validate the live behavior before merge, trigger via a
> `pull_request`-based run or the `modal` CLI.
## What was built
A diff-driven selector that, on a PR, runs only the `tests/unit/v1` tests impacted
by the changed files, with a fail-safe fallback to the full suite. Driven by the
`modal-torch-latest` workflow.
### Files
| File | State | Notes |
| --- | --- | --- |
| `ci/tests_fetcher.py` | new/rewritten | Config-driven `TestSelector` class; import-graph selector. |
| `ci/test_tests_fetcher.py` | new | 12 stdlib self-tests over synthetic git repos. |
| `ci/torch_latest.py` | modified | Reads `DS_TEST_LIST_FILE`, runs pytest on the selected targets (falls back to full `tests/unit/v1`). |
| `.github/workflows/modal-torch-latest.yml` | rewritten | `collect-tests` (fetcher) gates `deploy` (modal). |
| `.github/workflows/TEST_SELECTION.md` | new | Full design + usage doc. |
| `.github/workflows/TEST_SELECTION_STATE.md` | new | This file. |
| `CONTRIBUTING.md` | modified | "Diff-based CI test selection" section + link. |
| `.gitignore` | modified | Ignores `ci/.test_selection/`. |
## Key design decisions (and why)
- **Always-runs Required job, selects instead of skips.** `modal-torch-latest` is a
Required check, so path filters can't skip it. `collect-tests` decides
`all|subset|none`; `none` skips `deploy` while still satisfying the Required
status.
- **`deploy` tests PR code but restores `ci/` from base.** Selection must reflect
PR code, but the orchestration that holds modal/HF secrets must not be
PR-controlled. (Security trade-off accepted earlier in the work.)
- **Opaque hub modules + curated run-all globs.** `deepspeed`, `deepspeed.comm`,
`deepspeed.accelerator` are opaque in the graph to stop universal fan-out; core
hubs (`deepspeed/__init__.py`, `runtime/engine.py`, `comm/**`, `accelerator/**`,
…) instead live in the run-all globs. (Coarseness fix accepted earlier.)
- **Fail-safe to `all`, never `none`.** Every uncertain case (no base, no
merge-base, parse error, unexpected exception) widens to the full suite.
### Improvements implemented in the latest pass (items #3#11)
- **#3** Degrade to `all` on any selector error (top-level guard in `main()`).
- **#4** `DYNAMIC_EDGES` map for runtime/dynamic deps the AST can't see
(seeded: `deepspeed/module_inject/** → tests/unit/v1/moe/**`).
- **#5** Deleted `.py` only forces `all` when a *surviving* file still imports it
(dangling import); clean deletions no longer over-trigger.
- **#6** GitHub job summary (`$GITHUB_STEP_SUMMARY`) with mode/reason/file list;
`reason` also on `$GITHUB_OUTPUT`.
- **#7** `--explain` prints import chains from changed files to selected tests.
- **#8** Escape hatches documented in `CONTRIBUTING.md` + `TEST_SELECTION.md`.
- **#9** Self-tests in `ci/test_tests_fetcher.py`, also run in `collect-tests`.
- **#10** Robust merge-base: explicit check, `all` if missing; workflow keeps
`fetch-depth: 0` with rationale.
- **#11** Multi-workflow config: `WORKFLOWS` registry + `WorkflowConfig` +
`--workflow` flag.
## Verification done locally
- `python ci/tests_fetcher.py` self-tests: **12/12 pass**
(narrowing, shared importers, core/comm/fixture run-all, commit tag, docs-only →
none, new test file, clean vs. dangling delete, dynamic edge, missing base).
- Real-repo smoke: `--base`, `--explain`, `--workflow` validation all behave.
- Confirmed `$GITHUB_OUTPUT` + `$GITHUB_STEP_SUMMARY` emission and the #3
error-fallback path directly.
- No linter errors.
Re-run the core check any time:
```bash
python ci/test_tests_fetcher.py
python ci/tests_fetcher.py --base origin/master --explain
```
## Open items / possible follow-ups
- **Live validation:** watch the first real PR; confirm `collect-tests` artifact
hand-off and `deploy` gating behave on Actions + modal.
- **`DYNAMIC_EDGES` is minimal.** Only one seeded edge. Expand as blind spots are
found (tests that fail on `master`'s full run but weren't selected on their PR
are the signal).
- **Single workflow wired.** The engine is config-driven (#11) but only
`modal-torch-latest` is registered/wired. Other GPU workflows could adopt it by
adding a `WorkflowConfig` and mirroring the `collect-tests` job.
- **Run-all glob tuning.** The core-hub list is a conservative first cut; revisit
if it proves too coarse (full runs on minor edits) or too narrow (missed impact).
- **No telemetry.** Consider logging selection stats over time to tune
globs/opaque-modules against real false-positive/negative rates.
+85
View File
@@ -0,0 +1,85 @@
name: amd-mi200
on:
workflow_dispatch:
pull_request:
paths:
- '.github/workflows/amd-mi200.yml'
- 'requirements/**'
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
issues: write
jobs:
amd-tests:
name: amd-mi200 / AMD MI200 tests
# The type of runner that the job will run on
runs-on: [self-hosted, amd, mi200]
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Install pytorch
run: |
pip install -U --cache-dir $TORCH_CACHE torch torchvision --index-url https://download.pytorch.org/whl/rocm6.0
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
# if needed switch to the last known good SHA until transformers@master is fixed
# git checkout 1cc453d33
git rev-parse --short HEAD
pip install .
- name: Install (ROCm) apex
run: |
git clone https://github.com/ROCmSoftwarePlatform/apex.git
CURRENT_VER=$(git rev-parse HEAD)
INSTALLED_VER=$(cat /blob/amd-apex/.venv_installed_version)
if [[ "$CURRENT_VER" != "$INSTALLED_VER" ]]; then
pip install -v --disable-pip-version-check --no-cache-dir --no-build-isolation --config-settings="--global-option=--cpp_ext" --config-settings="--global-option=--cuda_ext" --target=/blob/amd-apex/ --upgrade .
git rev-parse HEAD > /blob/amd-apex/.venv_installed_version
fi
echo PYTHONPATH=$PYTHONPATH:/blob/amd-apex/ >> $GITHUB_ENV
# Runs a set of commands using the runners shell
- name: Install deepspeed
run: |
pip install .[dev,1bit,autotuning]
#python -c "from deepspeed.env_report import cli_main; cli_main()"
ds_report
- name: Python environment
run: |
pip list
# Runs a set of commands using the runners shell
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
pytest $PYTEST_OPTS -n 4 --verbose unit/
pytest $PYTEST_OPTS -m 'sequential' unit/
- name: Open GitHub issue if nightly CI fails
if: ${{ failure() && (github.event_name == 'schedule') }}
uses: JasonEtco/create-an-issue@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
filename: .github/ISSUE_TEMPLATE/ci_failure_report.md
update_existing: true
+115
View File
@@ -0,0 +1,115 @@
################################################################################
# DeepSpeed CI - AWS L40S GPU Tests (HuggingFace Accelerate Integration)
#
# Runs the same tests as modal-accelerate.yml but on AWS self-hosted runners.
# Tests DeepSpeed integration with HuggingFace Accelerate library.
# Uses 4x NVIDIA L40S GPUs on g6e.12xlarge instances.
################################################################################
name: aws-accelerate
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-paths:
name: aws-accelerate / check paths
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.filter.outputs.run_tests }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
run_tests:
- '**'
- '!docs/**'
- '!blogs/**'
- '!deepspeed/inference/v2/**'
- '!tests/unit/inference/v2/**'
accelerate-tests:
name: aws-accelerate / accelerate integration tests
needs: check-paths
if: needs.check-paths.outputs.should_run == 'true'
runs-on: [self-hosted, gpu-ci, gpu-l40s, l40s-1gpu, aws]
timeout-minutes: 60
container:
image: nvidia/cuda:12.6.3-devel-ubuntu22.04
options: --gpus all --shm-size "32G"
env:
TORCH_VER: "2.7"
CUDA_VER: "12.6"
steps:
- name: Install system dependencies
run: |
apt-get update && apt-get install -y git git-lfs libaio-dev python3 python3-pip
git lfs install
ln -sf /usr/bin/python3 /usr/bin/python
- name: Checkout repository
uses: actions/checkout@v4
with:
lfs: true
- name: Install PyTorch
run: |
pip install torch==2.7.1 torchvision==0.22.1 torchaudio==2.7.1 --index-url https://download.pytorch.org/whl/cu126
- name: Install Python dependencies
run: |
pip install --upgrade pip
pip install -r requirements/requirements.txt
pip install -r requirements/requirements-dev.txt
pip install datasets
- name: Check environment
run: |
echo "=== GPU Information ==="
nvidia-smi
echo ""
echo "=== CUDA Version ==="
nvcc --version
echo ""
echo "=== Python/PyTorch Info ==="
python --version
python -c "import torch; print(f'PyTorch: {torch.__version__}')"
python -c "import torch; print(f'CUDA available: {torch.cuda.is_available()}')"
python -c "import torch; print(f'CUDA devices: {torch.cuda.device_count()}')"
python -c "import torch; print(f'BF16 support: {torch.cuda.is_bf16_supported()}')"
- name: Install DeepSpeed
run: |
# Initialize CUDA before install so setup.py can detect NCCL version
python -c "import torch; torch.cuda.init(); print(f'NCCL version: {torch.cuda.nccl.version()}')"
# Use --no-build-isolation so setup.py can access pre-installed PyTorch
pip install --no-build-isolation .
ds_report
# Debug: Check captured torch_info values
python -c "from deepspeed.git_version_info import torch_info; print(f'torch_info: {torch_info}')"
- name: Clone and install Accelerate
run: |
git clone https://github.com/huggingface/accelerate
pip install "./accelerate[testing]"
- name: Run Accelerate DeepSpeed tests
run: |
pytest --verbose ./accelerate/tests/deepspeed
+380
View File
@@ -0,0 +1,380 @@
################################################################################
# DeepSpeed CI - AWS L40S GPU Full Tests (PyTorch Latest)
#
# Runs the full DeepSpeed unit test suite on AWS self-hosted runners.
# Prefers 4x NVIDIA L40S GPUs on g6e.12xlarge instances, with AWS-side
# fallback to 8x A100 nodes when L40S capacity is unavailable.
#
# This workflow runs:
# - Parallel tests with pytest-xdist (-n 8)
# - Sequential tests marked with @pytest.mark.sequential
# - Nightly schedule: skips if no new commits since last successful run
################################################################################
name: aws-torch-latest-full
on:
schedule:
- cron: '0 8 * * *' # Daily at 08:00 UTC (midnight PST)
workflow_dispatch:
inputs:
torch_preset:
description: PyTorch preset to install for manual runs
required: false
default: '2.10.0-cu126'
type: choice
options:
- '2.7.1-cu126'
- '2.8.0-cu126'
- '2.9.1-cu126'
- '2.10.0-cu126'
- '2.11.0-cu126'
transformers_version:
description: Hugging Face Transformers PyPI package version to install
required: false
default: '4.50.0'
type: string
transformers_source:
description: Hugging Face Transformers source for manual runs
required: false
default: 'git'
type: choice
options:
- 'pypi'
- 'git'
transformers_ref:
description: Hugging Face Transformers git ref to install when source is git
required: false
default: 'main'
type: string
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-changes:
name: Check for new commits
runs-on: ubuntu-latest
if: github.event_name == 'schedule'
outputs:
has_changes: ${{ steps.check.outputs.has_changes }}
steps:
- name: Check for commits since last successful run
id: check
env:
GH_TOKEN: ${{ github.token }}
run: |
default_branch="${{ github.event.repository.default_branch }}"
last_sha=$(gh api \
"repos/${{ github.repository }}/actions/workflows/aws-torch-latest-full.yml/runs?status=success&event=schedule&branch=${default_branch}&per_page=1" \
--jq '.workflow_runs[0].head_sha // empty')
current_sha="${{ github.sha }}"
if [ -z "$last_sha" ]; then
echo "No previous successful run found - running tests"
echo "has_changes=true" >> "$GITHUB_OUTPUT"
elif [ "$last_sha" = "$current_sha" ]; then
echo "No new commits since last successful run ($last_sha) - skipping"
echo "has_changes=false" >> "$GITHUB_OUTPUT"
else
echo "New commits detected: $last_sha -> $current_sha - running tests"
echo "has_changes=true" >> "$GITHUB_OUTPUT"
fi
unit-tests:
name: Unit Tests (Full)
needs: [check-changes]
if: |
!cancelled() &&
(github.event_name == 'workflow_dispatch' || needs.check-changes.outputs.has_changes == 'true')
runs-on: [self-hosted, gpu-ci, gpu-l40s, l40s-4gpu, aws]
timeout-minutes: 180
container:
image: nvidia/cuda:12.6.3-devel-ubuntu22.04
# Mount /mnt/aio for async I/O tests (O_DIRECT requires native filesystem, not overlayfs)
options: --gpus all --shm-size "32G" -v /mnt/aio:/mnt/aio
env:
DEFAULT_TORCH_PRESET: '2.10.0-cu126'
DEFAULT_TRANSFORMERS_SOURCE: 'git'
DEFAULT_TRANSFORMERS_VERSION: '4.50.0'
DEFAULT_TRANSFORMERS_REF: 'main'
CUTLASS_PATH: /opt/cutlass
# Disable reuse_dist_env to prevent pool worker cleanup hangs in full test runs
DS_DISABLE_REUSE_DIST_ENV: '1'
steps:
- name: Install system dependencies
run: |
apt-get update && apt-get install -y git git-lfs libaio-dev pdsh python3 python3-pip
git lfs install
ln -sf /usr/bin/python3 /usr/bin/python
- name: Checkout repository
uses: actions/checkout@v4
with:
lfs: true
- name: Resolve dependency inputs
env:
GITHUB_EVENT_NAME: ${{ github.event_name }}
MANUAL_TORCH_PRESET: ${{ github.event.inputs.torch_preset || '' }}
MANUAL_TRANSFORMERS_SOURCE: ${{ github.event.inputs.transformers_source || '' }}
MANUAL_TRANSFORMERS_VERSION: ${{ github.event.inputs.transformers_version || '' }}
MANUAL_TRANSFORMERS_REF: ${{ github.event.inputs.transformers_ref || '' }}
run: |
if [ "$GITHUB_EVENT_NAME" = 'workflow_dispatch' ] && [ -n "$MANUAL_TORCH_PRESET" ]; then
selected_preset="$MANUAL_TORCH_PRESET"
else
selected_preset="$DEFAULT_TORCH_PRESET"
fi
if [ "$GITHUB_EVENT_NAME" = 'workflow_dispatch' ] && [ -n "$MANUAL_TRANSFORMERS_SOURCE" ]; then
transformers_source="$MANUAL_TRANSFORMERS_SOURCE"
else
transformers_source="$DEFAULT_TRANSFORMERS_SOURCE"
fi
if [ "$GITHUB_EVENT_NAME" = 'workflow_dispatch' ] && [ -n "$MANUAL_TRANSFORMERS_VERSION" ]; then
transformers_version="$MANUAL_TRANSFORMERS_VERSION"
else
transformers_version="$DEFAULT_TRANSFORMERS_VERSION"
fi
if [ "$GITHUB_EVENT_NAME" = 'workflow_dispatch' ] && [ -n "$MANUAL_TRANSFORMERS_REF" ]; then
transformers_ref="$MANUAL_TRANSFORMERS_REF"
else
transformers_ref="$DEFAULT_TRANSFORMERS_REF"
fi
if [ "$transformers_source" = 'git' ] && [ -z "$transformers_ref" ]; then
transformers_ref='main'
fi
case "$selected_preset" in
'2.7.1-cu126')
torch_install_version='2.7.1'
torchvision_install_version='0.22.1'
torchaudio_install_version='2.7.1'
torch_test_version='2.7'
cuda_test_version='12.6'
pytorch_index_url='https://download.pytorch.org/whl/cu126'
;;
'2.8.0-cu126')
torch_install_version='2.8.0'
torchvision_install_version='0.23.0'
torchaudio_install_version='2.8.0'
torch_test_version='2.8'
cuda_test_version='12.6'
pytorch_index_url='https://download.pytorch.org/whl/cu126'
;;
'2.9.1-cu126')
torch_install_version='2.9.1'
torchvision_install_version='0.24.1'
torchaudio_install_version='2.9.1'
torch_test_version='2.9'
cuda_test_version='12.6'
pytorch_index_url='https://download.pytorch.org/whl/cu126'
;;
'2.10.0-cu126')
torch_install_version='2.10.0'
torchvision_install_version='0.25.0'
torchaudio_install_version='2.10.0'
torch_test_version='2.10'
cuda_test_version='12.6'
pytorch_index_url='https://download.pytorch.org/whl/cu126'
;;
'2.11.0-cu126')
torch_install_version='2.11.0'
torchvision_install_version='0.26.0'
torchaudio_install_version='2.11.0'
torch_test_version='2.11'
cuda_test_version='12.6'
pytorch_index_url='https://download.pytorch.org/whl/cu126'
;;
*)
echo "Unsupported torch_preset: $selected_preset" >&2
exit 1
;;
esac
{
echo "SELECTED_TORCH_PRESET=$selected_preset"
echo "TORCH_INSTALL_VERSION=$torch_install_version"
echo "TORCHVISION_INSTALL_VERSION=$torchvision_install_version"
echo "TORCHAUDIO_INSTALL_VERSION=$torchaudio_install_version"
echo "TORCH_TEST_VERSION=$torch_test_version"
echo "CUDA_TEST_VERSION=$cuda_test_version"
echo "PYTORCH_INDEX_URL=$pytorch_index_url"
echo "TRANSFORMERS_SOURCE=$transformers_source"
echo "TRANSFORMERS_VERSION=$transformers_version"
echo "TRANSFORMERS_REF=$transformers_ref"
} >> "$GITHUB_ENV"
echo "Selected PyTorch preset: $selected_preset"
echo "Resolved install tuple: torch==$torch_install_version torchvision==$torchvision_install_version torchaudio==$torchaudio_install_version"
echo "Resolved test expectations: torch=$torch_test_version cuda=$cuda_test_version"
echo "Resolved PyTorch index: $pytorch_index_url"
echo "Resolved Transformers source: $transformers_source"
echo "Resolved Transformers version: $transformers_version"
echo "Resolved Transformers ref: $transformers_ref"
- name: Install CUTLASS
run: |
git clone --depth 1 --branch v3.5.1 https://github.com/NVIDIA/cutlass.git /opt/cutlass
echo "CUTLASS installed at /opt/cutlass"
ls -la /opt/cutlass/include/ | head -10
- name: Install PyTorch
run: |
pip install \
torch=="$TORCH_INSTALL_VERSION" \
torchvision=="$TORCHVISION_INSTALL_VERSION" \
torchaudio=="$TORCHAUDIO_INSTALL_VERSION" \
--index-url "$PYTORCH_INDEX_URL"
- name: Install Transformers
run: |
case "$TRANSFORMERS_SOURCE" in
'pypi')
pip install "transformers==$TRANSFORMERS_VERSION"
;;
'git')
git clone --filter=blob:none https://github.com/huggingface/transformers /tmp/transformers
cd /tmp/transformers
git checkout "$TRANSFORMERS_REF"
resolved_ref="$(git rev-parse HEAD)"
echo "TRANSFORMERS_RESOLVED_REF=$resolved_ref" >> "$GITHUB_ENV"
echo "Resolved Transformers git ref: $resolved_ref"
pip install .
;;
*)
echo "Unsupported TRANSFORMERS_SOURCE: $TRANSFORMERS_SOURCE" >&2
exit 1
;;
esac
python -c "import transformers; print('transformers:', transformers.__version__, transformers)"
- name: Install Python dependencies
run: |
pip install --upgrade pip
pip install -r requirements/requirements.txt
pip install -r requirements/requirements-dev.txt
pip install -r requirements/requirements-deepcompile.txt
pip install pytest-timeout pytest-instafail
- name: Check environment
run: |
echo "=== Selected PyTorch Preset ==="
echo "Preset: $SELECTED_TORCH_PRESET"
echo "Install tuple: torch==$TORCH_INSTALL_VERSION torchvision==$TORCHVISION_INSTALL_VERSION torchaudio==$TORCHAUDIO_INSTALL_VERSION"
echo "PyTorch index URL: $PYTORCH_INDEX_URL"
echo "Expected test versions: torch=$TORCH_TEST_VERSION cuda=$CUDA_TEST_VERSION"
echo "Transformers source: $TRANSFORMERS_SOURCE"
echo "Transformers version: $TRANSFORMERS_VERSION"
echo "Transformers ref: $TRANSFORMERS_REF"
echo "Transformers resolved ref: ${TRANSFORMERS_RESOLVED_REF:-}"
echo ""
echo "=== GPU Information ==="
nvidia-smi
echo ""
echo "=== CUDA Version ==="
nvcc --version
echo ""
echo "=== Python/PyTorch Info ==="
python --version
python -c "import torch; print(f'PyTorch: {torch.__version__}')"
python -c "import torch; print(f'CUDA available: {torch.cuda.is_available()}')"
python -c "import torch; print(f'CUDA devices: {torch.cuda.device_count()}')"
python -c "import torch; print(f'BF16 support: {torch.cuda.is_bf16_supported()}')"
echo ""
echo "=== CUTLASS ==="
echo "CUTLASS_PATH: $CUTLASS_PATH"
ls -la "$CUTLASS_PATH"/include/ | head -5
- name: Detect GPU architecture
run: |
python - <<'PY'
import os
import torch
torch.cuda.init()
major, minor = torch.cuda.get_device_capability(0)
arch = f"{major}.{minor}"
gpu_count = torch.cuda.device_count()
gpu_name = torch.cuda.get_device_name(0)
with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as env_file:
env_file.write(f"TORCH_CUDA_ARCH_LIST={arch}\n")
env_file.write(f"GPU_COUNT={gpu_count}\n")
print(f"Detected GPU: {gpu_name}")
print(f"Detected compute capability: {arch}")
print(f"Detected GPU count: {gpu_count}")
PY
- name: Install DeepSpeed
run: |
echo "Using TORCH_CUDA_ARCH_LIST=$TORCH_CUDA_ARCH_LIST"
# Initialize CUDA before install so setup.py can detect NCCL version
python -c "import torch; torch.cuda.init(); print(f'NCCL version: {torch.cuda.nccl.version()}')"
# Use --no-build-isolation so setup.py can access pre-installed PyTorch
pip install --no-build-isolation .[dev,1bit,autotuning,deepcompile]
ds_report
- name: Reinstall selected Transformers
run: |
case "$TRANSFORMERS_SOURCE" in
'pypi')
pip install --no-deps --force-reinstall "transformers==$TRANSFORMERS_VERSION"
;;
'git')
cd /tmp/transformers
pip install --no-deps --force-reinstall .
;;
*)
echo "Unsupported TRANSFORMERS_SOURCE: $TRANSFORMERS_SOURCE" >&2
exit 1
;;
esac
python -c "import transformers; print('transformers:', transformers.__version__, transformers)"
- name: Python environment
run: |
pip list
- name: Unit tests (parallel)
run: |
echo "Running parallel tests with TORCH_CUDA_ARCH_LIST=$TORCH_CUDA_ARCH_LIST on $GPU_COUNT GPUs"
cd tests
# Skip tests requiring unavailable hardware or known issues:
# - nvme checkpointing: no nvme device
# - GDS tests: no GPUDirect Storage support
# - launcher user_args: pdsh requires SSH server
# - zenflow: Stage 3 tests have pre-existing bugs + CUDA/fork issues
rm -rf /mnt/aio/pytest
pytest --instafail --timeout 600 --forked -n 8 --basetemp=/mnt/aio/pytest unit/ \
--ignore=unit/runtime/zero/test_nvme_checkpointing.py \
--ignore=unit/ops/aio/test_gds.py \
--ignore=unit/launcher/test_user_args.py \
--ignore=unit/runtime/zenflow \
--ignore=unit/ops/adam/test_zf_torch_adam.py \
--torch_ver="$TORCH_TEST_VERSION" --cuda_ver="$CUDA_TEST_VERSION"
- name: Unit tests (sequential)
run: |
echo "Running sequential tests with TORCH_CUDA_ARCH_LIST=$TORCH_CUDA_ARCH_LIST on $GPU_COUNT GPUs"
cd tests
rm -rf /mnt/aio/pytest
pytest --instafail --timeout 600 -m 'sequential' --basetemp=/mnt/aio/pytest unit/ \
--ignore=unit/runtime/zero/test_nvme_checkpointing.py \
--ignore=unit/ops/aio/test_gds.py \
--ignore=unit/launcher/test_user_args.py \
--ignore=unit/runtime/zenflow \
--ignore=unit/ops/adam/test_zf_torch_adam.py \
--ignore=unit/ops/deepspeed4science/test_DS4Sci_EvoformerAttention.py \
--torch_ver="$TORCH_TEST_VERSION" --cuda_ver="$CUDA_TEST_VERSION"
+113
View File
@@ -0,0 +1,113 @@
################################################################################
# DeepSpeed CI - AWS L40S GPU Tests (PyTorch Latest)
#
# Runs the same tests as modal-torch-latest.yml but on AWS self-hosted runners.
# Uses 4x NVIDIA L40S GPUs on g6e.12xlarge instances.
################################################################################
name: aws-torch-latest
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-paths:
name: aws-torch-latest / check paths
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.filter.outputs.run_tests }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
run_tests:
- '**'
- '!docs/**'
- '!blogs/**'
- '!deepspeed/inference/v2/**'
- '!tests/unit/inference/v2/**'
unit-tests:
name: aws-torch-latest / unit tests (v1)
needs: check-paths
if: needs.check-paths.outputs.should_run == 'true'
runs-on: [self-hosted, gpu-ci, gpu-l40s, l40s-4gpu, aws]
timeout-minutes: 60
container:
image: nvidia/cuda:12.6.3-devel-ubuntu22.04
options: --gpus all --shm-size "32G"
env:
TORCH_VER: "2.7"
CUDA_VER: "12.6"
steps:
- name: Install system dependencies
run: |
apt-get update && apt-get install -y git git-lfs libaio-dev python3 python3-pip
git lfs install
ln -sf /usr/bin/python3 /usr/bin/python
- name: Checkout repository
uses: actions/checkout@v4
with:
lfs: true
- name: Install PyTorch
run: |
pip install torch==2.7.1 torchvision==0.22.1 torchaudio==2.7.1 --index-url https://download.pytorch.org/whl/cu126
- name: Install Python dependencies
run: |
pip install --upgrade pip
pip install -r requirements/requirements.txt
pip install -r requirements/requirements-dev.txt
pip install -r requirements/requirements-deepcompile.txt
- name: Check environment
run: |
echo "=== GPU Information ==="
nvidia-smi
echo ""
echo "=== CUDA Version ==="
nvcc --version
echo ""
echo "=== Python/PyTorch Info ==="
python --version
python -c "import torch; print(f'PyTorch: {torch.__version__}')"
python -c "import torch; print(f'CUDA available: {torch.cuda.is_available()}')"
python -c "import torch; print(f'CUDA devices: {torch.cuda.device_count()}')"
python -c "import torch; print(f'BF16 support: {torch.cuda.is_bf16_supported()}')"
- name: Install DeepSpeed
run: |
# Initialize CUDA before install so setup.py can detect NCCL version
python -c "import torch; torch.cuda.init(); print(f'NCCL version: {torch.cuda.nccl.version()}')"
# Use --no-build-isolation so setup.py can access pre-installed PyTorch
pip install --no-build-isolation .
ds_report
# Debug: Check captured torch_info values
python -c "from deepspeed.git_version_info import torch_info; print(f'torch_info: {torch_info}')"
- name: Run unit tests
run: |
pytest -n 4 --forked --verbose tests/unit/v1/ --torch_ver=${{ env.TORCH_VER }} --cuda_ver=${{ env.CUDA_VER }}
- name: Run sequential unit tests
run: |
pytest --verbose -m 'sequential' tests/unit/v1/ --torch_ver=${{ env.TORCH_VER }} --cuda_ver=${{ env.CUDA_VER }}
+243
View File
@@ -0,0 +1,243 @@
name: cpu-torch-latest
on:
workflow_dispatch:
inputs:
torch_preset:
description: PyTorch CPU preset to install for manual runs
required: false
default: '2.10.0-cpu'
type: choice
options:
- '2.7.1-cpu'
- '2.8.0-cpu'
- '2.9.1-cpu'
- '2.10.0-cpu'
transformers_version:
description: Hugging Face Transformers PyPI package version to install
required: false
default: '4.50.0'
type: string
transformers_source:
description: Hugging Face Transformers source for manual runs
required: false
default: 'git'
type: choice
options:
- 'pypi'
- 'git'
transformers_ref:
description: Hugging Face Transformers git ref to install when source is git
required: false
default: 'main'
type: string
pull_request:
merge_group:
branches: [ master ]
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-paths:
name: cpu-torch-latest / check paths
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.non_pr.outputs.should_run || steps.filter.outputs.run_tests }}
steps:
- id: non_pr
if: github.event_name != 'pull_request'
run: echo "should_run=true" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@v4
if: github.event_name == 'pull_request'
- uses: dorny/paths-filter@v3
id: filter
if: github.event_name == 'pull_request'
with:
predicate-quantifier: every
filters: |
run_tests:
- '**'
- '!docs/**'
- '!blogs/**'
- '!deepspeed/inference/v2/**'
- '!tests/unit/inference/v2/**'
unit-tests:
name: cpu-torch-latest / unit tests
needs: check-paths
if: ${{ !cancelled() && (needs.check-paths.result != 'success' || needs.check-paths.outputs.should_run == 'true') }}
runs-on: ubuntu-24.04
env:
DEFAULT_TORCH_PRESET: '2.10.0-cpu'
DEFAULT_TRANSFORMERS_SOURCE: 'git'
DEFAULT_TRANSFORMERS_VERSION: '4.50.0'
DEFAULT_TRANSFORMERS_REF: 'main'
steps:
- name: Fail if path filter failed
if: needs.check-paths.result != 'success'
run: exit 1
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Install system packages
run: |
sudo apt-get install -y numactl pdsh
- name: Resolve dependency inputs
env:
GITHUB_EVENT_NAME: ${{ github.event_name }}
MANUAL_TORCH_PRESET: ${{ github.event.inputs.torch_preset || '' }}
MANUAL_TRANSFORMERS_SOURCE: ${{ github.event.inputs.transformers_source || '' }}
MANUAL_TRANSFORMERS_VERSION: ${{ github.event.inputs.transformers_version || '' }}
MANUAL_TRANSFORMERS_REF: ${{ github.event.inputs.transformers_ref || '' }}
run: |
if [ "$GITHUB_EVENT_NAME" = 'workflow_dispatch' ] && [ -n "$MANUAL_TORCH_PRESET" ]; then
selected_preset="$MANUAL_TORCH_PRESET"
else
selected_preset="$DEFAULT_TORCH_PRESET"
fi
if [ "$GITHUB_EVENT_NAME" = 'workflow_dispatch' ] && [ -n "$MANUAL_TRANSFORMERS_SOURCE" ]; then
transformers_source="$MANUAL_TRANSFORMERS_SOURCE"
else
transformers_source="$DEFAULT_TRANSFORMERS_SOURCE"
fi
if [ "$GITHUB_EVENT_NAME" = 'workflow_dispatch' ] && [ -n "$MANUAL_TRANSFORMERS_VERSION" ]; then
transformers_version="$MANUAL_TRANSFORMERS_VERSION"
else
transformers_version="$DEFAULT_TRANSFORMERS_VERSION"
fi
if [ "$GITHUB_EVENT_NAME" = 'workflow_dispatch' ] && [ -n "$MANUAL_TRANSFORMERS_REF" ]; then
transformers_ref="$MANUAL_TRANSFORMERS_REF"
else
transformers_ref="$DEFAULT_TRANSFORMERS_REF"
fi
if [ "$transformers_source" = 'git' ] && [ -z "$transformers_ref" ]; then
transformers_ref='main'
fi
case "$selected_preset" in
'2.7.1-cpu')
torch_install_version='2.7.1'
torchvision_install_version='0.22.1'
torch_test_version='2.7'
;;
'2.8.0-cpu')
torch_install_version='2.8.0'
torchvision_install_version='0.23.0'
torch_test_version='2.8'
;;
'2.9.1-cpu')
torch_install_version='2.9.1'
torchvision_install_version='0.24.1'
torch_test_version='2.9'
;;
'2.10.0-cpu')
torch_install_version='2.10.0'
torchvision_install_version='0.25.0'
torch_test_version='2.10'
;;
*)
echo "Unsupported torch_preset: $selected_preset" >&2
exit 1
;;
esac
{
echo "SELECTED_TORCH_PRESET=$selected_preset"
echo "TORCH_INSTALL_VERSION=$torch_install_version"
echo "TORCHVISION_INSTALL_VERSION=$torchvision_install_version"
echo "TORCH_TEST_VERSION=$torch_test_version"
echo "PYTORCH_INDEX_URL=https://download.pytorch.org/whl/cpu"
echo "TRANSFORMERS_SOURCE=$transformers_source"
echo "TRANSFORMERS_VERSION=$transformers_version"
echo "TRANSFORMERS_REF=$transformers_ref"
} >> "$GITHUB_ENV"
echo "Selected PyTorch preset: $selected_preset"
echo "Resolved install tuple: torch==$torch_install_version torchvision==$torchvision_install_version"
echo "Resolved test expectation: torch=$torch_test_version"
echo "Resolved Transformers source: $transformers_source"
echo "Resolved Transformers version: $transformers_version"
echo "Resolved Transformers ref: $transformers_ref"
- name: Install PyTorch
run: |
pip install \
torch=="$TORCH_INSTALL_VERSION" \
torchvision=="$TORCHVISION_INSTALL_VERSION" \
--index-url "$PYTORCH_INDEX_URL"
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install Transformers
run: |
case "$TRANSFORMERS_SOURCE" in
'pypi')
pip install "transformers==$TRANSFORMERS_VERSION"
;;
'git')
git clone --filter=blob:none https://github.com/huggingface/transformers /tmp/transformers
cd /tmp/transformers
git checkout "$TRANSFORMERS_REF"
resolved_ref="$(git rev-parse HEAD)"
echo "TRANSFORMERS_RESOLVED_REF=$resolved_ref" >> "$GITHUB_ENV"
echo "Resolved Transformers git ref: $resolved_ref"
pip install .
;;
*)
echo "Unsupported TRANSFORMERS_SOURCE: $TRANSFORMERS_SOURCE" >&2
exit 1
;;
esac
python -c "import transformers; print('transformers:', transformers.__version__, transformers)"
- name: Install deepspeed
run: |
pip install .[dev,autotuning]
ds_report
- name: Reinstall selected Transformers
run: |
case "$TRANSFORMERS_SOURCE" in
'pypi')
pip install --no-deps --force-reinstall "transformers==$TRANSFORMERS_VERSION"
;;
'git')
cd /tmp/transformers
pip install --no-deps --force-reinstall .
;;
*)
echo "Unsupported TRANSFORMERS_SOURCE: $TRANSFORMERS_SOURCE" >&2
exit 1
;;
esac
python -c "import transformers; print('transformers:', transformers.__version__, transformers)"
- name: Python environment
run: |
pip list
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
HF_HOME=/tmp/hf_home/ pytest $PYTEST_OPTS --forked -n 4 unit/ --torch_ver="$TORCH_TEST_VERSION"
HF_HOME=/tmp/hf_home/ pytest $PYTEST_OPTS --forked -m 'sequential' unit/ --torch_ver="$TORCH_TEST_VERSION"
+585
View File
@@ -0,0 +1,585 @@
# Copyright (c) DeepSpeed Team.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
name: DCO / required
on:
pull_request:
branches:
- master
merge_group:
branches:
- master
permissions:
checks: read
contents: read
pull-requests: read
jobs:
dco_required:
name: DCO / required
runs-on: ubuntu-latest
steps:
- name: Validate commit signoffs
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
python - <<'PY'
import json
import os
import re
import sys
import urllib.error
import urllib.parse
import urllib.request
# GitHub App ID for https://github.com/apps/dco.
PROBOT_DCO_APP_ID = 1861
def load_event(path):
with open(path, encoding="utf-8") as f:
return json.load(f)
def fail(message):
print(f"::error::{message}")
sys.exit(1)
def extract_pr_numbers_from_refs(*refs):
numbers = []
text = "\n".join(value for value in refs if value)
for match in re.finditer(r"(?:^|[/-])pr-(\d+)(?=$|[/-])", text):
number = int(match.group(1))
if number not in numbers:
numbers.append(number)
return numbers
def extract_pull_request_number_from_refs(*refs):
text = "\n".join(value for value in refs if value)
match = re.search(r"(?:^|/)pull/(\d+)(?=/|$)", text)
if match:
return int(match.group(1))
return None
def discover_pr_numbers(event_name, event, github_ref):
if event_name == "pull_request":
number = event.get("number")
if number is not None:
try:
return [int(number)]
except (TypeError, ValueError):
fail(f"pull_request event had non-integer number: {number!r}")
try:
return [int(event["pull_request"]["number"])]
except (KeyError, TypeError, ValueError):
ref_number = extract_pull_request_number_from_refs(
os.environ.get("GITHUB_REF"),
github_ref,
event.get("ref"),
)
if ref_number is not None:
return [ref_number]
fail("pull_request event did not include a pull request number")
if event_name == "merge_group":
merge_group = event.get("merge_group", {})
numbers = extract_pr_numbers_from_refs(
merge_group.get("head_ref"),
os.environ.get("GITHUB_REF_NAME"),
github_ref,
event.get("ref"),
)
if numbers:
return numbers
fail(
"merge_group event did not include a parseable PR number. "
f"head_ref={merge_group.get('head_ref')!r} "
f"GITHUB_REF_NAME={os.environ.get('GITHUB_REF_NAME')!r} "
f"GITHUB_REF={github_ref!r}"
)
fail(f"Unsupported event for DCO check: {event_name}")
def graphql_request(query, variables, token):
body = json.dumps({"query": query, "variables": variables}).encode("utf-8")
req = urllib.request.Request(
"https://api.github.com/graphql",
data=body,
headers={
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"X-GitHub-Api-Version": "2022-11-28",
"User-Agent": "deepspeed-dco-check",
},
)
try:
with urllib.request.urlopen(req, timeout=30) as response:
payload = json.loads(response.read().decode("utf-8"))
except urllib.error.HTTPError as exc:
detail = exc.read().decode("utf-8", errors="replace")
fail(f"GitHub GraphQL request failed: HTTP {exc.code} {detail}")
except urllib.error.URLError as exc:
fail(f"GitHub GraphQL request failed: {exc}")
if payload.get("errors"):
fail(f"GitHub GraphQL returned errors: {payload['errors']}")
return payload["data"]
def rest_request(path, token, fatal=True):
url = f"https://api.github.com/repos/{os.environ['GITHUB_REPOSITORY']}{path}"
items = []
while url:
req = urllib.request.Request(
url,
headers={
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {token}",
"X-GitHub-Api-Version": "2022-11-28",
"User-Agent": "deepspeed-dco-check",
},
)
try:
with urllib.request.urlopen(req, timeout=30) as response:
data = json.loads(response.read().decode("utf-8"))
link = response.headers.get("Link", "")
except urllib.error.HTTPError as exc:
detail = exc.read().decode("utf-8", errors="replace")
message = (
f"GitHub REST request failed for {path}: "
f"HTTP {exc.code} {detail}"
)
if fatal:
fail(message)
print(f"::warning::{message}")
return None
except urllib.error.URLError as exc:
message = f"GitHub REST request failed for {path}: {exc}"
if fatal:
fail(message)
print(f"::warning::{message}")
return None
if isinstance(data, list):
items.extend(data)
else:
commits = data.get("commits")
if isinstance(commits, list):
items.extend(commits)
else:
return data
next_url = None
for part in link.split(","):
if 'rel="next"' in part:
next_url = part[part.find("<") + 1:part.find(">")]
break
url = next_url
return items
def fetch_compare_commits(base_sha, head_sha, token):
base = urllib.parse.quote(base_sha, safe="")
head = urllib.parse.quote(head_sha, safe="")
return rest_request(f"/compare/{base}...{head}?per_page=100", token)
def fetch_commit(sha, token):
ref = urllib.parse.quote(sha, safe="")
return rest_request(f"/commits/{ref}", token, fatal=False)
def has_successful_probot_dco(head_sha, token):
if not head_sha:
return False
ref = urllib.parse.quote(head_sha, safe="")
payload = rest_request(
f"/commits/{ref}/check-runs?check_name=DCO&filter=latest",
token,
fatal=False,
)
if not payload:
return False
for check_run in payload.get("check_runs", []):
app = check_run.get("app") or {}
is_probot_dco = app.get("slug") == "dco" or app.get("id") == PROBOT_DCO_APP_ID
if (
check_run.get("name") == "DCO"
and is_probot_dco
and check_run.get("status") == "completed"
and check_run.get("conclusion") == "success"
):
print(
"Found successful Probot DCO check for PR head "
f"{head_sha}; accepting Probot result."
)
return True
return False
def fetch_pr_commits(owner, repo, number, token):
query = """
query($owner: String!, $repo: String!, $number: Int!, $cursor: String) {
repository(owner: $owner, name: $repo) {
PULL_REQUEST_FIELD(number: $number) {
baseRefName
baseRepository {
nameWithOwner
}
headRefOid
commits(first: 100, after: $cursor) {
pageInfo {
hasNextPage
endCursor
}
nodes {
commit {
oid
message
author {
name
email
user {
login
}
}
committer {
name
email
user {
login
}
}
parents(first: 2) {
totalCount
}
}
}
}
}
}
}
""".replace("PULL_REQUEST_FIELD", "pull" + "Request")
cursor = None
commits = []
base_ref = None
base_repo = None
head_sha = None
while True:
data = graphql_request(
query,
{"owner": owner, "repo": repo, "number": number, "cursor": cursor},
token,
)
pull_request = data["repository"]["pull" + "Request"]
if pull_request is None:
fail(f"PR #{number} was not found")
base_ref = pull_request["baseRefName"]
base_repo = pull_request["baseRepository"]["nameWithOwner"]
head_sha = pull_request["headRefOid"]
connection = pull_request["commits"]
commits.extend(connection["nodes"])
page_info = connection["pageInfo"]
if not page_info["hasNextPage"]:
break
cursor = page_info["endCursor"]
if not cursor:
fail(f"PR #{number} pagination did not return an end cursor")
return {
"base_ref": base_ref,
"base_repo": base_repo,
"head_sha": head_sha,
"commits": commits,
}
def has_signed_off_by(message):
return bool(
re.search(
r"^Signed-off-by:\s+\S.*$",
message,
flags=re.MULTILINE,
)
)
def commit_subject(message):
return message.splitlines()[0] if message.splitlines() else "(empty subject)"
def actor_from_graphql(git_actor):
git_actor = git_actor or {}
user = git_actor.get("user") or {}
return {
"login": user.get("login") or "",
"type": "",
"name": git_actor.get("name") or "",
"email": git_actor.get("email") or "",
}
def actor_from_rest(api_actor, git_actor):
api_actor = api_actor or {}
git_actor = git_actor or {}
return {
"login": api_actor.get("login") or "",
"type": api_actor.get("type") or "",
"name": git_actor.get("name") or "",
"email": git_actor.get("email") or "",
}
def is_trusted_bot_actor(actor):
actor = actor or {}
return str(actor.get("type", "")).lower() == "bot"
def has_bot_marker(actor):
actor = actor or {}
for key in ("login", "name", "email"):
value = str(actor.get(key, "")).lower()
if "[bot]" in value:
return True
return False
def actor_label(actor):
actor = actor or {}
return (
actor.get("login")
or actor.get("name")
or actor.get("email")
or "unknown actor"
)
def is_verified_bot_authored(record, token):
author = record.get("author") or {}
if is_trusted_bot_actor(author):
return True
if not token or not has_bot_marker(author):
return False
commit = fetch_commit(record["sha"], token)
if not commit:
return False
api_author = commit.get("author") or {}
if str(api_author.get("type", "")).lower() != "bot":
return False
author["login"] = api_author.get("login") or author.get("login") or ""
author["type"] = api_author.get("type") or author.get("type") or ""
return True
def validate_records(records, seen, token=None, skip_sha=None):
failures = []
checked = []
skipped = []
accepted = []
for record in records:
oid = record["sha"]
if oid in seen:
continue
seen.add(oid)
if skip_sha and oid == skip_sha:
skipped.append(oid)
print(f"Skipping merge group head commit {oid}")
continue
if record["parent_count"] > 1:
skipped.append(oid)
print(f"Skipping merge commit {oid}")
continue
if is_verified_bot_authored(record, token):
skipped.append(oid)
print(
"Skipping bot-authored commit "
f"{oid} ({actor_label(record.get('author'))})"
)
continue
checked.append(oid)
message = record.get("message") or ""
if not has_signed_off_by(message):
failures.append({"sha": oid, "subject": commit_subject(message)})
return {
"checked": checked,
"skipped": skipped,
"accepted": accepted,
"failures": failures,
}
def validate_pr(owner, repo, number, token, seen):
print(f"Validating DCO trailers for PR #{number}")
pull_request = fetch_pr_commits(owner, repo, number, token)
expected_base = f"{owner}/{repo}"
if (
pull_request["base_repo"] != expected_base
or pull_request["base_ref"] != "master"
):
fail(
f"PR #{number} targets "
f"{pull_request['base_repo']}:{pull_request['base_ref']}, "
f"expected {expected_base}:master"
)
records = []
for node in pull_request["commits"]:
commit = node["commit"]
records.append(
{
"sha": commit["oid"],
"message": commit.get("message") or "",
"author": actor_from_graphql(commit.get("author")),
"committer": actor_from_graphql(commit.get("committer")),
"parent_count": commit["parents"]["totalCount"],
}
)
if not records:
return {
"checked": [],
"skipped": [],
"accepted": [],
"failures": [
{
"sha": f"PR #{number}",
"subject": "no commits returned by pull request commits API",
}
],
}
if has_successful_probot_dco(pull_request["head_sha"], token):
accepted = []
for record in records:
oid = record["sha"]
if oid not in seen:
seen.add(oid)
accepted.append(oid)
return {
"checked": [],
"skipped": [],
"accepted": accepted,
"failures": [],
}
return validate_records(records, seen, token=token)
def verify_merge_group_range_coverage(event, token, seen):
merge_group = event.get("merge_group", {})
base_sha = merge_group.get("base_sha")
head_sha = merge_group.get("head_sha") or os.environ.get("GITHUB_SHA")
if not base_sha or not head_sha:
fail(
"merge_group event did not include base_sha and head_sha. "
f"base_sha={base_sha!r} head_sha={head_sha!r} "
f"GITHUB_SHA={os.environ.get('GITHUB_SHA')!r}"
)
print(f"Checking merge group range coverage {base_sha}...{head_sha}")
commits = fetch_compare_commits(base_sha, head_sha, token)
records = []
for commit in commits:
git_commit = commit.get("commit", {}) or {}
records.append(
{
"sha": commit.get("sha", ""),
"message": git_commit.get("message", "") or "",
"author": actor_from_rest(
commit.get("author"),
git_commit.get("author"),
),
"committer": actor_from_rest(
commit.get("committer"),
git_commit.get("committer"),
),
"parent_count": len(commit.get("parents", [])),
}
)
if not commits:
fail(f"merge_group compare range {base_sha}...{head_sha} returned no commits")
return validate_records(records, seen, token=token, skip_sha=head_sha)
def main():
repository = os.environ["GITHUB_REPOSITORY"]
owner, repo = repository.split("/", 1)
event_name = os.environ["GITHUB_EVENT_NAME"]
github_ref = os.environ.get("GITHUB_REF")
token = os.environ["GITHUB_TOKEN"]
event = load_event(os.environ["GITHUB_EVENT_PATH"])
pull_numbers = discover_pr_numbers(event_name, event, github_ref)
failures = []
checked = set()
skipped = set()
accepted = set()
seen = set()
for number in sorted(pull_numbers):
result = validate_pr(owner, repo, number, token, seen)
failures.extend(result["failures"])
checked.update(result["checked"])
skipped.update(result["skipped"])
accepted.update(result.get("accepted", []))
if event_name == "merge_group":
result = verify_merge_group_range_coverage(
event,
token,
seen,
)
failures.extend(result["failures"])
checked.update(result["checked"])
skipped.update(result["skipped"])
accepted.update(result.get("accepted", []))
if failures:
for failure in failures:
print(f"::error::{failure['sha']}: {failure['subject']}")
fail(
f"{len(failures)} commit(s) are missing a Signed-off-by trailer."
)
print(
"DCO validation passed for "
f"{len(pull_numbers)} pull request(s): "
f"checked {len(checked)} commit(s), "
f"accepted {len(accepted)} commit(s) via Probot DCO, "
f"skipped {len(skipped)} merge, bot, or synthetic commit(s)."
)
if __name__ == "__main__":
main()
PY
+41
View File
@@ -0,0 +1,41 @@
name: Formatting
on:
workflow_dispatch:
pull_request:
branches:
'**'
merge_group:
branches: [ master ]
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# formatting and basic install on cpu-only machine
unit-tests:
name: formatting / formatting checks
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: environment
run: |
which python
python --version
- name: Install dependencies
run: |
# Previously we would do pip install .[dev] but this is causing out of
# space errors start with torch 2.1.0 release
grep -E "clang-format|pre-commit" requirements/requirements-dev.txt | xargs pip install
- name: Formatting checks
run: |
pip show pre-commit clang-format
pre-commit run --all-files
+88
View File
@@ -0,0 +1,88 @@
name: hpu-gaudi2-nightly
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
pull_request:
paths:
- ".github/workflows/hpu-gaudi2-nightly.yml"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
issues: write
jobs:
unit-tests:
name: hpu-gaudi2-nightly / unit tests
# The type of runner that the job will run on
runs-on: [self-hosted, intel, gaudi2]
container:
image: vault.habana.ai/gaudi-docker/1.21.0/ubuntu22.04/habanalabs/pytorch-installer-2.6.0:latest
ports:
- 80
options: --runtime=habana -e HABANA_VISIBLE_DEVICES=all -e OMPI_MCA_btl_vader_single_copy_mechanism=none --cap-add=sys_nice
env:
PT_HPU_LAZY_MODE: 0
TORCHINDUCTOR_COMPILE_THREADS: 1
TEST_LIST: |
test_adamw.py
test_bf16.py
test_ds_config_dict.py
test_dynamic_loss_scale.py
test_latest_checkpoint.py
test_moe_checkpoint.py
test_multi_output_model.py
test_other_optimizer.py
test_pipe.py
test_pipeline.py
test_universal_checkpoint.py
test_zero_context_return.py
test_zero_leaf_module.py
test_zero_offloadpp.py
test_zero_tiled.py
test_autotp_training.py
test_ulysses.py
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
- name: Check container state
run: |
ldd --version
hl-smi -L
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
git rev-parse --short HEAD
pip install .
- name: Install deepspeed
run: |
pip install .[dev,autotuning]
ds_report
- name: Python environment
run: |
pip list
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
export PT_HPU_LAZY_MODE=${PT_HPU_LAZY_MODE}
export TORCHINDUCTOR_COMPILE_THREADS=${TORCHINDUCTOR_COMPILE_THREADS}
TEST_LIST=$(echo "$TEST_LIST" | awk 'NF{printf "%s%s", (NR>1 ? " or " : ""), $0} END{if (NR>1) print ""}')
echo "TEST_LIST ${TEST_LIST}"
pytest --verbose unit/ -k "${TEST_LIST}"
+139
View File
@@ -0,0 +1,139 @@
name: hpu-gaudi2
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
pull_request:
paths:
- ".github/workflows/hpu-gaudi2.yml"
- "accelerator/hpu_accelerator.py"
- "op_builder/hpu/**"
- "deepspeed/runtime/engine.py"
- "deepspeed/runtime/bf16_optimizer.py"
- "deepspeed/runtime/zero/stage_1_and_2.py"
- "deepspeed/runtime/zero/stage3.py"
- "deepspeed/runtime/zero/partition_parameters.py"
- "deepspeed/runtime/zero/partitioned_param_coordinator.py"
- "deepspeed/runtime/zero/parameter_offload.py"
- "deepspeed/runtime/pipe/engine.py"
- "deepspeed/runtime/utils.py"
- "deepspeed/inference/engine.py"
- "deepspeed/module_inject/auto_tp.py"
- "deepspeed/module_inject/replace_module.py"
- "deepspeed/module_inject/load_checkpoint.py"
- "deepspeed/module_inject/inject.py"
- "deepspeed/ops/transformer/**"
- "deepspeed/ops/adam/**"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
issues: write
jobs:
unit-tests:
name: hpu-gaudi2 / unit tests
# The type of runner that the job will run on
runs-on: [self-hosted, intel, gaudi2]
container:
image: vault.habana.ai/gaudi-docker/1.21.0/ubuntu22.04/habanalabs/pytorch-installer-2.6.0:latest
ports:
- 80
options: --runtime=habana -e HABANA_VISIBLE_DEVICES=all -e OMPI_MCA_btl_vader_single_copy_mechanism=none --cap-add=sys_nice
env:
PT_HPU_LAZY_MODE: 0
TORCHINDUCTOR_COMPILE_THREADS: 1
TEST_LIST: |
test_accelerator.py
test_autotuning.py
test_compression.py
test_dist.py
test_elastic.py
test_ds_arguments.py
test_run.py
test_multinode_runner.py
test_moe_tp.py
test_monitor.py
(test_zero_optimizer.py and (TestSaveTensorClone or TestZeRONonDistributed))
(test_latest_checkpoint.py and test_missing_latest)
test_reshape_checkpoint.py
test_shared_weights.py
test_sparse.py
test_tag_validation.py
test_pipe_module.py
(test_flops_profiler.py and test_flops_profiler_in_inference)
test_get_optim_files.py
test_groups.py
test_partition_balanced.py
(test_adamw.py and TestAdamConfigs)
test_coalesced_collectives.py
test_activation_checkpointing_non_reentrant.py
test_activation_checkpointing.py
test_data.py
(test_ds_config_dict.py and (TestBasicConfig or TestBatchConfig))
test_ds_config_model.py
test_mup_optimizers.py
(test_pld.py and test_pld_schedule)
test_runtime_utils.py
test_pipe_schedule.py
test_topology.py
(test_ds_initialize.py and (TestClientOptimizer or TestClientLrScheduler))
test_csr.py
(test_fp16.py and (TestZeroEmptyGrad or TestZeroAllowUntestedOptimizer))
(test_bf16.py and TestZeroDtypeCocktail)
test_partition.py
test_ignore_unused_parameters.py
test_zero_config.py
test_zero_context_ancestry.py
(test_zero_context.py and not TestSerialContext)
test_zero_dynamic_class.py
test_zero_nesting_init.py
test_zeropp.py
(test_zero.py and (TestZero3ParamPartitioningLargeParam or TestZero3ParamPartitioningLargeParam))
(test_linear.py and (TestLoRALinear or TestBasicLinear))
(test_ctx.py and TestEngine)
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
- name: Check container state
run: |
ldd --version
hl-smi -L
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
# if needed switch to the last known good SHA until transformers@master is fixed
# git checkout 981c276
git rev-parse --short HEAD
pip install .
- name: Install deepspeed
run: |
pip install .[dev,autotuning]
ds_report
- name: Python environment
run: |
pip list
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
export PT_HPU_LAZY_MODE=${PT_HPU_LAZY_MODE}
export TORCHINDUCTOR_COMPILE_THREADS=${TORCHINDUCTOR_COMPILE_THREADS}
TEST_LIST=$(echo "$TEST_LIST" | awk 'NF{printf "%s%s", (NR>1 ? " or " : ""), $0} END{if (NR>1) print ""}')
echo "TEST_LIST ${TEST_LIST}"
pytest --verbose unit/ -k "${TEST_LIST}"
+104
View File
@@ -0,0 +1,104 @@
name: modal-accelerate
# This CI is running on modal.com's GPUs.
#
# It's set up here on github actions and then the cloned repo is sent to modal and everything
# happens on their hw - see ci/accelerate.py for where the actual vm is loaded, updated and the tests are
# run.
#
# Both files are annotated to what's important and how one might change or update things if needed.
#
# Note that since this is a Required job we can't use `on.push.path` file filter - we are using
# collect-tests job to do the filtering for us so that the job can be skipped and satisfy the
# Required status for PRs to pass.
#
on:
workflow_dispatch:
push:
branches:
- master
# you have to switch to `pull_request` if you need to change the CI job's python script,
# otherwise GH will use a master version of the CI files, ignoring the modifications in the PR -
# the other way is to use modal cli to test this job from one's host - it'd require setting up
# modal secrets
# pull_request:
pull_request_target:
paths-ignore:
- 'docs/**'
- 'blogs/**'
- 'deepspeed/inference/v2/**'
- 'tests/unit/inference/v2/**'
types: [review_requested, ready_for_review, synchronize]
branches:
- master
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
collect-tests:
name: modal-accelerate / collect tests
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
deepspeed: ${{ steps.filter.outputs.deepspeed }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
lfs: true
- name: Filter changed files
uses: dorny/paths-filter@v2
id: filter
with:
token: ${{ secrets.GITHUB_TOKEN }}
filters: |
deepspeed:
- 'deepspeed/**'
- '.github/workflows/modal*.yml'
- 'ci/**'
- 'tests/unit/**'
- 'csrc/**'
deploy:
name: modal-accelerate / DeepSpeedAI CI
runs-on: ubuntu-latest
needs: collect-tests
env:
# these are created at https://modal.com/settings/deepspeedai/tokens
# they are then added to the repo's secrets at https://github.com/deepspeedai/deepspeed/settings/secrets/actions
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
# this one comes from https://huggingface.co/settings/profile of the bot user
# and it too is then updated at https://github.com/deepspeedai/deepspeed/settings/secrets/actions
HF_TOKEN: ${{ secrets.HF_TOKEN }}
if: needs.collect-tests.outputs.deepspeed == 'true'
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
lfs: true
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: 'pip' # caching pip dependencies
- name: Install build dependencies
run: |
pip install uv # much faster than pip
uv pip install --system modal
- name: Run tests
run: |
modal run -m ci.accelerate
+241
View File
@@ -0,0 +1,241 @@
name: modal-torch-latest
# This CI is running on modal.com's GPUs.
#
# It's set up here on github actions and then the cloned repo is sent to modal and everything
# happens on their hw - see ci/torch_latest.py for where the actual vm is loaded, updated and the tests are
# run.
#
# Both files are annotated to what's important and how one might change or update things if needed.
#
# Note that since this is a Required job we can't use `on.push.path` file filter - we are using
# the collect-tests job to do the filtering for us so that the job can be skipped and satisfy the
# Required status for PRs to pass.
#
# Test selection: collect-tests runs ci/tests_fetcher.py, which traces the import
# graph from the PR's changed files to the impacted tests/unit/v1 tests. It emits a
# `mode` (all | subset | none) and a test-list file:
# - none -> deploy is skipped (Required status is still satisfied by the skip)
# - subset -> deploy runs pytest on only the impacted test files
# - all -> deploy runs the whole tests/unit/v1 suite
#
# Full design / how to drive & change it: .github/workflows/TEST_SELECTION.md
#
on:
workflow_dispatch:
inputs:
torch_preset:
description: Modal PyTorch/CUDA image preset for manual runs
required: false
default: '2.10.0-cuda12.8'
type: choice
options:
- '2.7.1-cuda12.8'
- '2.8.0-cuda12.8'
- '2.9.1-cuda12.8'
- '2.10.0-cuda12.8'
- '2.11.0-cuda12.8'
transformers_source:
description: Hugging Face Transformers source for manual runs
required: false
default: 'git'
type: choice
options:
- 'requirements'
- 'git'
transformers_ref:
description: Hugging Face Transformers git ref to install when source is git
required: false
default: 'main'
type: string
push:
branches:
- master
pull_request_target:
types: [review_requested, ready_for_review, synchronize]
branches:
- master
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
collect-tests:
name: modal-torch-latest / collect tests
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
mode: ${{ steps.fetch.outputs.mode }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
# For PRs, check out the PR head so the fetcher sees the proposed
# deepspeed/ + tests/ code. This job holds NO secrets. The selection
# *logic* (ci/) is restored from the base branch in a later step so a PR
# can't tamper with the decision (see "Use base-branch CI scripts").
# Falls back to the pushed/manual commit for non-PR events.
ref: ${{ github.event.pull_request.head.sha || github.sha }}
# Full history so the merge-base with the base branch is always present.
# This is the robust (if slower) choice: a shallow clone that can't reach
# the fork point would produce a wrong diff. The fetcher additionally
# guards against a missing merge-base by falling back to the full suite,
# so we never run a narrow (false-negative) selection on a bad base.
fetch-depth: 0
lfs: true
- name: Determine base ref
id: base
env:
EVENT_NAME: ${{ github.event_name }}
BASE_REF: ${{ github.base_ref }}
run: |
git config --global --add safe.directory '*'
if [ "$EVENT_NAME" = "pull_request_target" ]; then
# Fetch the base branch's full history too, so a merge-base always exists.
git fetch --no-tags origin "$BASE_REF"
echo "ref=origin/$BASE_REF" >> "$GITHUB_OUTPUT"
else
# push to master / manual dispatch -> no diff base -> run the full suite
echo "ref=" >> "$GITHUB_OUTPUT"
fi
- name: Use base-branch CI scripts
# SECURITY: this job decides whether the Required `deploy` job runs. Under
# pull_request_target we must NOT trust the PR's own ci/ for that decision:
# a PR could rewrite ci/tests_fetcher.py to emit `mode=none` (or its self
# tests) and skip CI entirely while still satisfying the Required check.
# So run the selector + self-tests from the *base* branch's ci/. The diff is
# computed from git history, so a PR's ci/ changes still show up in the diff
# and (via the base selector's `ci/**` run-all glob) force a full run.
if: github.event_name == 'pull_request_target'
env:
BASE_REF: ${{ github.base_ref }}
run: |
git config --global --add safe.directory '*'
git checkout "origin/$BASE_REF" -- ci/
- name: Self-test the fetcher
# Pure-stdlib self-tests for the selector (only needs git + python). Runs
# here so a broken selector is caught before it (mis)picks tests. Skipped
# when the base branch has no selector yet (bootstrap; see below).
run: |
if [ -f ci/test_tests_fetcher.py ]; then
python3 ci/test_tests_fetcher.py
else
echo "No base-branch ci/test_tests_fetcher.py (bootstrap) -> skipping self-tests."
fi
- name: Select impacted tests
id: fetch
# Pure-stdlib script; the runner's system python is fine (no deps needed).
# If the base branch doesn't have the selector yet (e.g. the PR that
# introduces it), the restored base ci/ won't contain tests_fetcher.py, so
# fall back to the full suite -- safe, and unblocks the bootstrap PR.
run: |
if [ -f ci/tests_fetcher.py ]; then
python3 ci/tests_fetcher.py --workflow modal-torch-latest --base "${{ steps.base.outputs.ref }}"
else
echo "No base-branch ci/tests_fetcher.py (bootstrap) -> running the full suite."
echo "mode=all" >> "$GITHUB_OUTPUT"
mkdir -p ci/.test_selection
printf 'tests/unit/v1\n' > ci/.test_selection/test_list.txt
fi
- name: Upload test selection
uses: actions/upload-artifact@v4
with:
name: modal-torch-latest-test-selection
path: ci/.test_selection/test_list.txt
# The path lives under a dot-folder; upload-artifact treats dot-prefixed
# paths as hidden and skips them by default (only warns), which would make
# deploy's download fail. Opt in explicitly.
include-hidden-files: true
retention-days: 3
deploy:
name: modal-torch-latest / DeepSpeedAI CI
runs-on: ubuntu-latest
needs: collect-tests
# Run when: manual dispatch, OR the selector failed (fail closed so the Required
# check doesn't silently pass), OR the diff impacts at least one test (mode != none).
# (!cancelled() adopted from upstream so a cancelled run doesn't trigger deploy.)
if: ${{ !cancelled() && (github.event_name == 'workflow_dispatch' || needs.collect-tests.result != 'success' || needs.collect-tests.outputs.mode != 'none') }}
steps:
- name: Fail if test selection failed
if: github.event_name != 'workflow_dispatch' && needs.collect-tests.result != 'success'
run: exit 1
- name: Checkout Repository
uses: actions/checkout@v4
with:
# Test the PR's code (not the base) so diff-driven selection is meaningful.
# SECURITY NOTE: under pull_request_target this runs PR-authored code while
# the modal/HF secrets are on this runner. The trigger types include
# `synchronize`, so this re-runs on every push to an open PR (not only on a
# maintainer's review_requested / ready_for_review action) -- do not treat
# the maintainer gate as an absolute barrier. The primary protection is that
# the CI orchestration (which actually receives the secrets) is restored
# from the base branch in the next step, so a PR can't repoint it at the
# secrets; only the PR's deepspeed/ + tests/ run, inside modal.
ref: ${{ github.event.pull_request.head.sha || github.sha }}
lfs: true
- name: Use base-branch CI scripts
# Run the *base* version of ci/ (which drives `modal run` with the secrets in
# scope) rather than the PR's, so a PR can't modify the orchestration to
# exfiltrate secrets. The PR's deepspeed/ + tests/ are still what gets tested.
# (As noted in the header, changes to ci/* must be validated via `pull_request`
# or the modal CLI, since pull_request_target always uses the base ci/ here.)
if: github.event_name == 'pull_request_target'
env:
BASE_REF: ${{ github.base_ref }}
run: |
git config --global --add safe.directory '*'
git fetch --no-tags --depth=1 origin "$BASE_REF"
git checkout "origin/$BASE_REF" -- ci/
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: 'pip' # caching pip dependencies
- name: Download test selection
if: needs.collect-tests.result == 'success'
uses: actions/download-artifact@v4
with:
name: modal-torch-latest-test-selection
path: ci/.test_selection
- name: Install build dependencies
run: |
pip install uv # much faster than pip
uv pip install --system modal
- name: Run tests
env:
MODAL_TORCH_PRESET: ${{ github.event.inputs.torch_preset || '2.10.0-cuda12.8' }}
MODAL_TRANSFORMERS_SOURCE: ${{ github.event.inputs.transformers_source || 'git' }}
MODAL_TRANSFORMERS_REF: ${{ github.event.inputs.transformers_ref || 'main' }}
# Diff-selected pytest targets produced by collect-tests (falls back to the
# full tests/unit/v1 suite if the file is missing/empty).
DS_TEST_LIST_FILE: ci/.test_selection/test_list.txt
# these are created at https://modal.com/settings/deepspeedai/tokens
# they are then added to the repo's secrets at https://github.com/deepspeedai/deepspeed/settings/secrets/actions
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
# this one comes from https://huggingface.co/settings/profile of the bot user
# and it too is then updated at https://github.com/deepspeedai/deepspeed/settings/secrets/actions
HF_TOKEN: ${{ secrets.HF_TOKEN }}
run: |
modal run -m ci.torch_latest
+50
View File
@@ -0,0 +1,50 @@
name: no-torch
on:
workflow_dispatch:
pull_request:
paths:
- 'accelerator/**'
- '.github/workflows/no-torch.yml'
- 'op_builder/**'
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
issues: write
jobs:
unit-tests:
name: no-torch / source distribution build
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Python environment
run: |
pip uninstall torch --yes
pip install setuptools
pip install build
pip list
- name: Build deepspeed
run: |
DS_BUILD_STRING=" " python -m build --sdist
- name: Open GitHub issue if nightly CI fails
if: ${{ failure() && (github.event_name == 'schedule') }}
uses: JasonEtco/create-an-issue@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
filename: .github/ISSUE_TEMPLATE/ci_failure_report.md
update_existing: true
+75
View File
@@ -0,0 +1,75 @@
name: nv-a6000
on:
pull_request:
paths:
- 'accelerator/cuda_accelerator.py'
- 'deepspeed/inference/v2/**'
- 'tests/unit/inference/v2/**'
- '.github/workflows/nv-a6000.yml'
workflow_dispatch:
inputs:
mii_branch:
description: 'DeepSpeed-MII Branch'
required: false
default: 'main'
type: string
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
unit-tests:
name: nv-a6000 / inference and MII tests
runs-on: [self-hosted, nvidia, a6000]
container:
image: nvcr.io/nvidia/pytorch:25.01-py3
ports:
- 80
options: --gpus all --shm-size "8G"
steps:
- uses: actions/checkout@v4
- name: Check container state
run: |
ldd --version
nvcc --version
nvidia-smi
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
# if you need to use an older transformers version temporarily in case of breakage
# git checkout 981c276
git rev-parse --short HEAD
python -m pip install .
- name: Install deepspeed
run: |
python -m pip install docutils==0.18.1 jinja2==3.0 urllib3==1.26.11 ninja
python -m pip install .[dev,1bit,autotuning,inf]
ds_report
- name: Python environment
run: |
python -m pip list
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
python -m pytest --color=yes --durations=0 --verbose -rF -m 'inference_v2' unit/ --torch_ver="2.6" --cuda_ver="12"
python -m pytest --color=yes --durations=0 --verbose -rF -m 'inference_v2_ops' unit/ --torch_ver="2.6" --cuda_ver="12"
- name: MII unit tests
run: |
BRANCH="main"
if [[ ! -z "${{ github.event.inputs.mii_branch }}" ]]; then
BRANCH="${{ github.event.inputs.mii_branch }}"
fi
echo "Cloning DeepSpeed-MII branch: $BRANCH"
git clone -b $BRANCH --depth=1 https://github.com/deepspeedai/DeepSpeed-MII.git
cd DeepSpeed-MII
pip install .[dev]
cd tests
python -m pytest --color=yes --durations=0 --verbose -rF ./
+47
View File
@@ -0,0 +1,47 @@
name: nv-accelerate-v100
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
unit-tests:
runs-on: [self-hosted, nvidia, cu124, v100]
steps:
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Install pytorch
run: |
pip install -U --cache-dir $TORCH_CACHE torch torchvision --index-url https://download.pytorch.org/whl/cu124
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install deepspeed
run: |
pip install .[dev,autotuning]
ds_report
- name: Python environment
run: |
pip list
- name: HF Accelerate tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
git clone https://github.com/huggingface/accelerate
cd accelerate
git rev-parse --short HEAD
# temp workaround until this is resolved https://github.com/huggingface/accelerate/issues/3676
pip install datasets==3.6.0
# installing dependencies
pip install .[testing]
# force protobuf version due to issues
pip install "protobuf<4.21.0"
pip list
pytest $PYTEST_OPTS --color=yes --durations=0 --verbose tests/deepspeed
+80
View File
@@ -0,0 +1,80 @@
name: nv-ds-chat
on:
workflow_dispatch:
inputs:
dse_branch:
description: 'DeepSpeedExamples Branch'
required: false
default: 'master'
type: string
pull_request:
paths:
- ".github/workflows/nv-ds-chat.yml"
- "deepspeed/runtime/zero/stage_1_and_2.py"
- "deepspeed/runtime/zero/stage3.py"
- "deepspeed/runtime/hybrid_engine.py"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
issues: write
jobs:
unit-tests:
name: nv-ds-chat / DeepSpeed-Chat tests
runs-on: [self-hosted, nvidia, cu124, v100]
steps:
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Install pytorch
run: |
pip install -U --cache-dir $TORCH_CACHE torch torchvision --index-url https://download.pytorch.org/whl/cu124
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install deepspeed
run: |
pip install .[dev]
pip install transformers==4.48.3
ds_report
- name: Install deepspeed-chat
run: |
BRANCH="master"
if [[ ! -z "${{ github.event.inputs.dse_branch }}" ]]; then
BRANCH="${{ github.event.inputs.dse_branch }}"
fi
echo "DeepSpeedExamples Branch: $BRANCH"
git clone -b $BRANCH https://github.com/deepspeedai/DeepSpeedExamples.git
cd DeepSpeedExamples/applications/DeepSpeed-Chat
pip install -r requirements.txt
pip install -e .
- name: Python environment
run: |
pip list
- name: DS-Chat unit tests
run: |
cd DeepSpeedExamples/applications/DeepSpeed-Chat
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
unset NCCL_DEBUG
cd tests
pytest $PYTEST_OPTS ./
- name: Open GitHub issue if nightly CI fails
if: ${{ failure() && (github.event_name == 'schedule') }}
uses: JasonEtco/create-an-issue@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
filename: .github/ISSUE_TEMPLATE/ci_failure_report.md
update_existing: true
+68
View File
@@ -0,0 +1,68 @@
name: nv-flash-attn
on:
workflow_dispatch:
pull_request:
paths:
- 'deepspeed/sequence/**'
- 'tests/unit/sequence_parallelism/**'
- '.github/workflows/nv-flash-attn.yml'
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
unit-tests:
name: nv-flash-attn / sequence parallelism tests
runs-on: [self-hosted, nvidia, a6000]
container:
image: nvcr.io/nvidia/pytorch:24.12-py3
ports:
- 80
options: --gpus all --shm-size "8G"
steps:
- uses: actions/checkout@v4
- name: Check container state
run: |
ldd --version
nvcc --version
nvidia-smi
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install deepspeed
run: |
python -m pip install .[dev]
ds_report
# install transformers after deepspeed so that the right version of transformers is installed
- name: Install transformers
run: |
python -m pip install transformers==4.50.0
- name: Install FlashAttention
run: |
python -m pip install flash-attn
- name: Python environment
run: |
python -m pip list
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
python -m pytest --color=yes --durations=0 --verbose -rF unit/sequence_parallelism/test_ulysses.py --torch_ver="2.6" --cuda_ver="12"
- name: Open GitHub issue if nightly CI fails
if: ${{ failure() && (github.event_name == 'schedule') }}
uses: JasonEtco/create-an-issue@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
filename: .github/ISSUE_TEMPLATE/ci_failure_report.md
update_existing: true
+66
View File
@@ -0,0 +1,66 @@
name: nv-inference
on:
workflow_dispatch:
pull_request:
paths:
- '.github/workflows/nv-inference.yml'
- 'requirements/**'
- 'deepspeed/__init__.py'
- 'deepspeed/inference/**'
- '!deepspeed/inference/v2/**' # exclude v2 dir
- 'tests/unit/inference/**'
- '!tests/unit/inference/v2/**' # exclude v2 tests dir
merge_group:
branches: [ master ]
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
unit-tests:
name: nv-inference / inference tests
runs-on: [self-hosted, nvidia, cu124, v100]
steps:
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Install pytorch
run: |
pip install -U --cache-dir $TORCH_CACHE torch==2.1.2 torchvision==0.16.2 --index-url https://download.pytorch.org/whl/cu124
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
#git checkout f370bebdc
git rev-parse --short HEAD
pip install .
- name: Install deepspeed
run: |
DS_ACCELERATOR=cpu pip install .[dev,1bit,autotuning,inf]
#pip install .[dev,1bit,autotuning,inf,triton]
ds_report
- name: Python environment
run: |
pip list
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
#pytest $PYTEST_OPTS -m 'seq_inference' unit/ --torch_ver="2.1" --cuda_ver="12.4"
pytest $PYTEST_OPTS -m 'inference_ops' unit/ --torch_ver="2.1" --cuda_ver="12.4"
pytest $PYTEST_OPTS --forked -n 4 -m 'inference' unit/ --torch_ver="2.1" --cuda_ver="12.4"
# run ds_report again to check updated op list
ds_report
+53
View File
@@ -0,0 +1,53 @@
# name: nv-lightning-v100
# disabled as the v100s are no more - need to port to modal while removing v100
# on:
# workflow_dispatch:
# pull_request:
# paths-ignore:
# - 'docs/**'
# - 'blogs/**'
# - 'deepspeed/inference/v2/**'
# - 'tests/unit/inference/v2/**'
# merge_group:
# branches: [ master ]
# schedule:
# - cron: "0 0 * * *"
# concurrency:
# group: ${{ github.workflow }}-${{ github.ref }}
# cancel-in-progress: true
# jobs:
# unit-tests:
# runs-on: [self-hosted, nvidia, cu124, v100]
# steps:
# - uses: actions/checkout@v4
# - id: setup-venv
# uses: ./.github/workflows/setup-venv
# - name: Install pytorch
# run: |
# pip install -U --cache-dir $TORCH_CACHE torch torchvision --index-url https://download.pytorch.org/whl/cu124
# python -c "import torch; print('torch:', torch.__version__, torch)"
# python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
# - name: Install deepspeed
# run: |
# pip install .[dev,autotuning]
# ds_report
# - name: Python environment
# run: |
# pip list
# - name: PyTorch Lightning Tests
# run: |
# unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
# pip install pytorch-lightning
# pip install "protobuf<4.21.0"
# cd tests
# pytest $PYTEST_OPTS lightning/
+54
View File
@@ -0,0 +1,54 @@
name: nv-mii
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
unit-tests:
runs-on: [self-hosted, nvidia, cu124, v100]
steps:
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Install pytorch
run: |
pip3 install -U --cache-dir $TORCH_CACHE torch torchvision --index-url https://download.pytorch.org/whl/cu124
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install deepspeed
run: |
pip install .[dev]
ds_report
# install transformers after deepspeed so that the right version of transformers is installed
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
# if needed switch to the last known good SHA until transformers@master is fixed
git checkout v4.42.4
git rev-parse --short HEAD
pip install .
- name: Python environment
run: |
pip list
- name: MII unit tests
run: |
BRANCH="main"
if [[ ! -z "${{ github.event.inputs.mii_branch }}" ]]; then
BRANCH="${{ github.event.inputs.mii_branch }}"
fi
echo "Cloning DeepSpeed-MII branch: $BRANCH"
git clone -b $BRANCH --depth=1 https://github.com/deepspeedai/DeepSpeed-MII.git
cd DeepSpeed-MII
pip install .[dev]
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests/legacy
pytest $PYTEST_OPTS --forked -m "deepspeed" ./
+62
View File
@@ -0,0 +1,62 @@
name: nv-nightly
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
issues: write
jobs:
unit-tests:
runs-on: [self-hosted, nvidia, cu124, v100]
steps:
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Install pytorch
run: |
pip install -U --cache-dir $TORCH_CACHE torch torchvision --index-url https://download.pytorch.org/whl/cu124
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
# if needed switch to the last known good SHA until transformers@master is fixed
git checkout v4.42.4
git rev-parse --short HEAD
pip install .
- name: Install datasets
run: |
pip install datasets
- name: Install deepspeed
run: |
pip install .[dev,1bit,autotuning,inf]
ds_report
- name: Python environment
run: |
pip list
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
pytest $PYTEST_OPTS --forked -m 'nightly' unit/ --torch_ver="2.6" --cuda_ver="12.4"
- name: Open GitHub issue if nightly CI fails
if: ${{ failure() && (github.event_name == 'schedule') }}
uses: JasonEtco/create-an-issue@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
filename: .github/ISSUE_TEMPLATE/ci_failure_report.md
update_existing: true
+82
View File
@@ -0,0 +1,82 @@
name: nv-pre-compile-ops
on:
workflow_dispatch:
pull_request:
branches:
'**'
merge_group:
branches: [ master ]
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-paths:
name: nv-pre-compile-ops / check paths
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.non_pr.outputs.should_run || steps.filter.outputs.run_tests }}
steps:
- id: non_pr
if: github.event_name != 'pull_request'
run: echo "should_run=true" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@v4
if: github.event_name == 'pull_request'
- uses: dorny/paths-filter@v3
id: filter
if: github.event_name == 'pull_request'
with:
predicate-quantifier: every
filters: |
run_tests:
- '**'
- '!docs/**'
- '!blogs/**'
- '!deepspeed/inference/v2/**'
- '!tests/unit/inference/v2/**'
unit-tests:
name: nv-pre-compile-ops / precompile ops
needs: check-paths
if: ${{ !cancelled() && (needs.check-paths.result != 'success' || needs.check-paths.outputs.should_run == 'true') }}
runs-on: ubuntu-24.04
container:
image: nvidia/cuda:12.6.3-devel-ubuntu22.04
steps:
- name: Fail if path filter failed
if: needs.check-paths.result != 'success'
run: exit 1
- name: Install system dependencies
run: |
apt-get update && apt-get install -y git python3 python3-pip libaio-dev ninja-build
ln -sf /usr/bin/python3 /usr/bin/python
- uses: actions/checkout@v4
- name: Install PyTorch
run: |
pip install torch==2.10.0 --index-url https://download.pytorch.org/whl/cu126
- name: environment
run: |
which python
python --version
python -c "import torch; print('torch:', torch.__version__, torch)"
#python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Compile DeepSpeed Ops
run: |
DS_ACCELERATOR=cuda DS_ENABLE_NINJA=1 TORCH_CUDA_ARCH_LIST="7.0;7.5;8.0;8.6;8.9;9.0" DS_BUILD_OPS=1 DS_BUILD_SPARSE_ATTN=0 DS_BUILD_FP_QUANTIZER=0 DS_BUILD_CUTLASS_OPS=0 DS_BUILD_GDS=0 DS_BUILD_RAGGED_DEVICE_OPS=0 DS_BUILD_EVOFORMER_ATTN=0 DS_BUILD_DEEP_COMPILE=0 pip3 install .
- name: DS Report
run: |
DS_ACCELERATOR=cuda ds_report
+73
View File
@@ -0,0 +1,73 @@
name: nv-sd
on:
workflow_dispatch:
pull_request:
paths:
- "deepspeed/ops/transformer/inference/diffusers_**"
- "tests/unit/inference/test_stable_diffusion.py"
- "deepspeed/model_implementations/diffusers/unet.py"
- "deepspeed/model_implementations/diffusers/vae.py"
- "deepspeed/module_inject/containers/vae.py"
- "deepspeed/module_inject/containers/unet.py"
- ".github/workflows/nv-sd.yml"
- "requirements/requirements-sd.txt"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
issues: write
jobs:
sd-tests:
name: nv-sd / stable diffusion tests
runs-on: [self-hosted, nvidia, a6000]
container:
image: nvcr.io/nvidia/pytorch:24.03-py3
ports:
- 80
options: --gpus all --shm-size "8G"
steps:
- uses: actions/checkout@v4
- name: Check container state
run: |
ldd --version
nvcc --version
nvidia-smi
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
git rev-parse --short HEAD
python -m pip install .
- name: Install deepspeed
run: |
pip install image-similarity-measures
python -m pip install opencv-python==4.6.* --force-reinstall
python -m pip install docutils==0.18.1 jinja2==3.0 urllib3==1.26.11 ninja
python -m pip install .[dev,1bit,autotuning,sd]
ds_report
- name: Python environment
run: |
python -m pip list
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
python -m pytest --color=yes --durations=0 --verbose -rF -m 'stable_diffusion' -k "TestStableDiffusion" unit/ --torch_ver="2.3" --cuda_ver="12"
- name: Open GitHub issue if weekly CI fails
if: ${{ failure() && (github.event_name == 'schedule') }}
uses: JasonEtco/create-an-issue@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
filename: .github/ISSUE_TEMPLATE/ci_failure_report.md
update_existing: true
@@ -0,0 +1,47 @@
name: nv-torch-latest-v100
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
unit-tests:
runs-on: [self-hosted, nvidia, cu124, v100]
steps:
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Install pytorch
run: |
pip install -U --cache-dir $TORCH_CACHE torch torchvision --index-url https://download.pytorch.org/whl/cu124
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
# if needed switch to the last known good SHA until transformers@master is fixed
git checkout 981c276
git rev-parse --short HEAD
pip install .
- name: Install deepspeed
run: |
pip install .[dev,1bit,autotuning,deepcompile]
pip install pytest-timeout pytest-instafail
ds_report
- name: Python environment
run: |
pip list
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
pytest -x $PYTEST_OPTS --instafail --timeout 600 --forked -n 8 unit/ --torch_ver="2.6" --cuda_ver="12.4"
pytest $PYTEST_OPTS --instafail --timeout 600 --forked -m 'sequential' unit/ --torch_ver="2.6" --cuda_ver="12.4"
@@ -0,0 +1,59 @@
name: nv-torch-nightly-v100
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
issues: write
jobs:
unit-tests:
runs-on: [self-hosted, nvidia, cu124, v100]
steps:
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Install pytorch
run: |
pip install --pre torch torchvision --index-url https://download.pytorch.org/whl/nightly/cu124
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
# if needed switch to the last known good SHA until transformers@master is fixed
# git checkout 981c276
git rev-parse --short HEAD
pip install .
- name: Install deepspeed
run: |
pip install .[dev,1bit,autotuning]
ds_report
- name: Python environment
run: |
pip list
- name: Unit tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd tests
pytest $PYTEST_OPTS --forked -n 8 unit/
pytest $PYTEST_OPTS --forked -m 'sequential' unit/
- name: Open GitHub issue if nightly CI fails
if: ${{ failure() && (github.event_name == 'schedule') }}
uses: JasonEtco/create-an-issue@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
filename: .github/ISSUE_TEMPLATE/ci_failure_report.md
update_existing: true
@@ -0,0 +1,52 @@
name: nv-transformers-v100
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
unit-tests:
runs-on: [self-hosted, nvidia, cu124, v100]
steps:
- uses: actions/checkout@v4
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Install pytorch
run: |
# use the same pytorch version as transformers CI
pip install -U --cache-dir $TORCH_CACHE torch==2.0.1+cu124 --index-url https://download.pytorch.org/whl/cu124
python -c "import torch; print('torch:', torch.__version__, torch)"
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
- name: Install transformers
run: |
git clone https://github.com/huggingface/transformers
cd transformers
# if needed switch to the last known good SHA until transformers@master is fixed
git checkout e7e9261a2
git rev-parse --short HEAD
pip install .
- name: Install deepspeed
run: |
pip install .[dev,autotuning]
ds_report
- name: Python environment
run: |
pip list
- name: HF transformers tests
run: |
unset TORCH_CUDA_ARCH_LIST # only jit compile for current arch
cd transformers
pip install .[testing]
# find reqs used in ds integration tests
find examples/pytorch -regextype posix-egrep -regex '.*(language-modeling|question-answering|summarization|image-classification|text-classification|translation).*/requirements.txt' -exec grep -v 'torch' {} \; | xargs -I {} pip install --upgrade {}
# force protobuf version due to issues
pip install "protobuf<4.21.0"
pip list
WANDB_DISABLED=true RUN_SLOW=1 pytest $PYTEST_OPTS tests/deepspeed
+90
View File
@@ -0,0 +1,90 @@
name: python
on:
workflow_dispatch:
pull_request:
branches:
'**'
merge_group:
branches: [ master ]
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-paths:
name: python / check paths
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.non_pr.outputs.should_run || steps.filter.outputs.run_tests }}
steps:
- id: non_pr
if: github.event_name != 'pull_request'
run: echo "should_run=true" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@v4
if: github.event_name == 'pull_request'
- uses: dorny/paths-filter@v3
id: filter
if: github.event_name == 'pull_request'
with:
predicate-quantifier: every
filters: |
run_tests:
- '**'
- '!docs/**'
- '!blogs/**'
unit-tests:
name: python / install smoke (Python ${{ matrix.pyVersion }})
needs: check-paths
if: ${{ !cancelled() }}
strategy:
matrix:
pyVersion: ["3.10", "3.11", "3.12"]
fail-fast: false
runs-on: ubuntu-24.04
container:
image: python:${{ matrix.pyVersion }}-slim
steps:
- name: Fail if path filter failed
if: needs.check-paths.result != 'success'
run: exit 1
- name: Skip ignored-path install smoke
if: needs.check-paths.outputs.should_run != 'true'
run: echo "Only ignored paths changed; install smoke intentionally skipped."
- uses: actions/checkout@v4
if: needs.check-paths.outputs.should_run == 'true'
- name: Install build dependencies
if: needs.check-paths.outputs.should_run == 'true'
run: |
apt-get update && apt-get install -y build-essential ninja-build
- name: environment
if: needs.check-paths.outputs.should_run == 'true'
run: |
which python
python --version
- name: Install PyTorch (CPU)
if: needs.check-paths.outputs.should_run == 'true'
run: |
pip install torch --index-url https://download.pytorch.org/whl/cpu
- name: Install deepspeed
if: needs.check-paths.outputs.should_run == 'true'
run: |
pip install .
- name: DS Report
if: needs.check-paths.outputs.should_run == 'true'
run: |
ds_report
+52
View File
@@ -0,0 +1,52 @@
name: Build and publish DeepSpeed release
on:
push:
tags:
- 'v*.*.*'
jobs:
deploy:
runs-on: ubuntu-24.04
environment: release-env
steps:
- uses: actions/checkout@v4
with:
ref: "master"
- id: setup-venv
uses: ./.github/workflows/setup-venv
- name: Get release version from tag
run: |
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/v}" >> $GITHUB_ENV
- name: Check release version
run: |
pip install packaging
python release/check_release_version.py --release_version ${{ env.RELEASE_VERSION }}
- name: Build DeepSpeed
run: |
pip install setuptools
pip install build
DS_BUILD_STRING=" " python -m build --sdist
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
repository-url: https://upload.pypi.org/legacy/
- name: Bump version
run: |
python release/bump_patch_version.py --current_version ${{ env.RELEASE_VERSION }}
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GH_PAT }}
add-paths: |
version.txt
body: |
**Auto-generated PR to update version.txt after a DeepSpeed release**
Released version - ${{ env.RELEASE_VERSION }}
Author - @${{ github.actor }}
branch: AutoPR/${{ env.RELEASE_VERSION }}
assignees: ${{ github.actor }}
title: "Update version.txt after ${{ env.RELEASE_VERSION }} release"
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
+53
View File
@@ -0,0 +1,53 @@
name: Create Virtual Environment
runs:
using: "composite"
steps:
- id: update-env
run: |
sudo apt-get update
# Temporary disable nvme UTs
# sudo apt-get install -y libaio-dev
sudo apt remove -y libaio-dev
python -m pip install --user --upgrade pip
python -m pip install --user --upgrade virtualenv
shell: bash
- id: create-venv
run: |
rm -rf ./unit-test-venv
python -m venv unit-test-venv
source ./unit-test-venv/bin/activate
python -m pip install --upgrade pip
pip install wheel # required after pip>=23.1
echo PATH=$PATH >> $GITHUB_ENV # Make it so venv is inherited for other steps
shell: bash
- id: set-env-vars
run: |
echo TEST_DATA_DIR=/blob/ >> $GITHUB_ENV
echo HF_HOME=/blob/hf_home/ >> $GITHUB_ENV
echo TORCH_EXTENSIONS_DIR=./torch-extensions/ >> $GITHUB_ENV
echo TORCH_CACHE=/blob/torch_cache/ >> $GITHUB_ENV
echo HF_DATASETS_CACHE=/blob/datasets_cache/ >> $GITHUB_ENV
echo MEGATRON_CKPT_DIR=/blob/megatron_ckpt/ >> $GITHUB_ENV
echo CRITIC_CKPT_DIR=/blob/step2_opt_125m_ckpt/ >> $GITHUB_ENV
echo PYTEST_OPTS="--maxfail=100 --color=yes --durations=0 --verbose -rF" >> $GITHUB_ENV
shell: bash
- id: print-env
run: |
which python
python --version
if [[ -z "${AISC_NODE_INSTANCE_ID}" ]]; then
echo "Not on self-hosted node"
else
echo "JobID: ${AISC_NODE_INSTANCE_ID}"
fi
if command -v nvidia-smi; then
nvidia-smi
which nvcc
nvcc --version
elif command -v rocm-smi; then
rocm-smi --showhw
which hipcc
hipcc --version
fi
shell: bash
+62
View File
@@ -0,0 +1,62 @@
name: xpu-compile
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
pull_request:
paths:
- ".github/workflows/xpu-compile.yml"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
issues: write
jobs:
compile-tests:
name: xpu-compile / compile tests
runs-on: [self-hosted, intel, xpu]
container:
image: intel/oneapi-basekit:2025.0.2-0-devel-ubuntu22.04
ports:
- 80
options: --privileged -it --rm --device /dev/dri:/dev/dri -v /dev/dri/by-path:/dev/dri/by-path --ipc=host --cap-add=ALL
steps:
- uses: actions/checkout@v4
- name: Install prerequisite
run: |
apt-get update
apt-get install clinfo libaio-dev python3-pip -y
pip install torch==2.10.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu
pip install py-cpuinfo numpy
pip install .[dev,autotuning]
- name: Check container state
run: |
ldd --version
ds_report
python3 -c "import torch; print('torch:', torch.__version__, torch)"
python3 -c "import torch; print('XPU available:', torch.xpu.is_available())"
python3 -c "from deepspeed.accelerator import get_accelerator; print('accelerator:', get_accelerator()._name)"
pip list
- name: Compile Status
shell: bash
run: |
echo "# torch.compile graph breaks" >> $GITHUB_STEP_SUMMARY
export FI_HMEM=system
ulimit -n 1048575
cd tests/torch_compile
export ZE_AFFINITY_MASK=0,1
echo "## ZeRO stage 3" >> $GITHUB_STEP_SUMMARY
deepspeed test_compile.py --deepspeed_config ds_config_z3.json 2>&1 | tee log_z3.txt
# for each line start with 'dynamo_output', extract the second field and following fields and append to GITHUB_STEP_SUMMARY using awk
cat log_z3.txt | awk '/^dynamo_output/ {$1=""; print $0}' >> $GITHUB_STEP_SUMMARY
echo "## ZeRO stage 2" >> $GITHUB_STEP_SUMMARY
deepspeed test_compile.py --deepspeed_config ds_config_z2.json 2>&1 | tee log_z2.txt
cat log_z2.txt | awk '/^dynamo_output/ {$1=""; print $0}' >> $GITHUB_STEP_SUMMARY
+85
View File
@@ -0,0 +1,85 @@
name: xpu-max1100
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
pull_request:
paths:
- ".github/workflows/xpu-max1100.yml"
- "accelerator/xpu_accelerator.py"
- "accelerator/abstract_accelerator.py"
- "accelerator/cpu_accelerator.py"
- "accelerator/real_accelerator.py"
- "csrc/xpu/**"
- "deepspeed/runtime/engine.py"
- "deepspeed/runtime/bf16_optimizer.py"
- "deepspeed/runtime/zero/stage_1_and_2.py"
- "deepspeed/runtime/zero/stage3.py"
- "deepspeed/runtime/zero/partition_parameters.py"
- "deepspeed/runtime/zero/partitioned_param_coordinator.py"
- "deepspeed/runtime/zero/parameter_offload.py"
- "deepspeed/runtime/pipe/engine.py"
- "deepspeed/runtime/utils.py"
- "op_builder/xpu/**"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
issues: write
jobs:
unit-tests:
name: xpu-max1100 / unit tests
runs-on: [self-hosted, intel, xpu]
container:
image: intel/oneapi-basekit:2025.0.2-0-devel-ubuntu22.04
ports:
- 80
options: --privileged -it --rm --device /dev/dri:/dev/dri -v /dev/dri/by-path:/dev/dri/by-path --ipc=host --cap-add=ALL
steps:
- uses: actions/checkout@v4
- name: Install prerequisite
shell: bash
run: |
apt-get update
apt-get install -y python3.11 python3.11-dev python3-pip clinfo libaio-dev
pip install --upgrade pip
pip install py-cpuinfo
pip install torch==2.10.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu
pip install .[dev,autotuning]
- name: Check container state
shell: bash
run: |
ldd --version
ds_report
python3 -c "import torch; print('torch:', torch.__version__, torch)"
python3 -c "import torch; print('XPU available:', torch.xpu.is_available())"
python3 -c "from deepspeed.accelerator import get_accelerator; print('accelerator:', get_accelerator()._name)"
pip list
- name: Unit tests
shell: bash
run: |
cd tests/unit
export FI_PROVIDER="tcp"
export I_MPI_SHM=off
pytest --verbose accelerator/*
pytest --verbose autotuning/*
pytest --verbose model_parallelism/*
pytest --verbose monitor/*
pytest --verbose utils/*
pytest --verbose runtime/test_ds_config_model.py
pytest --verbose runtime/pipe/test_pipe_schedule.py
pytest --verbose runtime/zero/test_zero_config.py
pytest --verbose runtime/zero/test_zero_tiled.py
pytest --verbose runtime/zero/test_zeropp.py
pytest --verbose runtime/test_autocast.py
pytest --verbose runtime/test_data.py
pytest --verbose runtime/zero/test_zero_dynamic_class.py
+68
View File
@@ -0,0 +1,68 @@
## Ignore Python compiled files
*.pyc
## Output of the diff-based test selector (ci/tests_fetcher.py)
ci/.test_selection/
## Ignore IDE-specific files and directories
# JetBrains IDE settings
.idea/
# Visual Studio Code settings
.vscode/
# Theia IDE settings
.theia/
## Ignore temporary and backup files
# General backup files
*~
# Vim swap files
*.swp
## Ignore log files
*.log
## Ignore a specific generated file
deepspeed/git_version_info_installed.py
## Ignore Python bytecode cache
__pycache__
## Build + installation data
# Build artifacts
build/
# Distribution files
dist/
# Compiled shared objects
*.so
# Deepspeed package info
deepspeed.egg-info/
# Build information
build.txt
## Website generated files
# Jekyll generated site
docs/_site/
# Generated documentation
docs/build
docs/code-docs/source/_build
docs/code-docs/_build
docs/code-docs/build
# SASS cache
.sass-cache/
# Jekyll cache
.jekyll-cache/
.jekyll-metadata
## Testing data
# Saved checkpoints for testing
tests/unit/saved_checkpoint/
# HIP files created during AMD compilation
*_hip.cpp
*_hip.h
*.hip
*.cuh
*hip_layers.h
# virtual env directory for format
venv
View File
+89
View File
@@ -0,0 +1,89 @@
repos:
- repo: meta
hooks:
- id: check-hooks-apply
- id: check-useless-excludes
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: check-case-conflict
- id: check-json
- id: check-symlinks
- id: check-yaml
- id: destroyed-symlinks
- id: end-of-file-fixer
exclude: docs/CNAME
- id: fix-byte-order-marker
- id: fix-encoding-pragma
args: [--remove]
- id: mixed-line-ending
args: [--fix=lf]
- id: requirements-txt-fixer
- id: trailing-whitespace
- repo: https://github.com/google/yapf
rev: v0.40.0
hooks:
- id: yapf
- repo: https://gitlab.com/daverona/pre-commit/cpp
rev: 0.8.0
hooks:
- id: clang-format # formatter of C/C++ code based on a style guide: LLVM, Google, Chromium, Mozilla, and WebKit available
args: []
- repo: local
hooks:
- id: check-torchdist
name: check-torchdist
entry: ./scripts/check-torchdist.py
language: python
exclude: ^(deepspeed/comm/|docs/|benchmarks/|scripts/check-torchdist.py|deepspeed/moe/sharded_moe.py|deepspeed/runtime/comm/coalesced_collectives.py|deepspeed/elasticity/elastic_agent.py|deepspeed/launcher/launch.py|tests/unit/comm/test_dist.py)
# Specific deepspeed/ files are excluded for now until we wrap ProcessGroup in deepspeed.comm
- repo: local
hooks:
- id: check-license
name: check-license
entry: ./scripts/check-license.py
language: python
files: \.(py|c|cpp|cu|cc|h|hpp|cuh|hip|tr)$
exclude: ^(deepspeed/inference/v2/kernels/ragged_ops/blocked_flash|deepspeed/inference/v2/kernels/cutlass_ops/grouped_gemm)
- repo: https://github.com/codespell-project/codespell
rev: v2.1.0
hooks:
- id: codespell
args: [
# Do not check files that are automatically generated
'--skip=docs/Gemfile.lock,tests/unit/gpt2-merges.txt,tests/unit/gpt2-vocab.json',
'--ignore-regex=\\n', # Do not count the 'n' in an escaped newline as part of a word
'--ignore-words-list=youn,unsupport,noe,cann', # Word used in error messages that need rewording
--check-filenames,
--check-hidden
]
- repo: https://github.com/pycqa/flake8
rev: 5.0.4
hooks:
- id: flake8
args: ['--config=.flake8']
- repo: local
hooks:
- id: check-torchcuda
name: check-torchcuda
entry: ./scripts/check-torchcuda.py
language: python
exclude: ^(.github/workflows/|scripts/check-torchcuda.py|docs/_tutorials/accelerator-abstraction-interface.md|docs/_tutorials/deepnvme.md|accelerator/cuda_accelerator.py|deepspeed/inference/engine.py|deepspeed/model_implementations/transformers/clip_encoder.py|deepspeed/model_implementations/diffusers/vae.py|deepspeed/model_implementations/diffusers/unet.py|op_builder/spatial_inference.py|op_builder/transformer_inference.py|op_builder/builder.py|setup.py|tests/unit/ops/sparse_attention/test_sparse_attention.py)
# Specific deepspeed/ files are excluded for now until we wrap ProcessGroup in deepspeed.comm
- repo: local
hooks:
- id: check-extraindexurl
name: check-extraindexurl
entry: ./scripts/check-extraindexurl.py
language: python
files: \.(yml|yaml|sh|py)$
exclude: ^(scripts/check-extraindexurl.py)
+581
View File
@@ -0,0 +1,581 @@
[MASTER]
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code.
extension-pkg-whitelist=
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS
# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use.
jobs=1
# Control the amount of potential inferred values when inferring a single
# object. This can help the performance when dealing with large functions or
# complex, nested conditions.
limit-inference-results=100
# List of plugins (as comma separated values of python module names) to load,
# usually to register additional checkers.
load-plugins=
# Pickle collected data for later comparisons.
persistent=yes
# Specify a configuration file.
#rcfile=
# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
confidence=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then re-enable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=print-statement,
parameter-unpacking,
unpacking-in-except,
old-raise-syntax,
backtick,
long-suffix,
old-ne-operator,
old-octal-literal,
import-star-module-level,
non-ascii-bytes-literal,
raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead,
apply-builtin,
basestring-builtin,
buffer-builtin,
cmp-builtin,
coerce-builtin,
execfile-builtin,
file-builtin,
long-builtin,
raw_input-builtin,
reduce-builtin,
standarderror-builtin,
unicode-builtin,
xrange-builtin,
coerce-method,
delslice-method,
getslice-method,
setslice-method,
no-absolute-import,
old-division,
dict-iter-method,
dict-view-method,
next-method-called,
metaclass-assignment,
indexing-exception,
raising-string,
reload-builtin,
oct-method,
hex-method,
nonzero-method,
cmp-method,
input-builtin,
round-builtin,
intern-builtin,
unichr-builtin,
map-builtin-not-iterating,
zip-builtin-not-iterating,
range-builtin-not-iterating,
filter-builtin-not-iterating,
using-cmp-argument,
eq-without-hash,
div-method,
idiv-method,
rdiv-method,
exception-message-attribute,
invalid-str-codec,
sys-max-int,
bad-python3-import,
deprecated-string-function,
deprecated-str-translate-call,
deprecated-itertools-function,
deprecated-types-field,
next-method-defined,
dict-items-not-iterating,
dict-keys-not-iterating,
dict-values-not-iterating,
deprecated-operator-function,
deprecated-urllib-function,
xreadlines-attribute,
deprecated-sys-function,
exception-escape,
comprehension-escape
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=c-extension-no-member
[REPORTS]
# Python expression which should return a score less than or equal to 10. You
# have access to the variables 'error', 'warning', 'refactor', and 'convention'
# which contain the number of messages in each category, as well as 'statement'
# which is the total number of statements analyzed. This score is used by the
# global evaluation report (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details.
#msg-template=
# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio). You can also give a reporter class, e.g.
# mypackage.mymodule.MyReporterClass.
output-format=text
# Tells whether to display a full report or only the messages.
reports=no
# Activate the evaluation score.
score=yes
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=sys.exit
[BASIC]
# Naming style matching correct argument names.
argument-naming-style=snake_case
# Regular expression matching correct argument names. Overrides argument-
# naming-style.
#argument-rgx=
# Naming style matching correct attribute names.
attr-naming-style=snake_case
# Regular expression matching correct attribute names. Overrides attr-naming-
# style.
#attr-rgx=
# Bad variable names which should always be refused, separated by a comma.
bad-names=foo,
bar,
baz,
toto,
tutu,
tata
# Naming style matching correct class attribute names.
class-attribute-naming-style=any
# Regular expression matching correct class attribute names. Overrides class-
# attribute-naming-style.
#class-attribute-rgx=
# Naming style matching correct class names.
class-naming-style=PascalCase
# Regular expression matching correct class names. Overrides class-naming-
# style.
#class-rgx=
# Naming style matching correct constant names.
const-naming-style=UPPER_CASE
# Regular expression matching correct constant names. Overrides const-naming-
# style.
#const-rgx=
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
# Naming style matching correct function names.
function-naming-style=snake_case
# Regular expression matching correct function names. Overrides function-
# naming-style.
#function-rgx=
# Good variable names which should always be accepted, separated by a comma.
good-names=i,
j,
k,
ex,
Run,
_
# Include a hint for the correct naming format with invalid-name.
include-naming-hint=no
# Naming style matching correct inline iteration names.
inlinevar-naming-style=any
# Regular expression matching correct inline iteration names. Overrides
# inlinevar-naming-style.
#inlinevar-rgx=
# Naming style matching correct method names.
method-naming-style=snake_case
# Regular expression matching correct method names. Overrides method-naming-
# style.
#method-rgx=
# Naming style matching correct module names.
module-naming-style=snake_case
# Regular expression matching correct module names. Overrides module-naming-
# style.
#module-rgx=
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
# These decorators are taken in consideration only for invalid-name.
property-classes=abc.abstractproperty
# Naming style matching correct variable names.
variable-naming-style=snake_case
# Regular expression matching correct variable names. Overrides variable-
# naming-style.
#variable-rgx=
[LOGGING]
# Format style used to check logging format string. `old` means using %
# formatting, `new` is for `{}` formatting,and `fstr` is for f-strings.
logging-format-style=old
# Logging modules to check that the string format arguments are in logging
# function parameter format.
logging-modules=logging
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis). It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
# List of decorators that change the signature of a decorated function.
signature-mutators=
[SIMILARITIES]
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
# Minimum lines number of a similarity.
min-similarity-lines=4
[STRING]
# This flag controls whether the implicit-str-concat-in-sequence should
# generate a warning on implicit string concatenation in sequences defined over
# several lines.
check-str-concat-over-line-jumps=no
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
_cb
# A regular expression matching the name of dummy variables (i.e. expected to
# not be used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored. Default to name
# with leading underscore.
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=90
# Maximum number of lines in a module.
max-module-lines=1000
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,
dict-separator
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
XXX,
TODO
[SPELLING]
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions=4
# Spelling dictionary name. Available dictionaries: none. To make it work,
# install the python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains the private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to the private dictionary (see the
# --spelling-private-dict-file option) instead of raising a message.
spelling-store-unknown-words=no
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
__new__,
setUp,
__post_init__
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,
_fields,
_replace,
_source,
_make
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=cls
[DESIGN]
# Maximum number of arguments for function / method.
max-args=10
# Maximum number of attributes for a class (see R0902).
max-attributes=20
# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr=5
# Maximum number of branch for function / method body.
max-branches=12
# Maximum number of locals for function / method body.
max-locals=15
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of return / yield for function / method body.
max-returns=6
# Maximum number of statements in function / method body.
max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
[IMPORTS]
# List of modules that can be imported at any level, not just the top level
# one.
allow-any-import-level=
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Deprecated modules which should not be used, separated by a comma.
deprecated-modules=optparse,tkinter.tix
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled).
ext-import-graph=
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled).
import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled).
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
# Couples of modules and preferred modules, separated by a comma.
preferred-modules=
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "BaseException, Exception".
overgeneral-exceptions=BaseException,
Exception
+20
View File
@@ -0,0 +1,20 @@
# Required
version: 2
build:
os: "ubuntu-22.04"
tools:
python: "3.8"
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/code-docs/source/conf.py
fail_on_warning: false
# Optionally build your docs in additional formats such as PDF
formats:
- pdf
# Optionally set the version of Python and requirements required to build your docs
python:
install:
- requirements: requirements/requirements-readthedocs.txt
+3
View File
@@ -0,0 +1,3 @@
[style]
SPLIT_ALL_COMMA_SEPARATED_VALUES = false
COLUMN_LIMIT = 119
+32
View File
@@ -0,0 +1,32 @@
<!-- This file is duplicated as CLAUDE.md and AGENTS.md. Keep them in sync. -->
# AGENTS.md — Workspace-level instructions for AI coding agents
## DeepSpeed Project Rules
### Commit & CI requirements
- All commits MUST have a `Signed-off-by` line (use `--signoff`). Get the name and email from `git config user.name` / `git config user.email`.
- Formatting: yapf (column_limit=119, `.style.yapf`) + flake8 (`.flake8`).
- Always verify changed files pass pre-commit checks before committing: `pre-commit run --files <changed_files>`. Only check modified files, not the entire codebase. Config: `.pre-commit-config.yaml`.
- `check-torchdist` hook: NEVER directly import torch's distributed module. Use `import deepspeed.comm as dist` instead.
- New files require license header:
```
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
```
### Code change discipline
- NEVER make cosmetic/formatting-only changes to existing code. Only add/modify lines that are functionally necessary. Minimizing diff noise is critical for code review.
- Delete dead code decisively — if code is unused at runtime (only referenced in tests), remove it along with its tests.
- Prefer consolidating tests over proliferating test files.
- Blend in: when modifying code, read the surrounding context and match the style of neighboring code (naming, spacing, patterns, idioms).
- Write beginner-friendly code: avoid deeply nested expressions or chained logic. Break complex expressions into clear, named intermediate steps.
- Comments should explain **why**, not **what**. Describe the purpose and reasoning, not the mechanics that the code already shows.
- New features must include corresponding tests and documentation updates.
## Tool Caveats
### Edit tool auto-formatter
The Edit tool has a hidden auto-formatter that silently changes quotes, whitespace, blank lines, and line wrapping. For format-sensitive modifications (e.g., when exact formatting matters for pre-commit), use `bash` with `sed`, `python`, or `cat` instead.
+32
View File
@@ -0,0 +1,32 @@
<!-- This file is duplicated as CLAUDE.md and AGENTS.md. Keep them in sync. -->
# AGENTS.md — Workspace-level instructions for AI coding agents
## DeepSpeed Project Rules
### Commit & CI requirements
- All commits MUST have a `Signed-off-by` line (use `--signoff`). Get the name and email from `git config user.name` / `git config user.email`.
- Formatting: yapf (column_limit=119, `.style.yapf`) + flake8 (`.flake8`).
- Always verify changed files pass pre-commit checks before committing: `pre-commit run --files <changed_files>`. Only check modified files, not the entire codebase. Config: `.pre-commit-config.yaml`.
- `check-torchdist` hook: NEVER directly import torch's distributed module. Use `import deepspeed.comm as dist` instead.
- New files require license header:
```
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
```
### Code change discipline
- NEVER make cosmetic/formatting-only changes to existing code. Only add/modify lines that are functionally necessary. Minimizing diff noise is critical for code review.
- Delete dead code decisively — if code is unused at runtime (only referenced in tests), remove it along with its tests.
- Prefer consolidating tests over proliferating test files.
- Blend in: when modifying code, read the surrounding context and match the style of neighboring code (naming, spacing, patterns, idioms).
- Write beginner-friendly code: avoid deeply nested expressions or chained logic. Break complex expressions into clear, named intermediate steps.
- Comments should explain **why**, not **what**. Describe the purpose and reasoning, not the mechanics that the code already shows.
- New features must include corresponding tests and documentation updates.
## Tool Caveats
### Edit tool auto-formatter
The Edit tool has a hidden auto-formatter that silently changes quotes, whitespace, blank lines, and line wrapping. For format-sensitive modifications (e.g., when exact formatting matters for pre-commit), use `bash` with `sed`, `python`, or `cat` instead.
+59
View File
@@ -0,0 +1,59 @@
# This file is used to subscribe for notifications for PRs
# related to specific file paths, does not necessarily mean
# approval is required from these people before merging.
#
# Learn more about CODEOWNERS syntax here:
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# top-level repo folders
/.github/ @loadams
/azure/ @loadams
/benchmarks/ @guanhuawang @tjruwase
/bin/ @loadams
/csrc/ @tjruwase
/deepspeed/ @loadams @tjruwase
/docker/ @loadams @guanhuawang
/docs/ @loadams @tjruwase
/examples/ @jomayeri @tohtana
/op_builder/ @loadams @tjruwase @jomayeri
/release/ @loadams @jomayeri
/requirements/ @loadams
/scripts/ @loadams @tjruwase
/tests/ @tjruwase @loadams @tohtana
# deepspeed
/deepspeed/autotuning/ @loadams
/deepspeed/checkpoint/ @tjruwase
/deepspeed/comm/ @guanhuawang
/deepspeed/compression/ @tjruwase
/deepspeed/elasticity/ @tjruwase
/deepspeed/launcher/ @loadams
/deepspeed/module_inject/ @hwchen2017 @loadams
/deepspeed/moe/ @tohtana
/deepspeed/monitor/ @tjruwase
/deepspeed/nebula/ @tjruwase
/deepspeed/nvme/ @tjruwase @jomayeri
/deepspeed/ops/ @tohtana
/deepspeed/pipe/ @tohtana @loadams
/deepspeed/profiling/ @loadams
/deepspeed/sequence/ @tohtana
/deepspeed/utils/ @tjruwase @tohtana
# inference
/deepspeed/inference/ @hwchen2017 @tohtana
/deepspeed/model_implementations/@tohtana @loadams
# training
/deepspeed/runtime/ @tjruwase @tohtana
/deepspeed/runtime/activation_checkpointing/ @tjruwase
/deepspeed/runtime/checkpoint_engine/ @tjruwase
/deepspeed/runtime/comm/ @guanhuawang
/deepspeed/runtime/compression/ @tjruwase
/deepspeed/runtime/data_pipeline/ @tjruwase
/deepspeed/runtime/domino/ @guanhuawang @hwchen2017
/deepspeed/runtime/fp16/ @tjruwase @tohtana
/deepspeed/runtime/fp16/onebit/ @tjruwase
/deepspeed/runtime/pipe/ @loadams @tohtana
/deepspeed/runtime/swap_tensor/ @tjruwase @jomayeri
/deepspeed/runtime/zero/ @tjruwase @tohtana
+9
View File
@@ -0,0 +1,9 @@
# Microsoft Open Source Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
Resources:
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
+13
View File
@@ -0,0 +1,13 @@
# DeepSpeed TSC Committers #
| Name | GitHub ID | Affiliation
|--- | ---- | --- |
| Olatunji Ruwase | [tjruwase](https://github.com/tjruwase) | SnowFlake |
| Logan Adams | [loadams](https://github.com/loadams) | Microsoft |
| Masahiro Tanaka | [tohtana](https://github.com/tohtana) | Anyscale |
| Jeff Rasley | [jeffra](https://github.com/jeffra) | SnowFlake |
| Minjia Zhang | [minjiazhang](https://github.com/minjiazhang) | UIUC |
| Ashwin Aji | [ashwinma](https://github.com/ashwinma) | AMD |
| Sam Foreman | [saforem2](https://github.com/saforem2) | Argonne National Laboratory |
| Zhipeng Wang | [PKUWZP](https://github.com/PKUWZP) | LinkedIn |
| Guokai Ma | [delock](https://github.com/delock) | Intel |
+152
View File
@@ -0,0 +1,152 @@
# Contributing
DeepSpeed welcomes your contributions!
## Prerequisites
DeepSpeed uses [pre-commit](https://pre-commit.com/) to ensure that formatting is
consistent across DeepSpeed. First, ensure that `pre-commit` is installed from either
installing DeepSpeed or `pip install pre-commit`. Next, the pre-commit hooks must be
installed once before commits can be made:
```bash
pre-commit install
```
Afterwards, our suite of formatting tests run automatically before each `git commit`. You
can also run these manually:
```bash
pre-commit run --files $(git diff --name-only master)
```
If a formatting test fails, it will fix the modified code in place and abort
the `git commit`. After looking over the changes, you can `git add <modified files>`
and then repeat the previous `git commit` command.
You can also run:
```
make format
```
which will do the same as above, and it'll also automatically build a `venv` python environment if you
don't already have one, which will isolate the requirements of this project from requirements of other projects.
## Testing
DeepSpeed tracks two types of tests: unit tests and more costly model convergence tests.
The model convergence tests train
[DeepSpeedExamples](https://github.com/deepspeedai/DeepSpeedExamples/) and measure
end-to-end convergence and related metrics. Unit tests are found in `tests/unit/` and
the model convergence tests are found in `tests/model/`.
### Unit Tests
[PyTest](https://docs.pytest.org/en/latest/) is used to execute tests. PyTest can be
installed from PyPI via `pip install pytest`. Simply invoke `pytest --forked` to run the
unit tests:
```bash
pytest --forked tests/unit/
```
You can also provide the `-v` flag to `pytest` to see additional information about the
tests. Note that [pytest-forked](https://github.com/pytest-dev/pytest-forked) and the
`--forked` flag are required to test CUDA functionality in distributed tests. Using
`--forked` is safe because `import deepspeed` no longer initializes a CUDA context;
earlier versions probed CUDA at import time, which poisoned `fork()`.
You can also run:
```
make test
```
### Diff-based CI test selection
Some GPU CI workflows (currently `modal-torch-latest`, which runs `tests/unit/v1/`)
don't run the whole suite on every PR. Instead, `ci/tests_fetcher.py` looks at the
files your PR changes, builds an import graph over `deepspeed/` and the `unit` test
helpers, and runs only the tests that could be affected. This keeps CI fast without
losing coverage (`push` to `master` always runs everything). The full design — and
how to drive and extend it — is in
[`.github/workflows/TEST_SELECTION.md`](.github/workflows/TEST_SELECTION.md).
How it decides:
* It diffs your branch against the base branch's merge-base.
* Each changed Python file is traced *forward* to the tests that import it
(directly or transitively); those tests are selected.
* It **falls back to the full suite** (never to "no tests") whenever it can't
safely narrow: a missing base / merge-base, a changed shared fixture, build
system, CI script, or core runtime file, a deleted module that something still
imports, or any unexpected error in the selector itself.
Escape hatches:
* **Force the full suite for a push:** put `[test all]` (or `[no filter]`) anywhere
in a commit message on the branch.
* **Run all by touching infra:** changes to the run-all globs (CI config, build
system, `deepspeed/__init__.py`, collectives/accelerator, shared fixtures, etc.)
always trigger everything. See `COMMON_RUN_ALL_GLOBS` / `extra_run_all_globs` in
`ci/tests_fetcher.py`.
* **Runtime/dynamic deps the import graph can't see** (monkey-patching, plugin
registries, JIT ops, `deepspeed.initialize()`-time injection) are wired up via
the curated `DYNAMIC_EDGES` map in `ci/tests_fetcher.py` — add an entry there if
you find a gap.
Preview/debug locally (pure stdlib, no DeepSpeed install needed):
```bash
# What would CI run for your branch?
python ci/tests_fetcher.py --base origin/master
cat ci/.test_selection/test_list.txt
# Why was a test (de)selected? Prints the import chains.
python ci/tests_fetcher.py --base origin/master --explain
```
> Note: under `pull_request_target` the `deploy` job runs the PR's `deepspeed/` and
> `tests/` but restores `ci/` from the base branch (the CI scripts hold the modal/HF
> secrets). So changes to `ci/*` only take effect once merged — validate them via a
> `pull_request`-triggered run or the `modal` CLI.
### Model Tests
To execute model tests, first [install DeepSpeed](#installation). The
[DeepSpeedExamples](https://github.com/deepspeedai/DeepSpeedExamples/) repository is cloned
as part of this process. Next, execute the model test driver:
```bash
cd tests/model/
pytest run_sanity_check.py
```
Note that the `--forked` flag is not necessary for the model tests.
## Developer Certificate of Origin
This project welcomes contributions and suggestions. All contributions to deepspeedai projects
require commits to be signed off with a [Developer Certificate of Origin](https://en.wikipedia.org/wiki/Developer_Certificate_of_Origin)
(DCO) declaring that you have the right to, and actually do, grant us the rights to use your contribution.
When you submit a pull request, the DCO app will check for the presence of signed commits.
Information about how this check works is here: https://github.com/dcoapp/app?tab=readme-ov-file#how-it-works
To sign commits, you will need to include `-s` when running `git commit`. For example, `git commit -s -m "Commit message"`. One note, creating PRs via the GitHub interface do not appear to include this option. If you forget this, clicking on the failing check in your PR will point you to commands you can run to rebase and sign previous commits.
## Code of Conduct
This project has adopted the [Microsoft Open Source Code of
Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact
[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or
comments.
## New Feature Contribution Guidelines
Unlike bug fix or improving existing feature (where users usually directly submit a PR and we review it), adding a new feature to DeepSpeed requires several steps: (1) proposal and discussion, (2) implementation and verification, (3) release and maintenance. This general guideline applies to all new feature contributions. Core DeepSpeed team member contributions may complete step 1 internally.
### Step 1: proposal and discussion
We ask users to first post your intended feature in an issue. This issue needs to include:
* A description of the proposed feature.
* A motivation of why it will be useful to DeepSpeed users.
* A rough design of how you implement the feature inside DeepSpeed.
* (Important) Results or planned experiments to demonstrate the effectiveness and correctness of the feature.
* If this is a general feature applicable to different tasks, we require testing it on at least one CV task (e.g., [CIFAR](https://www.deepspeed.ai/tutorials/cifar-10/)) and one NLP task (e.g., [SQuAD](https://www.deepspeed.ai/tutorials/bert-finetuning/)). If this is a feature for one kind of task only, it is fine to just test on the specific task.
* If the feature only affects performance and does not affect training convergence, we require testing on a fraction of training to demonstrate that the training/validation loss are consistent with baseline, and that the performance is better than baseline.
* If the feature does affect training convergence, we require testing the whole training to demonstrate that the feature achieves better/on-par final model quality and training performance compared to baseline.
Based on the issue we shall discuss the merit of the new feature and decide whether accept or decline the proposal. Once accepted and after we confirm the design and implementation plan, we are ready for step 2.
### Step 2: implementation and verification
Contributor will go ahead and implement the feature, and the DeepSpeed team will provide guidance/helps as needed. The required deliverables include:
* A PR to [deepspeedai/DeepSpeed](https://github.com/deepspeedai/DeepSpeed) including (1) the feature implementation (2) unit tests (3) documentation (4) tutorial
* A PR to [deepspeedai/DeepSpeedExamples](https://github.com/deepspeedai/DeepSpeedExamples) or [deepspeedai/Megatron-DeepSpeed](https://github.com/deepspeedai/Megatron-DeepSpeed) including the examples of how to use the feature (this is related to the planned testing experiments in proposal)
* In the implementation (code, documentation, tutorial), we require the feature author to record their GitHub username as a contact method for future questions/maintenance.
After receiving the PRs, we will review them and merge them after necessary tests/fixes.
### Step 3: release and maintenance
After the PRs are merged, we will announce the feature on our website (with credit to the feature author). We ask the feature author to commit to the maintenance of the feature.
+101
View File
@@ -0,0 +1,101 @@
# DeepSpeed Project Charter and Governance
This charter sets forth the responsibilities and procedures for technical contribution to, and oversight of, the DeepSpeed open source project. All contributors (including committers, maintainers, and other technical positions) and other participants in the Project (collectively, "Collaborators") must comply with the terms of this Charter.
## Mission and Scope of the Project
The mission of the Project is to DeepSpeed is a deep learning optimization library that makes distributed training and inference easy, efficient, and effective.
The scope of the Project includes collaborative development under the Project License (as defined herein) supporting the mission, including documentation, testing, integration, and the creation of other artifacts that aid the development, deployment, operation, or adoption of the open source project.
## Technical Steering Committee
1. The Technical Steering Committee (the "TSC") will be responsible for all technical oversight of the open source Project.
2. The TSC voting members are initially the Project's Committers. At the inception of the project, the Committers of the Project will be as set forth within the "CONTRIBUTING" file within the Project's code repository. The TSC may choose an alternative approach for determining the voting members of the TSC, and any such alternative approach will be documented in the CONTRIBUTING file. Any meetings of the Technical Steering Committee are intended to be open to the public, and can be conducted electronically, via teleconference, or in person.
3. TSC projects generally will involve Contributors and Committers. The TSC may adopt or modify roles so long as the roles are documented in the CONTRIBUTING file. Unless otherwise documented:
- **Contributors** include anyone in the technical community that contributes code, documentation, or other technical artifacts to the Project.
- **Committers** are Contributors who have earned the ability to modify ("commit") source code, documentation, or other technical artifacts in a project's repository.
- A Contributor may become a Committer by a majority approval of the existing Committers. A Committer may be removed by a majority approval of the other existing Committers.
4. Participation in the Project through becoming a Contributor and Committer is open to anyone so long as they abide by the terms of this Charter.
5. The TSC may:
- Establish workflow procedures for the submission, approval, and closure/archiving of projects.
- Set requirements for the promotion of Contributors to Committer status, as applicable.
- Amend, adjust, refine and/or eliminate the roles of Contributors and Committers, and create new roles, and publicly document any TSC roles, as it sees fit.
6. The TSC may elect a TSC Chair, who will preside over meetings of the TSC and will serve until their resignation or replacement by the TSC. The TSC Chair, or any other TSC member so designated by the TSC, will serve as the primary communication contact between the Project and AI & Data, a directed fund of The Linux Foundation.
7. Responsibilities: The TSC will be responsible for all aspects of oversight relating to the Project, which may include:
- Coordinating the technical direction of the Project.
- Approving project or system proposals (including, but not limited to, incubation, deprecation, and changes to a sub-project's scope).
- Organizing sub-projects and removing sub-projects.
- Creating sub-committees or working groups to focus on cross-project technical issues and requirements.
- Appointing representatives to work with other open source or open standards communities.
- Establishing community norms, workflows, issuing releases, and security issue reporting policies.
- Approving and implementing policies and processes for contributing (to be published in the CONTRIBUTING file) and coordinating with the series manager of the Project (as provided for in the Series Agreement, the "Series Manager") to resolve matters or concerns that may arise as set forth in Section 7 of this Charter.
- Discussions, seeking consensus, and where necessary, voting on technical matters relating to the code base that affect multiple projects.
- Coordinating any marketing, events, or communications regarding the Project.
## TSC Voting
1. While the Project aims to operate as a consensus-based community, if any TSC decision requires a vote to move the Project forward, the voting members of the TSC will vote on a one vote per voting member basis.
2. Quorum for TSC meetings requires at least fifty percent of all voting members of the TSC to be present. The TSC may continue to meet if quorum is not met but will be prevented from making any decisions at the meeting.
3. Except as provided in Section 7.c. and 8.a, decisions by vote at a meeting require a majority vote of those in attendance, provided quorum is met. Decisions made by electronic vote without a meeting require a majority vote of all voting members of the TSC.
4. In the event a vote cannot be resolved by the TSC, any voting member of the TSC may refer the matter to the Series Manager for assistance in reaching a resolution.
## Compliance with Policies
1. This Charter is subject to the Series Agreement for the Project and the Operating Agreement of LF Projects. Contributors will comply with the policies of LF Projects as may be adopted and amended by LF Projects, including, without limitation, the policies listed at https://lfprojects.org/policies/.
2. The TSC may adopt a code of conduct ("CoC") for the Project, which is subject to approval by the Series Manager. In the event that a Project-specific CoC has not been approved, the LF Projects Code of Conduct listed at https://lfprojects.org/policies will apply for all Collaborators in the Project.
3. When amending or adopting any policy applicable to the Project, LF Projects will publish such policy, as to be amended or adopted, on its website at least 30 days prior to such policy taking effect; provided, however, that in the case of any amendment of the Trademark Policy or Terms of Use of LF Projects, any such amendment is effective upon publication on LF Project's website.
4. All Collaborators must allow open participation from any individual or organization meeting the requirements for contributing under this Charter and any policies adopted for all Collaborators by the TSC, regardless of competitive interests. Put another way, the Project community must not seek to exclude any participant based on any criteria, requirement, or reason other than those that are reasonable and applied on a non-discriminatory basis to all Collaborators in the Project community.
5. The Project will operate in a transparent, open, collaborative, and ethical manner at all times. The output of all Project discussions, proposals, timelines, decisions, and status should be made open and easily visible to all. Any potential violations of this requirement should be reported immediately to the Series Manager.
## Community Assets
1. LF Projects will hold title to all trade or service marks used by the Project ("Project Trademarks"), whether based on common law or registered rights. Project Trademarks will be transferred and assigned to LF Projects to hold on behalf of the Project. Any use of any Project Trademarks by Collaborators in the Project will be in accordance with the license from LF Projects and inure to the benefit of LF Projects.
2. The Project will, as permitted and in accordance with such license from LF Projects, develop and own all Project GitHub and social media accounts, and domain name registrations created by the Project community.
3. Under no circumstances will LF Projects be expected or required to undertake any action on behalf of the Project that is inconsistent with the tax-exempt status or purpose, as applicable, of the Joint Development Foundation or LF Projects, LLC.
## General Rules and Operations
The Project will:
1. Engage in the work of the Project in a professional manner consistent with maintaining a cohesive community, while also maintaining the goodwill and esteem of LF Projects, Joint Development Foundation, and other partner organizations in the open source community.
2. Respect the rights of all trademark owners, including any branding and trademark usage guidelines.
## Intellectual Property Policy
1. Collaborators acknowledge that the copyright in all new contributions will be retained by the copyright holder as independent works of authorship and that no contributor or copyright holder will be required to assign copyrights to the Project.
2. Except as described in Section 7.c., all contributions to the Project are subject to the following:
- All new inbound code contributions to the Project must be made using Apache License, Version 2.0 available at http://www.apache.org/licenses/LICENSE-2.0 (the "Project License").
- All new inbound code contributions must also be accompanied by a Developer Certificate of Origin (http://developercertificate.org) sign-off in the source code system that is submitted through a TSC-approved contribution process which will bind the authorized contributor and, if not self-employed, their employer to the applicable license.
- All outbound code will be made available under the Project License.
- Documentation will be received and made available by the Project under the Creative Commons Attribution 4.0 International License (available at http://creativecommons.org/licenses/by/4.0/).
- The Project may seek to integrate and contribute back to other open source projects ("Upstream Projects"). In such cases, the Project will conform to all license requirements of the Upstream Projects, including dependencies, leveraged by the Project. Upstream Project code contributions not stored within the Project's main code repository will comply with the contribution process and license terms for the applicable Upstream Project.
3. The TSC may approve the use of an alternative license or licenses for inbound or outbound contributions on an exception basis. To request an exception, please describe the contribution, the alternative open source license(s), and the justification for using an alternative open source license for the Project. License exceptions must be approved by a two-thirds vote of the entire TSC.
4. Contributed files should contain license information, such as SPDX short form identifiers, indicating the open source license or licenses pertaining to the file.
## Amendments
1. This charter may be amended by a two-thirds vote of the entire TSC and is subject to approval by LF Projects.
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+9
View File
@@ -0,0 +1,9 @@
include *.txt README.md
include deepspeed/inference/v2/kernels/ragged_ops/libs/*.so
include deepspeed/inference/v2/kernels/cutlass_ops/libs/*.so
recursive-include requirements *.txt
recursive-include deepspeed *.cpp *.h *.hpp *.cu *.hip *.tr *.cuh *.cc *.json
recursive-include csrc *.cpp *.h *.hpp *.cu *.tr *.cuh *.cc
recursive-include op_builder *.py
recursive-include benchmarks *.py
recursive-include accelerator *.py
+9
View File
@@ -0,0 +1,9 @@
include *.txt README.md
recursive-include requirements *.txt
# this is for Windows only
recursive-include deepspeed *.tr
recursive-exclude deepspeed/ops/csrc *.cpp *.h *.cu *.cuh *.cc
prune csrc
prune op_builder
prune accelerator
+23
View File
@@ -0,0 +1,23 @@
# usage: make help
.PHONY: help test format
.DEFAULT_GOAL := help
help: ## this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[0-9a-zA-Z_-]+:.*?##/ { printf " \033[36m%-22s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
echo $(MAKEFILE_LIST)
test: ## run tests
pytest --forked tests/unit/
format: ## fix formatting
@if [ ! -d "venv" ]; then \
python -m venv venv; \
. venv/bin/activate; \
pip install pre-commit -U; \
pre-commit clean; \
pre-commit uninstall; \
pre-commit install; \
deactivate; \
fi
. venv/bin/activate && pre-commit run --files $$(git diff --name-only master) && deactivate
Executable
+275
View File
@@ -0,0 +1,275 @@
[![License Apache 2.0](https://badgen.net/badge/license/apache2.0/blue)](https://github.com/deepspeedai/DeepSpeed/blob/master/LICENSE)
[![PyPI version](https://badge.fury.io/py/deepspeed.svg)](https://pypi.org/project/deepspeed/)
[![Downloads](https://static.pepy.tech/badge/deepspeed)](https://pepy.tech/project/deepspeed)
[![Build](https://badgen.net/badge/build/check-status/blue)](#build-pipeline-status)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9530/badge)](https://www.bestpractices.dev/projects/9530)
[![Twitter](https://img.shields.io/twitter/follow/DeepSpeedAI)](https://twitter.com/intent/follow?screen_name=DeepSpeedAI)
[![Japanese Twitter](https://img.shields.io/badge/%E6%97%A5%E6%9C%AC%E8%AA%9ETwitter-%40DeepSpeedAI_JP-blue)](https://twitter.com/DeepSpeedAI_JP)
[![Chinese Zhihu](https://img.shields.io/badge/%E7%9F%A5%E4%B9%8E-%E5%BE%AE%E8%BD%AFDeepSpeed-blue)](https://www.zhihu.com/people/deepspeed)
[![Slack](https://img.shields.io/badge/Slack-4A154B?style=for-the-badge&logo=slack&logoColor=white)](https://join.slack.com/t/deepspeedworkspace/shared_invite/zt-3a8pjd8dd-PCj2hMvR4Y2syPwVnjEoww)
<div align="center">
<img src="docs/assets/images/DeepSpeed_light.svg#gh-light-mode-only" width="400px">
<img src="docs/assets/images/DeepSpeed_dark_transparent.svg#gh-dark-mode-only" width="400px">
</div>
## Office Hours
DeepSpeed hosts regular office hours on the last Tuesday of each month at 12:00 America/New_York to discuss development plans, features, etc. This meeting is public for anyone to join and ask questions.
The meeting is hosted on Zoom and can be joined [here](https://zoom-lfx.platform.linuxfoundation.org/meeting/93902569995?password=7d9c4fc9-3efa-4715-88f0-df8a6deb008b).
## Latest News
* [2026/05] [Using Muon Optimizer with DeepSpeed](https://github.com/deepspeedai/DeepSpeed/blob/master/blogs/muon-optimizer/README.md)
* [2026/05] [System DMA (SDMA) for ZeRO-3: offload collectives off compute units on AMD GPUs for better overlap](https://github.com/deepspeedai/DeepSpeed/blob/master/examples/sdma_allgather/README.md)
* [2026/03] DeepSpeed Team gave a tutorial at ASPLOS 2026 titled ["Building Efficient Large-Scale Model Systems with DeepSpeed: From Open-Source Foundations to Emerging Research" ](https://supercomputing-system-ai-lab.github.io/events/asplos2026-llm-tutorial/index.html)
* [2026/03] [Our SuperOffload work received an Honorable Mention for the ASPLOS 2026 Best Paper Award](https://dl.acm.org/doi/10.1145/3760250.3762217)
* [2025/12] [DeepSpeed Core API updates: PyTorch-style backward and low-precision master states](https://github.com/deepspeedai/DeepSpeed/blob/master/blogs/core_api_update/README.md)
* [2025/11] [DeepSpeed ZeRO++ powers large-scale distillation training of LLMs for Recommendation Systems at LinkedIn](https://aclanthology.org/2025.emnlp-industry.119/)
* [2025/10] We hosted the [Ray x DeepSpeed Meetup](https://luma.com/3wctqteh) at Anyscale. We shared our most recent work on SuperOffload, ZenFlow, Muon Optimizer Support, Arctic Long Sequence Training and DeepCompile. Please find the meetup slides [here](https://docs.google.com/presentation/d/1eM3mY6oW9GYkRy1Xz0iOnbbEr5T1t0JJXOM5BKtR-Ks/edit?slide=id.g38615d6b4c2_0_87#slide=id.g38615d6b4c2_0_87).
* [2025/10] [SuperOffload: Unleashing the Power of Large-Scale LLM Training on Superchips](https://pytorch.org/blog/superoffload-unleashing-the-power-of-large-scale-llm-training-on-superchips/)
* [2025/10] [Study of ZenFlow and ZeRO offload performance with DeepSpeed CPU core binding](https://github.com/deepspeedai/DeepSpeed/blob/master/blogs/zenflow-corebinding/README.md)
* [2025/08] [ZenFlow: Stall-Free Offloading Engine for LLM Training](https://pytorch.org/blog/zenflow-stall-free-offloading-engine-for-llm-training/)
* [2025/06] [Arctic Long Sequence Training (ALST) with DeepSpeed: Scalable And Efficient Training For Multi-Million Token Sequences](https://www.snowflake.com/en/engineering-blog/arctic-long-sequence-training-multi-million-token-ai/)
* [2025/06] [DeepNVMe: Affordable I/O scaling for Deep Learning Applications](https://github.com/deepspeedai/DeepSpeed/blob/master/blogs/deepnvme/06-2025/README.md)
<!-- NOTE: we must use html for news items otherwise links will be broken in the 'more news' section -->
<details>
<!-- NOTE: Maintain only three items in 'more news' section -->
<summary>More news</summary>
<ul>
<li>[2025/04] <a href="https://github.com/deepspeedai/DeepSpeed/blob/master/blogs/deepcompile/README.md">DeepCompile: Unlocking Compiler Optimization for Distributed Training</a></li>
<li>[2025/03] <a href="https://github.com/deepspeedai/DeepSpeed/blob/master/blogs/huggingface-tp/README.md">DeepSpeed AutoTP: Automatic Tensor Parallel Training of Hugging Face models</a></li>
<li>[2024/12] <a href="https://github.com/deepspeedai/DeepSpeed/blob/master/blogs/ulysses-offload/README.md">Ulysses-Offload: Democratizing Long Context LLM Training</a></li>
</ul>
</details>
---
# Extreme Speed and Scale for DL Training
***[DeepSpeed](https://www.deepspeed.ai/) enabled the world's most powerful language models (at the time of this writing) such as [MT-530B](https://www.microsoft.com/en-us/research/blog/using-deepspeed-and-megatron-to-train-megatron-turing-nlg-530b-the-worlds-largest-and-most-powerful-generative-language-model/) and [BLOOM](https://huggingface.co/blog/bloom-megatron-deepspeed)***. DeepSpeed offers a confluence of [system innovations](https://www.deepspeed.ai/training/), that has made large scale DL training effective, and efficient, greatly improved ease of use, and redefined the DL training landscape in terms of scale that is possible. These innovations include ZeRO, ZeRO-Infinity, 3D-Parallelism, Ulysses Sequence Parallelism, DeepSpeed-MoE, etc.
---
# DeepSpeed Adoption
DeepSpeed was an important part of Microsofts
[AI at Scale](https://www.microsoft.com/en-us/research/project/ai-at-scale/)
initiative to enable next-generation AI capabilities at scale, where you can find more
information [here](https://innovation.microsoft.com/en-us/exploring-ai-at-scale).
DeepSpeed has been used to train many different large-scale models, below is a list of several examples that we are aware of (if you'd like to include your model please submit a PR):
* [Megatron-Turing NLG (530B)](https://www.microsoft.com/en-us/research/blog/using-deepspeed-and-megatron-to-train-megatron-turing-nlg-530b-the-worlds-largest-and-most-powerful-generative-language-model/)
* [Jurassic-1 (178B)](https://uploads-ssl.webflow.com/60fd4503684b466578c0d307/61138924626a6981ee09caf6_jurassic_tech_paper.pdf)
* [BLOOM (176B)](https://huggingface.co/blog/bloom-megatron-deepspeed)
* [GLM (130B)](https://github.com/THUDM/GLM-130B)
* [xTrimoPGLM (100B)](https://www.biorxiv.org/content/10.1101/2023.07.05.547496v2)
* [YaLM (100B)](https://github.com/yandex/YaLM-100B)
* [GPT-NeoX (20B)](https://github.com/EleutherAI/gpt-neox)
* [AlexaTM (20B)](https://www.amazon.science/blog/20b-parameter-alexa-model-sets-new-marks-in-few-shot-learning)
* [Turing NLG (17B)](https://www.microsoft.com/en-us/research/blog/turing-nlg-a-17-billion-parameter-language-model-by-microsoft/)
* [METRO-LM (5.4B)](https://arxiv.org/pdf/2204.06644.pdf)
DeepSpeed has been integrated with several different popular open-source DL frameworks such as:
| | Documentation |
| ---------------------------------------------------------------------------------------------- | -------------------------------------------- |
<img src="docs/assets/images/transformers-light.png#gh-light-mode-only" width="250px"><img src="docs/assets/images/transformers-dark.png#gh-dark-mode-only" width="250px"> | [Transformers with DeepSpeed](https://huggingface.co/docs/transformers/deepspeed) |
| <img src="docs/assets/images/accelerate-light.png#gh-light-mode-only" width="250px"><img src="docs/assets/images/accelerate-dark.png#gh-dark-mode-only" width="250px"> | [Accelerate with DeepSpeed](https://huggingface.co/docs/accelerate/usage_guides/deepspeed) |
| <img src="docs/assets/images/lightning-light.svg#gh-light-mode-only" width="200px"><img src="docs/assets/images/lightning-dark.svg#gh-dark-mode-only" width="200px"> | [Lightning with DeepSpeed](https://lightning.ai/docs/pytorch/stable/advanced/model_parallel.html#deepspeed) |
| <img src="docs/assets/images/mosaicml.svg" width="200px"> | [MosaicML with DeepSpeed](https://docs.mosaicml.com/projects/composer/en/latest/trainer/using_the_trainer.html?highlight=deepspeed#deepspeed-integration) |
| <img src="docs/assets/images/determined.svg" width="225px"> | [Determined with DeepSpeed](https://docs.determined.ai/latest/training/apis-howto/deepspeed/overview.html) |
| <img src="https://user-images.githubusercontent.com/58739961/187154444-fce76639-ac8d-429b-9354-c6fac64b7ef8.jpg" width=150> | [MMEngine with DeepSpeed](https://mmengine.readthedocs.io/en/latest/common_usage/large_model_training.html#deepspeed) |
---
# Build Pipeline Status
| Description | Status |
| ----------- | ------ |
| NVIDIA | [![nv-pre-compile-ops](https://github.com/deepspeedai/DeepSpeed/actions/workflows/nv-pre-compile-ops.yml/badge.svg)](https://github.com/deepspeedai/DeepSpeed/actions/workflows/nv-pre-compile-ops.yml) [![aws-torch-latest](https://github.com/deepspeedai/DeepSpeed/actions/workflows/aws-torch-latest.yml/badge.svg)](https://github.com/deepspeedai/DeepSpeed/actions/workflows/aws-torch-latest.yml) |
| AMD | [![amd-mi200](https://github.com/deepspeedai/DeepSpeed/actions/workflows/amd-mi200.yml/badge.svg?branch=master)](https://github.com/deepspeedai/DeepSpeed/actions/workflows/amd-mi200.yml) |
| CPU | [![torch-latest-cpu](https://github.com/deepspeedai/DeepSpeed/actions/workflows/cpu-torch-latest.yml/badge.svg?branch=master)](https://github.com/deepspeedai/DeepSpeed/actions/workflows/cpu-torch-latest.yml) |
| Intel Gaudi | [![hpu-gaudi2](https://github.com/deepspeedai/DeepSpeed/actions/workflows/hpu-gaudi2.yml/badge.svg?branch=master)](https://github.com/deepspeedai/DeepSpeed/actions/workflows/hpu-gaudi2.yml) |
| Intel XPU | [![xpu-max1100](https://github.com/deepspeedai/DeepSpeed/actions/workflows/xpu-max1100.yml/badge.svg?branch=master)](https://github.com/deepspeedai/DeepSpeed/actions/workflows/xpu-max1100.yml) |
| Integrations | [![aws-accelerate](https://github.com/deepspeedai/DeepSpeed/actions/workflows/aws-accelerate.yml/badge.svg)](https://github.com/deepspeedai/DeepSpeed/actions/workflows/aws-accelerate.yml) |
| Misc | [![Formatting](https://github.com/deepspeedai/DeepSpeed/actions/workflows/formatting.yml/badge.svg?branch=master)](https://github.com/deepspeedai/DeepSpeed/actions/workflows/formatting.yml) [![pages-build-deployment](https://github.com/deepspeedai/DeepSpeed/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/deepspeedai/DeepSpeed/actions/workflows/pages/pages-build-deployment) [![Documentation Status](https://readthedocs.org/projects/deepspeed/badge/?version=latest)](https://deepspeed.readthedocs.io/en/latest/?badge=latest)[![python](https://github.com/deepspeedai/DeepSpeed/actions/workflows/python.yml/badge.svg?branch=master)](https://github.com/deepspeedai/DeepSpeed/actions/workflows/python.yml) |
| Huawei Ascend NPU | [![Huawei Ascend NPU](https://github.com/Ascend/Ascend-CI/actions/workflows/deepspeed.yaml/badge.svg?branch=main)](https://github.com/Ascend/Ascend-CI/actions/workflows/deepspeed.yaml) |
# Installation
The quickest way to get started with DeepSpeed is via pip, this will install
the latest release of DeepSpeed which is not tied to specific PyTorch or CUDA
versions. DeepSpeed includes several C++/CUDA extensions that we commonly refer
to as our 'ops'. By default, all of these extensions/ops will be built
just-in-time (JIT) using [torch's JIT C++ extension loader that relies on
ninja](https://pytorch.org/docs/stable/cpp_extension.html) to build and
dynamically link them at runtime.
## Requirements
* [PyTorch](https://pytorch.org/) must be installed _before_ installing DeepSpeed.
* For full feature support we recommend a version of PyTorch that is >= 2.0 and ideally the latest PyTorch stable release.
* A CUDA or ROCm compiler such as [nvcc](https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/#introduction) or [hipcc](https://github.com/ROCm-Developer-Tools/HIPCC) used to compile C++/CUDA/HIP extensions.
* Specific GPUs we develop and test against are listed below, this doesn't mean your GPU will not work if it doesn't fall into this category it's just DeepSpeed is most well tested on the following:
* NVIDIA: Pascal, Volta, Ampere, and Hopper architectures
* AMD: MI100 and MI200
## Contributed HW support
* DeepSpeed now support various HW accelerators.
| Contributor | Hardware | Accelerator Name | Contributor validated | Upstream validated |
|-------------|-------------------------------------|------------------| --------------------- |--------------------|
| Huawei | Huawei Ascend NPU | npu | Yes | No |
| Intel | Intel(R) Gaudi(R) 2 AI accelerator | hpu | Yes | Yes |
| Intel | Intel(R) Xeon(R) Processors | cpu | Yes | Yes |
| Intel | Intel(R) Data Center GPU Max series | xpu | Yes | Yes |
| Tecorigin | Scalable Data Analytics Accelerator | sdaa | Yes | No |
## PyPI
We regularly push releases to [PyPI](https://pypi.org/project/deepspeed/) and encourage users to install from there in most cases.
```bash
pip install deepspeed
```
After installation, you can validate your install and see which extensions/ops
your machine is compatible with via the DeepSpeed environment report.
```bash
ds_report
```
If you would like to pre-install any of the DeepSpeed extensions/ops (instead
of JIT compiling) or install pre-compiled ops via PyPI please see our [advanced
installation instructions](https://www.deepspeed.ai/tutorials/advanced-install/).
## Windows
Many DeepSpeed features are supported on Windows for both training and inference. You can read more about this in the original blog post [here](https://github.com/deepspeedai/DeepSpeed/tree/master/blogs/windows/08-2024/README.md). Among features that are currently not supported are async io (AIO) and GDS (which does not support Windows).
1. Install PyTorch, such as pytorch 2.3+cu121.
2. Install Visual C++ build tools, such as VS2022 C++ x64/x86 build tools.
3. Launch Cmd console with Administrator permissions for creating required symlink folders and ensure MSVC tools are added to your PATH or launch the Developer Command Prompt for Visual Studio 2022 with administrator permissions.
4. Run `build_win.bat` to build wheel in `dist` folder.
# Further Reading
All DeepSpeed documentation, tutorials, and blogs can be found on our website: [deepspeed.ai](https://www.deepspeed.ai/)
| | Description |
| ---------------------------------------------------------------------------------------------- | -------------------------------------------- |
| [Getting Started](https://www.deepspeed.ai/getting-started/) | First steps with DeepSpeed |
| [DeepSpeed JSON Configuration](https://www.deepspeed.ai/docs/config-json/) | Configuring DeepSpeed |
| [API Documentation](https://deepspeed.readthedocs.io/en/latest/) | Generated DeepSpeed API documentation |
| [Tutorials](https://www.deepspeed.ai/tutorials/) | Tutorials |
| [Blogs](https://www.deepspeed.ai/posts/) | Blogs |
# CI funding
This being an open source project we rely on others to provide us resources for CI hardware. At this moment Modal is kindly supporting our GPU CI runs by funding the hardware for us. Modal is an AI infrastructure platform for inference, fine-tuning, batch jobs and more. Get started with $30/mo in free credits today at https://modal.com. We have been getting an amazing support from Modal's team and will surely recommend them to your business.
# Contributing
DeepSpeed welcomes your contributions! Please see our
[contributing](CONTRIBUTING.md) guide for more details on formatting, testing,
etc.<br/>
Thanks so much to all of our amazing contributors!
<a href="https://github.com/deepspeedai/DeepSpeed/graphs/contributors">
<img src="https://contrib.rocks/image?repo=microsoft/DeepSpeed&r=" width="800px"/>
</a>
## Developer Certificate of Origin
This project welcomes contributions and suggestions. Most contributions require you to
agree to a Developer Certificate of Origin [DCO](https://wiki.linuxfoundation.org/dco)
stating that they agree to the terms published at https://developercertificate.org for
that *particular* contribution.
DCOs are per-commit, so each commit needs to be signed off. These can be signed in
the commit by adding the `-s` flag. DCO enforcement can also be signed off in the PR
itself by clicking on the DCO enforcement check.
## Code of Conduct
This project has adopted the [Microsoft Open Source Code of
Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact
[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
# Publications
1. Samyam Rajbhandari, Jeff Rasley, Olatunji Ruwase, Yuxiong He. (2019) ZeRO: memory optimizations toward training trillion parameter models. [arXiv:1910.02054](https://arxiv.org/abs/1910.02054) and [In Proceedings of the International Conference for High Performance Computing, Networking, Storage and Analysis (SC '20)](https://dl.acm.org/doi/10.5555/3433701.3433727).
2. Jeff Rasley, Samyam Rajbhandari, Olatunji Ruwase, and Yuxiong He. (2020) DeepSpeed: System Optimizations Enable Training Deep Learning Models with Over 100 Billion Parameters. [In Proceedings of the 26th ACM SIGKDD International Conference on Knowledge Discovery & Data Mining (KDD '20, Tutorial)](https://dl.acm.org/doi/10.1145/3394486.3406703).
3. Minjia Zhang, Yuxiong He. (2020) Accelerating Training of Transformer-Based Language Models with Progressive Layer Dropping. [arXiv:2010.13369](https://arxiv.org/abs/2010.13369) and [NeurIPS 2020](https://proceedings.neurips.cc/paper/2020/hash/a1140a3d0df1c81e24ae954d935e8926-Abstract.html).
4. Jie Ren, Samyam Rajbhandari, Reza Yazdani Aminabadi, Olatunji Ruwase, Shuangyan Yang, Minjia Zhang, Dong Li, Yuxiong He. (2021) ZeRO-Offload: Democratizing Billion-Scale Model Training. [arXiv:2101.06840](https://arxiv.org/abs/2101.06840) and [USENIX ATC 2021](https://www.usenix.org/conference/atc21/presentation/ren-jie). [[paper]](https://arxiv.org/abs/2101.06840) [[slides]](https://www.usenix.org/system/files/atc21_slides_ren-jie.pdf) [[blog]](https://www.microsoft.com/en-us/research/blog/deepspeed-extreme-scale-model-training-for-everyone/)
5. Hanlin Tang, Shaoduo Gan, Ammar Ahmad Awan, Samyam Rajbhandari, Conglong Li, Xiangru Lian, Ji Liu, Ce Zhang, Yuxiong He. (2021) 1-bit Adam: Communication Efficient Large-Scale Training with Adam's Convergence Speed. [arXiv:2102.02888](https://arxiv.org/abs/2102.02888) and [ICML 2021](http://proceedings.mlr.press/v139/tang21a.html).
6. Samyam Rajbhandari, Olatunji Ruwase, Jeff Rasley, Shaden Smith, Yuxiong He. (2021) ZeRO-Infinity: Breaking the GPU Memory Wall for Extreme Scale Deep Learning. [arXiv:2104.07857](https://arxiv.org/abs/2104.07857) and [SC 2021](https://dl.acm.org/doi/abs/10.1145/3458817.3476205). [[paper]](https://arxiv.org/abs/2104.07857) [[slides]](docs/assets/files/SC21-ZeRO-Infinity.pdf) [[blog]](https://www.microsoft.com/en-us/research/blog/zero-infinity-and-deepspeed-unlocking-unprecedented-model-scale-for-deep-learning-training/)
7. Conglong Li, Ammar Ahmad Awan, Hanlin Tang, Samyam Rajbhandari, Yuxiong He. (2021) 1-bit LAMB: Communication Efficient Large-Scale Large-Batch Training with LAMB's Convergence Speed. [arXiv:2104.06069](https://arxiv.org/abs/2104.06069) and [HiPC 2022](https://hipc.org/advance-program/).
8. Conglong Li, Minjia Zhang, Yuxiong He. (2021) The Stability-Efficiency Dilemma: Investigating Sequence Length Warmup for Training GPT Models. [arXiv:2108.06084](https://arxiv.org/abs/2108.06084) and [NeurIPS 2022](https://openreview.net/forum?id=JpZ5du_Kdh).
9. Yucheng Lu, Conglong Li, Minjia Zhang, Christopher De Sa, Yuxiong He. (2022) Maximizing Communication Efficiency for Large-scale Training via 0/1 Adam. [arXiv:2202.06009](https://arxiv.org/abs/2202.06009).
10. Samyam Rajbhandari, Conglong Li, Zhewei Yao, Minjia Zhang, Reza Yazdani Aminabadi, Ammar Ahmad Awan, Jeff Rasley, Yuxiong He. (2022) DeepSpeed-MoE: Advancing Mixture-of-Experts Inference and Training to Power Next-Generation AI Scale [arXiv:2201.05596](https://arxiv.org/abs/2201.05596) and [ICML 2022](https://proceedings.mlr.press/v162/rajbhandari22a.html). [[pdf]](https://arxiv.org/abs/2201.05596) [[slides]](docs/assets/files/ICML-5mins.pdf) [[blog]](https://www.microsoft.com/en-us/research/blog/deepspeed-advancing-moe-inference-and-training-to-power-next-generation-ai-scale/)
11. Shaden Smith, Mostofa Patwary, Brandon Norick, Patrick LeGresley, Samyam Rajbhandari, Jared Casper, Zhun Liu, Shrimai Prabhumoye, George Zerveas, Vijay Korthikanti, Elton Zhang, Rewon Child, Reza Yazdani Aminabadi, Julie Bernauer, Xia Song, Mohammad Shoeybi, Yuxiong He, Michael Houston, Saurabh Tiwary, Bryan Catanzaro. (2022) Using DeepSpeed and Megatron to Train Megatron-Turing NLG 530B, A Large-Scale Generative Language Model [arXiv:2201.11990](https://arxiv.org/abs/2201.11990).
12. Xiaoxia Wu, Zhewei Yao, Minjia Zhang, Conglong Li, Yuxiong He. (2022) Extreme Compression for Pre-trained Transformers Made Simple and Efficient. [arXiv:2206.01859](https://arxiv.org/abs/2206.01859) and [NeurIPS 2022](https://openreview.net/forum?id=xNeAhc2CNAl).
13. Zhewei Yao, Reza Yazdani Aminabadi, Minjia Zhang, Xiaoxia Wu, Conglong Li, Yuxiong He. (2022) ZeroQuant: Efficient and Affordable Post-Training Quantization for Large-Scale Transformers. [arXiv:2206.01861](https://arxiv.org/abs/2206.01861) and [NeurIPS 2022](https://openreview.net/forum?id=f-fVCElZ-G1) [[slides]](docs/assets/files/zeroquant_series.pdf) [[blog]](https://www.microsoft.com/en-us/research/blog/deepspeed-compression-a-composable-library-for-extreme-compression-and-zero-cost-quantization/)
14. Reza Yazdani Aminabadi, Samyam Rajbhandari, Minjia Zhang, Ammar Ahmad Awan, Cheng Li, Du Li, Elton Zheng, Jeff Rasley, Shaden Smith, Olatunji Ruwase, Yuxiong He. (2022) DeepSpeed Inference: Enabling Efficient Inference of Transformer Models at Unprecedented Scale. [arXiv:2207.00032](https://arxiv.org/abs/2207.00032) and [SC 2022](https://dl.acm.org/doi/abs/10.5555/3571885.3571946). [[paper]](https://arxiv.org/abs/2207.00032) [[slides]](docs/assets/files/sc22-ds-inference.pdf) [[blog]](https://www.microsoft.com/en-us/research/blog/deepspeed-accelerating-large-scale-model-inference-and-training-via-system-optimizations-and-compression/)
15. Zhewei Yao, Xiaoxia Wu, Conglong Li, Connor Holmes, Minjia Zhang, Cheng Li, Yuxiong He. (2022) Random-LTD: Random and Layerwise Token Dropping Brings Efficient Training for Large-scale Transformers. [arXiv:2211.11586](https://arxiv.org/abs/2211.11586).
16. Conglong Li, Zhewei Yao, Xiaoxia Wu, Minjia Zhang, Yuxiong He. (2022) DeepSpeed Data Efficiency: Improving Deep Learning Model Quality and Training Efficiency via Efficient Data Sampling and Routing. [arXiv:2212.03597](https://arxiv.org/abs/2212.03597) [ENLSP2023 Workshop at NeurIPS2023](https://neurips2023-enlsp.github.io/)
17. Xiaoxia Wu, Cheng Li, Reza Yazdani Aminabadi, Zhewei Yao, Yuxiong He. (2023) Understanding INT4 Quantization for Transformer Models: Latency Speedup, Composability, and Failure Cases. [arXiv:2301.12017](https://arxiv.org/abs/2301.12017) and [ICML2023](https://icml.cc/Conferences/2023).
18. Syed Zawad, Cheng Li, Zhewei Yao, Elton Zheng, Yuxiong He, Feng Yan. (2023) DySR: Adaptive Super-Resolution via Algorithm and System Co-design. [ICLR:2023](https://openreview.net/forum?id=Pgtn4l6eKjv).
19. Sheng Shen, Zhewei Yao, Chunyuan Li, Trevor Darrell, Kurt Keutzer, Yuxiong He. (2023) Scaling Vision-Language Models with Sparse Mixture of Experts. [arXiv:2303.07226](https://arxiv.org/abs/2303.07226) and [Finding at EMNLP2023](https://2023.emnlp.org/).
20. Quentin Anthony, Ammar Ahmad Awan, Jeff Rasley, Yuxiong He, Aamir Shafi, Mustafa Abduljabbar, Hari Subramoni, Dhabaleswar Panda. (2023) MCR-DL: Mix-and-Match Communication Runtime for Deep Learning [arXiv:2303.08374](https://arxiv.org/abs/2303.08374) and will appear at IPDPS 2023.
21. Siddharth Singh, Olatunji Ruwase, Ammar Ahmad Awan, Samyam Rajbhandari, Yuxiong He, Abhinav Bhatele. (2023) A Hybrid Tensor-Expert-Data Parallelism Approach to Optimize Mixture-of-Experts Training [arXiv:2303.06318](https://arxiv.org/abs/2303.06318) and [ICS 2023](https://dl.acm.org/doi/10.1145/3577193.3593704).
22. Guanhua Wang, Heyang Qin, Sam Ade Jacobs, Xiaoxia Wu, Connor Holmes, Zhewei Yao, Samyam Rajbhandari, Olatunji Ruwase, Feng Yan, Lei Yang, Yuxiong He. (2023) ZeRO++: Extremely Efficient Collective Communication for Giant Model Training [arXiv:2306.10209](https://arxiv.org/abs/2306.10209) and [ML for Sys Workshop at NeurIPS2023](http://mlforsystems.org/) [[blog]](https://www.microsoft.com/en-us/research/blog/deepspeed-zero-a-leap-in-speed-for-llm-and-chat-model-training-with-4x-less-communication/)
23. Zhewei Yao, Xiaoxia Wu, Cheng Li, Stephen Youn, Yuxiong He. (2023) ZeroQuant-V2: Exploring Post-training Quantization in LLMs from Comprehensive Study to Low Rank Compensation [arXiv:2303.08302](https://arxiv.org/abs/2303.08302) and [ENLSP2023 Workshop at NeurIPS2023](https://neurips2023-enlsp.github.io/) [[slides]](docs/assets/files/zeroquant_series.pdf)
24. Pareesa Ameneh Golnari, Zhewei Yao, Yuxiong He. (2023) Selective Guidance: Are All the Denoising Steps of Guided Diffusion Important? [arXiv:2305.09847](https://arxiv.org/abs/2305.09847)
25. Zhewei Yao, Reza Yazdani Aminabadi, Olatunji Ruwase, Samyam Rajbhandari, Xiaoxia Wu, Ammar Ahmad Awan, Jeff Rasley, Minjia Zhang, Conglong Li, Connor Holmes, Zhongzhu Zhou, Michael Wyatt, Molly Smith, Lev Kurilenko, Heyang Qin, Masahiro Tanaka, Shuai Che, Shuaiwen Leon Song, Yuxiong He. (2023) DeepSpeed-Chat: Easy, Fast and Affordable RLHF Training of ChatGPT-like Models at All Scales [arXiv:2308.01320](https://arxiv.org/abs/2308.01320).
26. Xiaoxia Wu, Zhewei Yao, Yuxiong He. (2023) ZeroQuant-FP: A Leap Forward in LLMs Post-Training W4A8 Quantization Using Floating-Point Formats [arXiv:2307.09782](https://arxiv.org/abs/2307.09782) and [ENLSP2023 Workshop at NeurIPS2023](https://neurips2023-enlsp.github.io/) [[slides]](docs/assets/files/zeroquant_series.pdf)
27. Zhewei Yao, Xiaoxia Wu, Conglong Li, Minjia Zhang, Heyang Qin, Olatunji Ruwase, Ammar Ahmad Awan, Samyam Rajbhandari, Yuxiong He. (2023) DeepSpeed-VisualChat: Multi-Round Multi-Image Interleave Chat via Multi-Modal Causal Attention [arXiv:2309.14327](https://arxiv.org/pdf/2309.14327.pdf)
28. Shuaiwen Leon Song, Bonnie Kruft, Minjia Zhang, Conglong Li, Shiyang Chen, Chengming Zhang, Masahiro Tanaka, Xiaoxia Wu, Jeff Rasley, Ammar Ahmad Awan, Connor Holmes, Martin Cai, Adam Ghanem, Zhongzhu Zhou, Yuxiong He, et al. (2023) DeepSpeed4Science Initiative: Enabling Large-Scale Scientific Discovery through Sophisticated AI System Technologies [arXiv:2310.04610](https://arxiv.org/abs/2310.04610) [[blog]](https://www.microsoft.com/en-us/research/blog/announcing-the-deepspeed4science-initiative-enabling-large-scale-scientific-discovery-through-sophisticated-ai-system-technologies/)
29. Zhewei Yao, Reza Yazdani Aminabadi, Stephen Youn, Xiaoxia Wu, Elton Zheng, Yuxiong He. (2023) ZeroQuant-HERO: Hardware-Enhanced Robust Optimized Post-Training Quantization Framework for W8A8 Transformers [arXiv:2310.17723](https://arxiv.org/abs/2310.17723)
30. Xiaoxia Wu, Haojun Xia, Stephen Youn, Zhen Zheng, Shiyang Chen, Arash Bakhtiari, Michael Wyatt, Reza Yazdani Aminabadi, Yuxiong He, Olatunji Ruwase, Leon Song, Zhewei Yao (2023) ZeroQuant(4+2): Redefining LLMs Quantization with a New FP6-Centric Strategy for Diverse Generative Tasks [arXiv:2312.08583](https://arxiv.org/abs/2312.08583)
31. Haojun Xia, Zhen Zheng, Xiaoxia Wu, Shiyang Chen, Zhewei Yao, Stephen Youn, Arash Bakhtiari, Michael Wyatt, Donglin Zhuang, Zhongzhu Zhou, Olatunji Ruwase, Yuxiong He, Shuaiwen Leon Song. (2024) FP6-LLM: Efficiently Serving Large Language Models Through FP6-Centric Algorithm-System Co-Design [arXiv:2401.14112](https://arxiv.org/abs/2401.14112)
32. Sam Ade Jacobs, Masahiro Tanaka, Chengming Zhang, Minjia Zhang, Reza Yazdani Aminadabi, Shuaiwen Leon Song, Samyam Rajbhandari, Yuxiong He. (2024) [System Optimizations for Enabling Training of Extreme Long Sequence Transformer Models](https://dl.acm.org/doi/10.1145/3662158.3662806)
33. Xinyu Lian, Sam Ade Jacobs, Lev Kurilenko, Masahiro Tanaka, Stas Bekman, Olatunji Ruwase, Minjia Zhang. (2024) Universal Checkpointing: Efficient and Flexible Checkpointing for Large Scale Distributed Training [arXiv:2406.18820](https://arxiv.org/abs/2406.18820)
34. Stas Bekman, Samyam Rajbhandari, Michael Wyatt, Jeff Rasley, Tunji Ruwase, Zhewei Yao, Aurick Qiao, Yuxiong He. (2025) Arctic Long Sequence Training: Scalable And Efficient Training For Multi-Million Token Sequences [arXiv:2506.13996](https://arxiv.org/abs/2506.13996)
35. Tingfeng Lan, Yusen Wu, Bin Ma, Zhaoyuan Su, Rui Yang, Tekin Bicer, Masahiro Tanaka, Olatunji Ruwase, Dong Li, Yue Cheng. (2025) ZenFlow: Enabling Stall-Free Offloading Training via Asynchronous Updates [arXiv:2505.12242](https://arxiv.org/abs/2505.12242)
36. Kayhan Behdin, Ata Fatahibaarzi, Qingquan Song, Yun Dai, Aman Gupta, Zhipeng Wang, Hejian Sang, Shao Tang, Gregory Dexter, Sirou Zhu, Siyu Zhu, Tejas Dharamsi, Vignesh Kothapalli, Zhoutong Fu, Yihan Cao, Pin-Lun Hsu, Fedor Borisyuk, Natesh S. Pillai, Luke Simon, Rahul Mazumder.(2025) Scaling Down, Serving Fast: Compressing and Deploying Efficient LLMs for Recommendation Systems [EMNLP 2025](https://aclanthology.org/2025.emnlp-industry.119/)
37. Xinyu Lian, Masahiro Tanaka, Olatunji Ruwase, Minjia Zhang. (2026) SuperOffload: Unleashing the Power of Large-Scale LLM Training on Superchips [arxiv](https://arxiv.org/abs/2509.21271), [ASPLOS 2026](https://www.asplos-conference.org/asplos2026)
# Videos
1. DeepSpeed KDD 2020 Tutorial
1. [Overview](https://www.youtube.com/watch?v=CaseqC45DNc&list=PLa85ZdUjfWS21mgibJ2vCvLziprjpKoW0&index=29)
2. [ZeRO + large model training](https://www.youtube.com/watch?v=y4_bCiAsIAk&list=PLa85ZdUjfWS21mgibJ2vCvLziprjpKoW0&index=28)
3. [17B T-NLG demo](https://www.youtube.com/watch?v=9V-ZbP92drg&list=PLa85ZdUjfWS21mgibJ2vCvLziprjpKoW0&index=27)
4. [Fastest BERT training + RScan tuning](https://www.youtube.com/watch?v=o1K-ZG9F6u0&list=PLa85ZdUjfWS21mgibJ2vCvLziprjpKoW0&index=26)
5. DeepSpeed hands on deep dive: [part 1](https://www.youtube.com/watch?v=_NOk-mBwDYg&list=PLa85ZdUjfWS21mgibJ2vCvLziprjpKoW0&index=92), [part 2](https://www.youtube.com/watch?v=sG6_c4VXLww&list=PLa85ZdUjfWS21mgibJ2vCvLziprjpKoW0&index=94), [part 3](https://www.youtube.com/watch?v=k9yPkBTayos&list=PLa85ZdUjfWS21mgibJ2vCvLziprjpKoW0&index=93)
6. [FAQ](https://www.youtube.com/watch?v=nsHu6vEgPew&list=PLa85ZdUjfWS21mgibJ2vCvLziprjpKoW0&index=24)
2. Microsoft Research Webinar
* Registration is free and all videos are available on-demand.
* [ZeRO & Fastest BERT: Increasing the scale and speed of deep learning training in DeepSpeed](https://note.microsoft.com/MSR-Webinar-DeepSpeed-Registration-On-Demand.html).
3. [DeepSpeed on AzureML](https://youtu.be/yBVXR8G8Bg8)
4. [Large Model Training and Inference with DeepSpeed // Samyam Rajbhandari // LLMs in Prod Conference](https://www.youtube.com/watch?v=cntxC3g22oU) [[slides]](docs/assets/files/presentation-mlops.pdf)
5. Community Tutorials
* [DeepSpeed: All the tricks to scale to gigantic models (Mark Saroufim)](https://www.youtube.com/watch?v=pDGI668pNg0)
* [Turing-NLG, DeepSpeed and the ZeRO optimizer (Yannic Kilcher)](https://www.youtube.com/watch?v=tC01FRB0M7w)
* [Ultimate Guide To Scaling ML Models (The AI Epiphany)](https://www.youtube.com/watch?v=hc0u4avAkuM)
+7
View File
@@ -0,0 +1,7 @@
# WeHub 来源说明
- 原始项目:`deepspeedai/DeepSpeed`
- 原始仓库:https://github.com/deepspeedai/DeepSpeed
- 导入方式:上游默认分支的最新快照
- 原作者、版权和许可证信息以原始仓库及本仓库 LICENSE 为准
- 本文件仅用于记录来源,不代表 WeHub 是原项目作者
+33
View File
@@ -0,0 +1,33 @@
# Security Policy
## Reporting security issues
Please report security issues privately using [the vulnerability submission form](https://github.com/deepspeedai/deepspeed/security/advisories/new).
## Issue triage
Reports will then be triaged by the maintainers.
## Threat model
Please see [PyTorch's Security Policy](https://github.com/pytorch/pytorch/blob/main/SECURITY.md) for more information and recommendations on how to securely interact with models.
## Issue severity
We will determine the risk of each issue, taking into account our experience dealing with past issues, versions affected, common defaults, and use cases. We use the following severity categories:
### CRITICAL Severity
Vulnerabilities that allow remote attackers to execute arbitrary code, take full control of the system, or significantly compromise confidentiality, integrity, or availability without any interaction or privileges needed, examples include remote code execution via network, deserialization issues that allow exploit chains. Generally those issues which are rated as CVSS ≥ 9.0.
### HIGH Severity
Serious security flaws that allow elevated impact—like RCE in specific, limited contexts or significant data loss—but require advanced conditions or some trust, examples include RCE in advanced deployment modes (e.g. multi-node), or high impact issues where some sort of privileged network access is required. These issues typically have CVSS scores between 7.0 and 8.9
### MODERATE Severity
Vulnerabilities that cause denial of service or partial disruption, but do not allow arbitrary code execution or data breach and have limited impact. These issues have a CVSS rating between 4.0 and 6.9
### LOW Severity
Minor issues such as informational disclosures, logging errors, non-exploitable flaws, or weaknesses that require local or high-privilege access and offer negligible impact. Examples include side channel attacks or hash collisions. These issues often have CVSS scores less than 4.0
+48
View File
@@ -0,0 +1,48 @@
# Third-Party Notices
This file records third-party source notices for code incorporated into
DeepSpeed source files.
## TorchTitan
The following files contain portions derived from TorchTitan:
- `deepspeed/module_inject/auto_ep_layer.py`
- `deepspeed/moe/ep_experts.py`
- `deepspeed/moe/ep_kernels.py`
- `deepspeed/moe/ep_router.py`
Source project: https://github.com/pytorch/torchtitan
TorchTitan is licensed under the BSD 3-Clause License:
```text
BSD 3-Clause License
(c) Meta Platforms, Inc. and affiliates.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
+7
View File
@@ -0,0 +1,7 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
from .abstract_accelerator import DeepSpeedAccelerator
from .real_accelerator import get_accelerator, set_accelerator, is_current_accelerator_supported
+303
View File
@@ -0,0 +1,303 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
import abc
from abc import ABC
class DeepSpeedAccelerator(ABC):
supports_nvtx_domain = False
def __init__(self):
self._name = None
self._communication_backend_name = None
self._compile_backend = None
@abc.abstractmethod
def is_synchronized_device(self):
...
@abc.abstractmethod
def use_host_timers(self):
...
@abc.abstractmethod
def resolves_data_dependency(self):
...
@abc.abstractmethod
def handles_memory_backpressure(self):
...
# Device APIs
@abc.abstractmethod
def device_name(self, device_index):
...
@abc.abstractmethod
def device(self, device_index):
...
@abc.abstractmethod
def set_device(self, device_index):
...
@abc.abstractmethod
def current_device(self):
...
@abc.abstractmethod
def current_device_name(self):
...
@abc.abstractmethod
def device_count(self):
...
@abc.abstractmethod
def synchronize(self, device_index=None):
...
# RNG APIs
@abc.abstractmethod
def random(self):
...
@abc.abstractmethod
def set_rng_state(self, new_state, device_index=None):
...
@abc.abstractmethod
def get_rng_state(self, device_index=None):
...
@abc.abstractmethod
def manual_seed(self, seed):
...
@abc.abstractmethod
def manual_seed_all(self, seed):
...
@abc.abstractmethod
def initial_seed(self):
...
@abc.abstractmethod
def default_generator(self, device_index):
...
# Streams/Events
@property
@abc.abstractmethod
def Stream(self):
...
@abc.abstractmethod
def stream(self, stream):
...
@abc.abstractmethod
def current_stream(self, device_index=None):
...
@abc.abstractmethod
def default_stream(self, device_index=None):
...
@property
@abc.abstractmethod
def Event(self):
...
# Memory management
@abc.abstractmethod
def empty_cache(self):
...
@abc.abstractmethod
def memory_allocated(self, device_index=None):
...
@abc.abstractmethod
def max_memory_allocated(self, device_index=None):
...
@abc.abstractmethod
def reset_max_memory_allocated(self, device_index=None):
...
@abc.abstractmethod
def memory_cached(self, device_index=None):
...
@abc.abstractmethod
def max_memory_cached(self, device_index=None):
...
@abc.abstractmethod
def reset_max_memory_cached(self, device_index=None):
...
@abc.abstractmethod
def memory_stats(self, device_index=None):
...
@abc.abstractmethod
def reset_peak_memory_stats(self, device_index=None):
...
@abc.abstractmethod
def memory_reserved(self, device_index=None):
...
@abc.abstractmethod
def max_memory_reserved(self, device_index=None):
...
@abc.abstractmethod
def total_memory(self, device_index=None):
...
@abc.abstractmethod
def available_memory(self, device_index=None):
...
# Data types
@abc.abstractmethod
def is_bf16_supported(self):
...
@abc.abstractmethod
def is_fp16_supported(self):
...
@abc.abstractmethod
def supported_dtypes(self):
...
# Misc
@abc.abstractmethod
def is_available(self):
...
@abc.abstractmethod
def range_push(self, msg, domain=None, category=None):
...
@abc.abstractmethod
def range_pop(self, domain=None):
...
@abc.abstractmethod
def lazy_call(self, callback):
...
@abc.abstractmethod
def communication_backend_name(self):
...
@abc.abstractmethod
def is_triton_supported(self):
...
# Graph operations
@abc.abstractmethod
def create_graph(self):
...
@abc.abstractmethod
def capture_to_graph(self, graph, pool=None, stream=None):
...
@abc.abstractmethod
def replay_graph(self, graph):
...
# Tensor operations
@property
@abc.abstractmethod
def BFloat16Tensor(self):
...
@property
@abc.abstractmethod
def ByteTensor(self):
...
@property
@abc.abstractmethod
def DoubleTensor(self):
...
@property
@abc.abstractmethod
def FloatTensor(self):
...
@property
@abc.abstractmethod
def HalfTensor(self):
...
@property
@abc.abstractmethod
def IntTensor(self):
...
@property
@abc.abstractmethod
def LongTensor(self):
...
@abc.abstractmethod
def pin_memory(self, tensor, align_bytes=1):
...
@abc.abstractmethod
def is_pinned(self, tensor):
...
@abc.abstractmethod
def on_accelerator(self, tensor):
...
@abc.abstractmethod
def op_builder_dir(self):
...
# create an instance of op builder, specified by class_name
@abc.abstractmethod
def create_op_builder(self, class_name):
...
# return an op builder class, specified by class_name
@abc.abstractmethod
def get_op_builder(self, class_name):
...
@abc.abstractmethod
def build_extension(self):
...
@abc.abstractmethod
def export_envs(self):
...
@abc.abstractmethod
def visible_devices_envs(self):
...
@abc.abstractmethod
def set_visible_devices_envs(self, current_env, local_accelerator_ids):
...
@abc.abstractmethod
def get_compile_backend(self):
...
@abc.abstractmethod
def set_compile_backend(self, backend):
...
+358
View File
@@ -0,0 +1,358 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
from .abstract_accelerator import DeepSpeedAccelerator
# During setup stage torch may not be installed, pass on no torch will
# allow op builder related API to be executed.
try:
import torch
except ImportError as e:
pass
try:
import oneccl_bindings_for_pytorch # noqa: F401 # type: ignore
oneccl_imported_p = True
except ImportError as e:
oneccl_imported_p = False
import os
# accelerator for Intel CPU
class CPU_Accelerator(DeepSpeedAccelerator):
def __init__(self):
self._name = 'cpu'
self._compile_backend = "inductor"
if oneccl_imported_p:
self._communication_backend_name = 'ccl'
else:
# fallback to gloo if oneccl_binding_for_pytorch is not installed
self._communication_backend_name = 'gloo'
try:
import psutil
mem = psutil.Process().memory_info().rss
self.max_mem = mem
except ImportError as e:
self.max_mem = 0
def is_synchronized_device(self):
return True
def use_host_timers(self):
return self.is_synchronized_device()
def resolves_data_dependency(self):
return self.is_synchronized_device()
def handles_memory_backpressure(self):
return self.is_synchronized_device()
# Device APIs
def device_name(self, device_index=None):
return 'cpu'
def device(self, device_index=None):
return None
def set_device(self, device_index):
return
def current_device(self):
return os.environ.get('LOCAL_RANK', 0)
def current_device_name(self):
return 'cpu'
def device_count(self):
device_count = int(os.environ.get('LOCAL_SIZE', 0))
if device_count > 0:
return device_count
else:
from deepspeed.utils.numa import get_numa_cores
# Count NUMA node for number of cpu accelerators. On machine with HBM
# In flat mode, HBM is in separate NUMA node with no cores on this node.
# Ignore these NUMA nodes with no cores.
numa_core_lists = get_numa_cores()
if not numa_core_lists:
return 1
numa_count = 0
prev_core_list = []
for core_list in numa_core_lists:
if len(core_list) > 0 and core_list != prev_core_list:
numa_count += 1
prev_core_list = core_list
return numa_count
def synchronize(self, device_index=None):
return
# RNG APIs
def random(self):
return torch.random
def set_rng_state(self, new_state, device_index=None):
if device_index is None:
return torch.set_rng_state(new_state)
return torch.set_rng_state(new_state, device_index)
def get_rng_state(self, device_index=None):
return torch.get_rng_state()
def manual_seed(self, seed):
return torch.manual_seed(seed)
def manual_seed_all(self, seed):
return torch.manual_seed(seed)
def initial_seed(self):
return torch.initial_seed()
def default_generator(self, device_index):
return torch.default_generator
# Streams/Events
@property
def Stream(self):
return None
def stream(self, stream):
from deepspeed.runtime.utils import noop_context
return noop_context()
def current_stream(self, device_index=None):
return None
def default_stream(self, device_index=None):
return None
@property
def Event(self):
return None
# Memory management
def empty_cache(self):
return
def get_rss(self):
import psutil
mem = psutil.Process().memory_info().rss
if mem > self.max_mem:
self.max_mem = mem
return mem
def reset_rss(self):
import psutil
mem = psutil.Process().memory_info().rss
self.max_mem = mem
return mem
def memory_allocated(self, device_index=None):
return self.get_rss()
def max_memory_allocated(self, device_index=None):
self.get_rss()
return self.max_mem
def reset_max_memory_allocated(self, device_index=None):
self.reset_rss()
return
def memory_cached(self, device_index=None):
return self.get_rss()
def max_memory_cached(self, device_index=None):
self.get_rss()
return self.max_mem
def reset_max_memory_cached(self, device_index=None):
self.reset_rss()
return
def memory_stats(self, device_index=None):
mem = self.get_rss()
mem_stat = {}
mem_stat['allocated_bytes.all.current'] = mem
mem_stat['allocated_bytes.all.peak'] = self.max_mem
return mem_stat
def reset_peak_memory_stats(self, device_index=None):
self.reset_rss()
return
def memory_reserved(self, device_index=None):
return self.get_rss()
def max_memory_reserved(self, device_index=None):
self.get_rss()
return self.max_mem
def total_memory(self, device_index=None):
import psutil
return psutil.virtual_memory().total
def available_memory(self, device_index=None):
import psutil
return psutil.virtual_memory().available
# Misc
def is_available(self):
return True
def range_push(self, msg, domain=None, category=None):
# TODO itt is currently not supported yet
# return torch.profiler.itt.range_push(msg)
return
def range_pop(self, domain=None):
# TODO itt is currently not supported yet
# return torch.profiler.itt.range_pop()
return
def lazy_call(self, callback):
return callback()
def communication_backend_name(self):
return self._communication_backend_name
def is_triton_supported(self):
return False
# Data types
def is_bf16_supported(self):
return True
def is_fp16_supported(self):
try:
if torch.ops.mkldnn._is_mkldnn_fp16_supported():
return True
except Exception:
return False
def supported_dtypes(self):
supported_dtypes = [torch.float, torch.bfloat16]
if self.is_fp16_supported():
supported_dtypes.append(torch.float16)
return supported_dtypes
# Graph operations
def create_graph(self):
return None
def capture_to_graph(self, graph, pool=None, stream=None):
from deepspeed.runtime.utils import noop_context
return noop_context()
def replay_graph(self, graph):
return
# Tensor operations
@property
def BFloat16Tensor(self):
return torch.BFloat16Tensor
@property
def ByteTensor(self):
return torch.ByteTensor
@property
def DoubleTensor(self):
return torch.DoubleTensor
@property
def FloatTensor(self):
return torch.FloatTensor
@property
def HalfTensor(self):
return torch.HalfTensor
@property
def IntTensor(self):
return torch.IntTensor
@property
def LongTensor(self):
return torch.LongTensor
def pin_memory(self, tensor, align_bytes=1):
return tensor
def is_pinned(self, tensor):
return tensor.is_pinned()
def op_builder_dir(self):
try:
# is op_builder from deepspeed or a 3p version? this should only succeed if it's deepspeed
# if successful this also means we're doing a local install and not JIT compile path
from op_builder import __deepspeed__ # noqa: F401 # type: ignore
return "op_builder.cpu"
except ImportError:
return "deepspeed.ops.op_builder.cpu"
def on_accelerator(self, tensor):
device_str = str(tensor.device)
if device_str.startswith('cpu'):
return True
else:
return False
# create an instance of op builder and return, name specified by class_name
def create_op_builder(self, op_name):
builder_class = self.get_op_builder(op_name)
if builder_class is not None:
return builder_class()
return None
# return an op builder class, name specified by class_name
def get_op_builder(self, class_name):
try:
# is op_builder from deepspeed or a 3p version? this should only succeed if it's deepspeed
# if successful this also means we're doing a local install and not JIT compile path
from op_builder import __deepspeed__ # noqa: F401 # type: ignore
from op_builder.cpu import AsyncIOBuilder, CCLCommBuilder, ShareMemCommBuilder, FusedAdamBuilder, CPUAdamBuilder, NotImplementedBuilder
except ImportError:
from deepspeed.ops.op_builder.cpu import AsyncIOBuilder, CCLCommBuilder, ShareMemCommBuilder, FusedAdamBuilder, CPUAdamBuilder, NotImplementedBuilder
if class_name == "CCLCommBuilder":
return CCLCommBuilder
elif class_name == "ShareMemCommBuilder":
return ShareMemCommBuilder
elif class_name == "FusedAdamBuilder":
return FusedAdamBuilder
elif class_name == "CPUAdamBuilder":
return CPUAdamBuilder
elif class_name == "AsyncIOBuilder":
return AsyncIOBuilder
else:
# return a NotImplementedBuilder to avoid get NoneType[Name] in unit tests
return NotImplementedBuilder
def build_extension(self):
from torch.utils.cpp_extension import BuildExtension
return BuildExtension
def export_envs(self):
return []
# TODO: cpu's visible envs is confirmed, keep as CUDA_VISIBLE_DEVICES
def visible_devices_envs(self):
return ['CUDA_VISIBLE_DEVICES']
def set_visible_devices_envs(self, current_env, local_accelerator_ids):
for env in self.visible_devices_envs():
current_env[env] = ",".join(map(str, local_accelerator_ids))
def get_compile_backend(self):
return self._compile_backend
def set_compile_backend(self, backend):
supported_backends = torch._dynamo.list_backends(exclude_tags=())
if backend in supported_backends:
self._compile_backend = backend
else:
raise ValueError(
f"{backend} not supported by {self.device_name()}. Supported Backends are {supported_backends}")
+404
View File
@@ -0,0 +1,404 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
import functools
import os
import pkgutil
import importlib
import sys
from .abstract_accelerator import DeepSpeedAccelerator
# During setup stage torch may not be installed, pass on no torch will
# allow op builder related API to be executed.
try:
import torch.cuda
except ImportError:
pass
try:
import nvtx
except ImportError:
nvtx = None
# Delay import pynvml to avoid import error when CUDA is not available
pynvml = None
class CUDA_Accelerator(DeepSpeedAccelerator):
supports_nvtx_domain = True
def __init__(self):
self._name = 'cuda'
self._communication_backend_name = 'nccl' if sys.platform != 'win32' else 'gloo'
self._compile_backend = "inductor"
self._nvtx_domains = {}
if pynvml is None:
self._init_pynvml()
def _init_pynvml(self):
global pynvml
try:
import pynvml
except ImportError:
return
try:
pynvml.nvmlInit()
except pynvml.NVMLError:
pynvml = None
return
def is_synchronized_device(self):
return False
def use_host_timers(self):
return self.is_synchronized_device()
def resolves_data_dependency(self):
return self.is_synchronized_device()
def handles_memory_backpressure(self):
return self.is_synchronized_device()
# Device APIs
def device_name(self, device_index=None):
if device_index is None:
return 'cuda'
return 'cuda:{}'.format(device_index)
def communication_backend_version(self):
return torch.cuda.nccl.version()
def device(self, device_index=None):
return torch.device('cuda', device_index)
def set_device(self, device_index):
torch.cuda.set_device(device_index)
def current_device(self):
return torch.cuda.current_device()
def current_device_name(self):
return 'cuda:{}'.format(torch.cuda.current_device())
def device_count(self):
return torch.cuda.device_count()
def synchronize(self, device_index=None):
return torch.cuda.synchronize(device_index)
# RNG APIs
def random(self):
return torch.random
def set_rng_state(self, new_state, device_index=None):
if device_index is None:
return torch.cuda.set_rng_state(new_state)
return torch.cuda.set_rng_state(new_state, device_index)
def get_rng_state(self, device_index=None):
if device_index is None:
return torch.cuda.get_rng_state()
return torch.cuda.get_rng_state(device_index)
def manual_seed(self, seed):
return torch.cuda.manual_seed(seed)
def manual_seed_all(self, seed):
return torch.cuda.manual_seed_all(seed)
def initial_seed(self):
return torch.cuda.initial_seed()
def default_generator(self, device_index):
return torch.cuda.default_generators[device_index]
# Streams/Events
@property
def Stream(self):
return torch.cuda.Stream
def stream(self, stream):
return torch.cuda.stream(stream)
def current_stream(self, device_index=None):
return torch.cuda.current_stream(device_index)
def default_stream(self, device_index=None):
return torch.cuda.default_stream(device_index)
@property
def Event(self):
return torch.cuda.Event
# Memory management
def empty_cache(self):
return torch.cuda.empty_cache()
def memory_allocated(self, device_index=None):
return torch.cuda.memory_allocated(device_index)
def max_memory_allocated(self, device_index=None):
return torch.cuda.max_memory_allocated(device_index)
def reset_max_memory_allocated(self, device_index=None):
return torch.cuda.reset_max_memory_allocated(device_index)
def memory_cached(self, device_index=None):
return torch.cuda.memory_cached(device_index)
def max_memory_cached(self, device_index=None):
return torch.cuda.max_memory_cached(device_index)
def reset_max_memory_cached(self, device_index=None):
return torch.cuda.reset_max_memory_cached(device_index)
def memory_stats(self, device_index=None):
if hasattr(torch.cuda, 'memory_stats'):
return torch.cuda.memory_stats(device_index)
def reset_peak_memory_stats(self, device_index=None):
if hasattr(torch.cuda, 'reset_peak_memory_stats'):
return torch.cuda.reset_peak_memory_stats(device_index)
def memory_reserved(self, device_index=None):
if hasattr(torch.cuda, 'memory_reserved'):
return torch.cuda.memory_reserved(device_index)
def max_memory_reserved(self, device_index=None):
if hasattr(torch.cuda, 'max_memory_reserved'):
return torch.cuda.max_memory_reserved(device_index)
def total_memory(self, device_index=None):
return torch.cuda.get_device_properties(device_index).total_memory
def _get_nvml_gpu_id(self, torch_gpu_id):
"""
credit: https://discuss.pytorch.org/t/making-pynvml-match-torch-device-ids-cuda-visible-devices/103020
Remap torch device id to nvml device id, respecting CUDA_VISIBLE_DEVICES.
If the latter isn't set return the same id
"""
# if CUDA_VISIBLE_DEVICES is used automagically remap the id since pynvml ignores this env var
if "CUDA_VISIBLE_DEVICES" in os.environ:
ids = list(map(int, os.environ.get("CUDA_VISIBLE_DEVICES", "").split(",")))
return ids[torch_gpu_id] # remap
else:
return torch_gpu_id
def available_memory(self, device_index=None):
if pynvml:
if device_index is None:
device_index = self.current_device()
handle = pynvml.nvmlDeviceGetHandleByIndex(self._get_nvml_gpu_id(device_index))
info = pynvml.nvmlDeviceGetMemoryInfo(handle)
return info.free
else:
return self.total_memory(device_index) - self.memory_allocated(device_index)
# Data types
def is_bf16_supported(self):
if not torch.cuda.is_available():
return True
return torch.cuda.is_bf16_supported()
def is_fp16_supported(self):
if not torch.cuda.is_available():
return True
# See https://docs.nvidia.com/deeplearning/tensorrt/support-matrix/index.html#hardware-precision-matrix
# FP16 on compute capability 6.x is deprecated
allow_deprecated_fp16 = os.environ.get('DS_ALLOW_DEPRECATED_FP16', '0') == '1'
major, _ = torch.cuda.get_device_capability()
if major >= 7:
return True
elif major == 6 and allow_deprecated_fp16:
return True
else:
return False
def supported_dtypes(self):
supported_dtypes = [torch.float]
if self.is_fp16_supported():
supported_dtypes.append(torch.half)
if self.is_bf16_supported():
supported_dtypes.append(torch.bfloat16)
return supported_dtypes
# Misc
def is_available(self):
return torch.cuda.is_available()
def _get_nvtx_domain(self, domain):
if nvtx is None or domain is None:
return None
if domain not in self._nvtx_domains:
self._nvtx_domains[domain] = nvtx.get_domain(domain)
return self._nvtx_domains[domain]
def range_push(self, msg, domain=None, category=None):
nvtx_domain = self._get_nvtx_domain(domain)
if nvtx_domain is not None:
return nvtx_domain.push_range(message=msg, category=category)
torch_nvtx = getattr(torch.cuda, 'nvtx', None)
if torch_nvtx is not None and hasattr(torch_nvtx, 'range_push'):
return torch_nvtx.range_push(msg)
def range_pop(self, domain=None):
nvtx_domain = self._get_nvtx_domain(domain)
if nvtx_domain is not None:
return nvtx_domain.pop_range()
torch_nvtx = getattr(torch.cuda, 'nvtx', None)
if torch_nvtx is not None and hasattr(torch_nvtx, 'range_pop'):
return torch_nvtx.range_pop()
def lazy_call(self, callback):
return torch.cuda._lazy_call(callback)
def communication_backend_name(self):
return self._communication_backend_name
def is_triton_supported(self):
if not self.is_available():
return False
major, _ = torch.cuda.get_device_capability()
if major >= 8:
return True
else:
return False
# Graph operations
def create_graph(self):
return torch.cuda.CUDAGraph()
def capture_to_graph(self, graph, pool=None, stream=None):
return torch.cuda.graph(graph, pool, stream)
def replay_graph(self, graph):
graph.replay()
return
# Tensor operations
@property
def BFloat16Tensor(self):
return functools.partial(torch.tensor, dtype=torch.bfloat16, device='cuda')
@property
def ByteTensor(self):
return functools.partial(torch.tensor, dtype=torch.uint8, device='cuda')
@property
def DoubleTensor(self):
return functools.partial(torch.tensor, dtype=torch.double, device='cuda')
@property
def FloatTensor(self):
return functools.partial(torch.tensor, dtype=torch.float, device='cuda')
@property
def HalfTensor(self):
return functools.partial(torch.tensor, dtype=torch.half, device='cuda')
@property
def IntTensor(self):
return functools.partial(torch.tensor, dtype=torch.int, device='cuda')
@property
def LongTensor(self):
return functools.partial(torch.tensor, dtype=torch.long, device='cuda')
def pin_memory(self, tensor, align_bytes=1):
return tensor.pin_memory()
def is_pinned(self, tensor):
return tensor.is_pinned()
def on_accelerator(self, tensor):
device_str = str(tensor.device)
if device_str.startswith('cuda:'):
return True
else:
return False
def op_builder_dir(self):
try:
# is op_builder from deepspeed or a 3p version? this should only succeed if it's deepspeed
# if successful this also means we're doing a local install and not JIT compile path
from op_builder import __deepspeed__ # noqa: F401 # type: ignore
return "op_builder"
except ImportError:
return "deepspeed.ops.op_builder"
# dict that holds class name <--> class type mapping i.e.
# 'AsyncIOBuilder': <class 'op_builder.async_io.AsyncIOBuilder'>
# this dict will be filled at init stage
class_dict = None
def _lazy_init_class_dict(self):
if self.class_dict is not None:
return
else:
self.class_dict = {}
# begin initialize for create_op_builder()
# put all valid class name <--> class type mapping into class_dict
op_builder_dir = self.op_builder_dir()
op_builder_module = importlib.import_module(op_builder_dir)
op_builder_absolute_path = os.path.dirname(op_builder_module.__file__)
for _, module_name, _ in pkgutil.iter_modules([op_builder_absolute_path]):
# avoid self references,
# skip sub_directories which contains ops for other backend(cpu, npu, etc.).
if module_name != 'all_ops' and module_name != 'builder' and not os.path.isdir(
os.path.join(op_builder_absolute_path, module_name)):
module = importlib.import_module("{}.{}".format(op_builder_dir, module_name))
for member_name in module.__dir__():
if member_name.endswith(
'Builder'
) and member_name != "OpBuilder" and member_name != "CUDAOpBuilder" and member_name != "TorchCPUOpBuilder": # avoid abstract classes
if not member_name in self.class_dict:
self.class_dict[member_name] = getattr(module, member_name)
# end initialize for create_op_builder()
# create an instance of op builder and return, name specified by class_name
def create_op_builder(self, class_name):
self._lazy_init_class_dict()
if class_name in self.class_dict:
return self.class_dict[class_name]()
else:
return None
# return an op builder class, name specified by class_name
def get_op_builder(self, class_name):
self._lazy_init_class_dict()
if class_name in self.class_dict:
return self.class_dict[class_name]
else:
return None
def build_extension(self):
from torch.utils.cpp_extension import BuildExtension
return BuildExtension
def export_envs(self):
return ['NCCL']
def visible_devices_envs(self):
return ['CUDA_VISIBLE_DEVICES']
def set_visible_devices_envs(self, current_env, local_accelerator_ids):
for env in self.visible_devices_envs():
current_env[env] = ",".join(map(str, local_accelerator_ids))
def get_compile_backend(self):
return self._compile_backend
def set_compile_backend(self, backend):
supported_backends = torch._dynamo.list_backends(exclude_tags=())
if backend in supported_backends:
self._compile_backend = backend
else:
raise ValueError(
f"{backend} not supported by {self.device_name()}. Supported Backends are {supported_backends}")
+328
View File
@@ -0,0 +1,328 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
import functools
import os
import pkgutil
import importlib
import torch
from .abstract_accelerator import DeepSpeedAccelerator
class HPU_Accelerator(DeepSpeedAccelerator):
def __init__(self):
self._name = 'hpu'
self._communication_backend_name = 'hccl'
self._compile_backend = "hpu_backend"
self.apply_hpu_workarounds()
try:
import habana_frameworks.torch.hpu as hpu
self.hpu = hpu
torch.use_deterministic_algorithms(True)
# TODO: remove this WA when memory mapping break is resolved.
torch.utils.deterministic.fill_uninitialized_memory = False
except ImportError as e:
raise ValueError(
"HPU_Accelerator requires habana_frameworks.torch.hpu, which is not installed on this system.")
self.fp16_supported = None
def apply_hpu_workarounds(self):
def update_wa_env_var(key, value):
if key not in os.environ.keys():
os.environ[key] = value
update_wa_env_var("PT_HPU_LAZY_ACC_PAR_MODE", "0")
update_wa_env_var("PT_HPU_ENABLE_REFINE_DYNAMIC_SHAPES", "0")
# Device APIs
def is_synchronized_device(self):
return False
def use_host_timers(self):
return False
def resolves_data_dependency(self):
return True
def handles_memory_backpressure(self):
return True
def device_name(self, device_index=None):
# ignoring device_index.
return 'hpu'
def device(self, device_index=None):
return torch.device(self.device_name(device_index))
def set_device(self, device_index):
self.hpu.set_device(device_index)
def current_device(self):
return (self.hpu.current_device())
def current_device_name(self):
return 'hpu:{}'.format(self.current_device())
def device_count(self):
return self.hpu.device_count()
def synchronize(self, device_index=None):
return self.hpu.synchronize()
# RNG APIs
def random(self):
return torch.random
def set_rng_state(self, new_state, device_index=None):
self.hpu.random.set_rng_state(new_state)
def get_rng_state(self, device_index=None):
return self.hpu.random.get_rng_state()
def manual_seed(self, seed):
return self.hpu.random.manual_seed(seed)
def manual_seed_all(self, seed):
self.hpu.random.manual_seed_all(seed)
def initial_seed(self):
return self.hpu.random.initial_seed()
def default_generator(self, device_index):
return self.hpu.random.default_generators[device_index]
# Streams/Events
@property
def Stream(self):
return self.hpu.Stream
def stream(self, stream):
return self.hpu.stream(stream)
def current_stream(self, device_index=None):
return self.hpu.current_stream()
def default_stream(self, device_index=None):
return self.hpu.default_stream()
@property
def Event(self):
import habana_frameworks.torch.core as htcore
return htcore.hpu.Event
# Memory management
def empty_cache(self):
return
def memory_allocated(self, device_index=None):
return self.hpu.memory_allocated()
def max_memory_allocated(self, device_index=None):
return self.hpu.max_memory_allocated()
def reset_max_memory_allocated(self, device_index=None):
return self.hpu.reset_max_memory_allocated()
def memory_cached(self, device_index=None):
return self.hpu.memory_cached(device_index)
def max_memory_cached(self, device_index=None):
return self.hpu.max_memory_cached(device_index)
def reset_max_memory_cached(self, device_index=None):
return None
def memory_stats(self, device_index=None):
return self.hpu.memory_stats(device_index)
def reset_peak_memory_stats(self, device_index=None):
self.hpu.reset_peak_memory_stats(device_index)
def memory_reserved(self, device_index=None):
return self.hpu.memory_reserved(device_index)
def max_memory_reserved(self, device_index=None):
return self.hpu.max_memory_reserved(device_index)
def total_memory(self, device_index=None):
return self.memory_stats(device_index)['Limit']
def available_memory(self, device_index=None):
return self.total_memory(device_index) - self.memory_allocated(device_index)
# Data types
def is_bf16_supported(self):
return True
def is_fp16_supported(self):
if self.fp16_supported is None:
import habana_frameworks.torch.utils.experimental as htexp
self.fp16_supported = htexp._is_fp16_supported()
return self.fp16_supported
def supported_dtypes(self):
supported_dtypes = [torch.float, torch.bfloat16]
if self.is_fp16_supported():
supported_dtypes.append(torch.half)
return supported_dtypes
# Misc
def is_available(self):
return self.hpu.is_available()
def range_push(self, msg, domain=None, category=None):
return
def range_pop(self, domain=None):
return
def lazy_call(self, callback):
callback()
def communication_backend_name(self):
return self._communication_backend_name
def is_triton_supported(self):
return False
# Graph operations
def create_graph(self):
return self.hpu.HPUGraph()
def capture_to_graph(self, graph, pool=None, stream=None):
return self.hpu.graph(graph, stream=stream)
def replay_graph(self, graph):
graph.replay()
return
# Tensor operations
@property
def BFloat16Tensor(self):
return functools.partial(torch.tensor, dtype=torch.bfloat16, device='hpu')
@property
def ByteTensor(self):
return functools.partial(torch.tensor, dtype=torch.uint8, device='hpu')
@property
def DoubleTensor(self):
return functools.partial(torch.tensor, dtype=torch.double, device='hpu')
@property
def FloatTensor(self):
return functools.partial(torch.tensor, dtype=torch.float, device='hpu')
@property
def HalfTensor(self):
return functools.partial(torch.tensor, dtype=torch.half, device='hpu')
@property
def IntTensor(self):
return functools.partial(torch.tensor, dtype=torch.int, device='hpu')
@property
def LongTensor(self):
return functools.partial(torch.tensor, dtype=torch.long, device='hpu')
def pin_memory(self, tensor, align_bytes=1):
return tensor.pin_memory(self.device())
def is_pinned(self, tensor):
return tensor.is_pinned()
def on_accelerator(self, tensor):
device_str = str(tensor.device)
if device_str.startswith('hpu:'):
return True
else:
return False
def op_builder_dir(self):
try:
# is op_builder from deepspeed or a 3p version? this should only succeed if it's deepspeed
# if successful this also means we're doing a local install and not JIT compile path
from op_builder import __deepspeed__ # noqa: F401 # type: ignore
return "op_builder.hpu"
except ImportError:
return "deepspeed.ops.op_builder.hpu"
# dict that holds class name <--> class type mapping i.e.
# 'AsyncIOBuilder': <class 'op_builder.async_io.AsyncIOBuilder'>
# this dict will be filled at init stage
class_dict = None
def _lazy_init_class_dict(self):
if self.class_dict is not None:
return
else:
self.class_dict = {}
# begin initialize for create_op_builder()
# put all valid class name <--> class type mapping into class_dict
op_builder_dir = self.op_builder_dir()
op_builder_module = importlib.import_module(op_builder_dir)
op_builder_absolute_path = os.path.dirname(op_builder_module.__file__)
for _, module_name, _ in pkgutil.iter_modules([op_builder_absolute_path]):
# avoid self references,
# skip sub_directories which contains ops for other backend(cpu, npu, etc.).
if module_name != 'all_ops' and module_name != 'builder' and not os.path.isdir(
os.path.join(op_builder_absolute_path, module_name)):
module = importlib.import_module("{}.{}".format(op_builder_dir, module_name))
for member_name in module.__dir__():
if member_name.endswith(
'Builder'
) and member_name != "OpBuilder" and member_name != "CPUOpBuilder" and member_name != "TorchCPUOpBuilder": # avoid abstract classes
if not member_name in self.class_dict:
self.class_dict[member_name] = getattr(module, member_name)
# end initialize for create_op_builder()
# create an instance of op builder and return, name specified by class_name
def create_op_builder(self, class_name):
self._lazy_init_class_dict()
if class_name in self.class_dict:
return self.class_dict[class_name]()
else:
return None
# return an op builder class, name specified by class_name
def get_op_builder(self, class_name):
self._lazy_init_class_dict()
if class_name in self.class_dict:
return self.class_dict[class_name]
else:
return self.class_dict['NotImplementedBuilder'] if 'NotImplementedBuilder' in self.class_dict else None
def build_extension(self):
from torch.utils.cpp_extension import BuildExtension
return BuildExtension
def export_envs(self):
return []
def visible_devices_envs(self):
# Current way deepspeed set this env var is not applicable with all HPU instances
# User has to follow instructions in:
# https://docs.habana.ai/en/latest/PyTorch/Reference/PT_Multiple_Tenants_on_HPU/Multiple_Workloads_Single_Docker.html
# keeping CUDA_VISIBLE_DEVICES
return ['CUDA_VISIBLE_DEVICES'] #['HABANA_VISIBLE_MODULES']
def set_visible_devices_envs(self, current_env, local_accelerator_ids):
for env in self.visible_devices_envs():
current_env[env] = ",".join(map(str, local_accelerator_ids))
def get_compile_backend(self):
return self._compile_backend
def set_compile_backend(self, backend):
supported_backends = torch._dynamo.list_backends(exclude_tags=())
if backend in supported_backends:
self._compile_backend = backend
else:
raise ValueError(
f"{backend} not supported by {self.device_name()}. Supported Backends are {supported_backends}")
+295
View File
@@ -0,0 +1,295 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
import importlib
import inspect
import functools
from .abstract_accelerator import DeepSpeedAccelerator
import torch
# During setup stage torch may not be installed, pass on no torch will
# allow op builder related API to be executed.
class MLU_Accelerator(DeepSpeedAccelerator):
def __init__(self):
self._name = 'mlu'
self._communication_backend_name = 'cncl'
self._compile_backend = "inductor"
self.class_dict = None
def is_synchronized_device(self):
return False
def use_host_timers(self):
return self.is_synchronized_device()
def resolves_data_dependency(self):
return self.is_synchronized_device()
def handles_memory_backpressure(self):
return self.is_synchronized_device()
# Device APIs
def device_name(self, device_index=None):
if device_index == None:
return 'mlu'
return 'mlu:{}'.format(device_index)
def device(self, device_index=None):
return torch.mlu.device(device_index)
def set_device(self, device_index):
torch.mlu.set_device(device_index)
def current_device(self):
return torch.mlu.current_device()
def current_device_name(self):
return 'mlu:{}'.format(torch.mlu.current_device())
def device_count(self):
return torch.mlu.device_count()
def synchronize(self, device_index=None):
return torch.mlu.synchronize(device_index)
# RNG APIs
def random(self):
return torch.random
def set_rng_state(self, new_state, device_index=None):
if device_index is None:
return torch.mlu.set_rng_state(new_state)
return torch.mlu.set_rng_state(new_state, device_index)
def get_rng_state(self, device_index=None):
if device_index is None:
return torch.mlu.get_rng_state()
return torch.mlu.get_rng_state(device_index)
def manual_seed(self, seed):
return torch.mlu.manual_seed(seed)
def manual_seed_all(self, seed):
return torch.mlu.manual_seed_all(seed)
def initial_seed(self, seed):
return torch.mlu.initial_seed(seed)
def default_generator(self, device_index):
return torch.mlu.default_generators[device_index]
# Streams/Events
@property
def Stream(self):
return torch.mlu.Stream
def stream(self, stream):
return torch.mlu.stream(stream)
def current_stream(self, device_index=None):
return torch.mlu.current_stream(device_index)
def default_stream(self, device_index=None):
return torch.mlu.default_stream(device_index)
@property
def Event(self):
return torch.mlu.Event
# Memory management
def empty_cache(self):
return torch.mlu.empty_cache()
def memory_allocated(self, device_index=None):
return torch.mlu.memory_allocated(device_index)
def max_memory_allocated(self, device_index=None):
return torch.mlu.max_memory_allocated(device_index)
def reset_max_memory_allocated(self, device_index=None):
return torch.mlu.reset_max_memory_allocated(device_index)
def memory_cached(self, device_index=None):
return torch.mlu.memory_cached(device_index)
def max_memory_cached(self, device_index=None):
return torch.mlu.max_memory_cached(device_index)
def reset_max_memory_cached(self, device_index=None):
return torch.mlu.reset_max_memory_cached(device_index)
def memory_stats(self, device_index=None):
if hasattr(torch.mlu, 'memory_stats'):
return torch.mlu.memory_stats(device_index)
def reset_peak_memory_stats(self, device_index=None):
if hasattr(torch.mlu, 'reset_peak_memory_stats'):
return torch.mlu.reset_peak_memory_stats(device_index)
def memory_reserved(self, device_index=None):
if hasattr(torch.mlu, 'memory_reserved'):
return torch.mlu.memory_reserved(device_index)
def max_memory_reserved(self, device_index=None):
if hasattr(torch.mlu, 'max_memory_reserved'):
return torch.mlu.max_memory_reserved(device_index)
def total_memory(self, device_index=None):
return torch.mlu.get_device_properties(device_index).total_memory
def available_memory(self, device_index=None):
return self.total_memory(device_index) - self.memory_allocated(device_index)
# Data types
def is_bf16_supported(self):
return torch.mlu.is_bf16_supported()
def is_fp16_supported(self):
return True
def supported_dtypes(self):
supported_dtypes = [torch.float]
if self.is_fp16_supported():
supported_dtypes.append(torch.half)
if self.is_bf16_supported():
supported_dtypes.append(torch.bfloat16)
return supported_dtypes
# Misc
def is_available(self):
return torch.mlu.is_available()
def range_push(self, msg, domain=None, category=None):
if hasattr(torch.mlu.cnpx, 'range_push'):
return torch.mlu.cnpx.range_push(msg)
def range_pop(self, domain=None):
if hasattr(torch.mlu.cnpx, 'range_pop'):
return torch.mlu.cnpx.range_pop()
def lazy_call(self, callback):
return torch.mlu._lazy_call(callback)
def communication_backend_name(self):
return self._communication_backend_name
def is_triton_supported(self):
return True
# Graph operations
def create_graph(self):
torch.mlu.MLUGraph()
def capture_to_graph(self, graph, pool=None, stream=None):
return torch.mlu.graph(graph, pool, stream)
def replay_graph(self, graph):
graph.replay()
return
# Tensor operations
@property
def BFloat16Tensor(self):
return functools.partial(torch.tensor, dtype=torch.bfloat16, device='mlu')
@property
def ByteTensor(self):
return functools.partial(torch.tensor, dtype=torch.uint8, device='mlu')
@property
def DoubleTensor(self):
return functools.partial(torch.tensor, dtype=torch.double, device='mlu')
@property
def FloatTensor(self):
return functools.partial(torch.tensor, dtype=torch.float, device='mlu')
@property
def HalfTensor(self):
return functools.partial(torch.tensor, dtype=torch.half, device='mlu')
@property
def IntTensor(self):
return functools.partial(torch.tensor, dtype=torch.int, device='mlu')
@property
def LongTensor(self):
return functools.partial(torch.tensor, dtype=torch.long, device='mlu')
def pin_memory(self, tensor):
return tensor.pin_memory()
def is_pinned(self, tensor):
return tensor.is_pinned()
def on_accelerator(self, tensor):
device_str = str(tensor.device)
if device_str.startswith('mlu:'):
return True
else:
return False
def op_builder_dir(self):
try:
# is op_builder from deepspeed or a 3p version? this should only succeed if it's deepspeed
# if successful this also means we're doing a local install and not JIT compile path
from op_builder import __deepspeed__ # noqa: F401 # type: ignore
return "op_builder.mlu"
except ImportError:
return "deepspeed.ops.op_builder.mlu"
def _lazy_init_class_dict(self):
if self.class_dict:
return
op_builder_module = importlib.import_module(self.op_builder_dir())
# get op builder class from op_builder/mlu/__init__.py
self.class_dict = {}
for class_name, class_obj in inspect.getmembers(op_builder_module, inspect.isclass):
self.class_dict[class_name] = class_obj
# create an instance of op builder and return, name specified by class_name
def create_op_builder(self, class_name):
builder_class = self.get_op_builder(class_name)
return builder_class()
# return an op builder class, name specified by class_name
def get_op_builder(self, class_name):
self._lazy_init_class_dict()
if class_name in self.class_dict:
return self.class_dict[class_name]
else:
return self.class_dict['NotImplementedBuilder']
def build_extension(self):
from torch.utils.cpp_extension import BuildExtension
return BuildExtension
def export_envs(self):
return ['NEUWARE_HOME', 'CNCL', 'LD_LIBRARY', 'PATH']
def visible_devices_envs(self):
return ['MLU_VISIBLE_DEVICES']
def set_visible_devices_envs(self, current_env, local_accelerator_ids):
for env in self.visible_devices_envs():
current_env[env] = ",".join(map(str, local_accelerator_ids))
def get_compile_backend(self):
return self._compile_backend
def set_compile_backend(self, backend):
supported_backends = torch._dynamo.list_backends(exclude_tags=())
if backend in supported_backends:
self._compile_backend = backend
else:
raise ValueError(
f"{backend} not supported by {self.device_name()}. Supported Backends are {supported_backends }")
+279
View File
@@ -0,0 +1,279 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
import torch
from .abstract_accelerator import DeepSpeedAccelerator
# During setup stage torch may not be installed, pass on no torch will
# allow op builder related API to be executed.
try:
import torch.mps
except ImportError:
pass
class MPS_Accelerator(DeepSpeedAccelerator):
def __init__(self):
self._name = "mps"
self._communication_backend_name = None
self._compile_backend = "inductor"
def is_synchronized_device(self):
return False
def use_host_timers(self):
# Event timers are not supported on MPS
return True
def resolves_data_dependency(self):
return self.is_synchronized_device()
def handles_memory_backpressure(self):
return self.is_synchronized_device()
# Device APIs
def device_name(self, device_index=None):
if device_index is None:
return "mps"
return "mps:{}".format(device_index)
def device(self, device_index):
return torch.device("mps", index=0)
def set_device(self, device_index):
return
def current_device(self):
return torch.device("mps", index=0)
def current_device_name(self):
return "mps:0"
def device_count(self):
return 1
def synchronize(self, device_index=None):
return torch.mps.synchronize()
# RNG APIs
def random(self):
return torch.random
def set_rng_state(self, new_state, device_index=None):
return torch.mps.set_rng_state(new_state)
def get_rng_state(self, device_index=None):
return torch.mps.get_rng_state()
def manual_seed(self, seed):
return torch.mps.manual_seed(seed)
def manual_seed_all(self, seed):
return torch.mps.manual_seed(seed)
def seed(self):
return torch.mps.seed()
def initial_seed(self):
return
def default_generator(self, device_index):
return
# Streams/Events
@property
def Stream(self):
return None
def stream(self, stream):
return None
def current_stream(self, device_index=None):
return None
def default_stream(self, device_index=None):
return None
@property
def Event(self):
return None
# Memory management
def empty_cache(self):
return torch.mps.empty_cache()
def memory_allocated(self, device_index=None):
return torch.mps.current_allocated_memory()
def max_memory_allocated(self, device_index=None):
return torch.mps.driver_allocated_memory()
def set_per_process_memory_fraction(self, fraction):
return torch.mps.set_per_process_memory_fraction(fraction)
def reset_max_memory_allocated(self, device_index=None):
return
def memory_cached(self, device_index=None):
return
def max_memory_cached(self, device_index=None):
return
def reset_max_memory_cached(self, device_index=None):
return
def memory_stats(self, device_index=None):
return
def reset_peak_memory_stats(self, device_index=None):
return
def memory_reserved(self, device_index=None):
return
def max_memory_reserved(self, device_index=None):
return
def total_memory(self, device_index=None):
return
def available_memory(self, device_index=None):
return
# Data types
def is_bf16_supported(self):
return False
def is_fp16_supported(self):
return False
def supported_dtypes(self):
return [torch.float]
# Misc
def is_available(self):
return hasattr(torch.backends, "mps") and torch.backends.mps.is_available()
def range_push(self, msg, domain=None, category=None):
return
def range_pop(self, domain=None):
return
def lazy_call(self, callback):
return
def communication_backend_name(self):
return self._communication_backend_name
def is_triton_supported(self):
return False
# Graph operations
def create_graph(self):
return None
def capture_to_graph(self, graph, pool=None, stream=None):
from deepspeed.runtime.utils import noop_context
return noop_context()
def replay_graph(self, graph):
return
# Tensor operations
@property
def BFloat16Tensor(self):
return
@property
def ByteTensor(self):
return
@property
def DoubleTensor(self):
return
@property
def FloatTensor(self):
return
@property
def HalfTensor(self):
return
@property
def IntTensor(self):
return
@property
def LongTensor(self):
return
def pin_memory(self, tensor, align_bytes=1):
return tensor.pin_memory()
def is_pinned(self, tensor):
return tensor.is_pinned()
def on_accelerator(self, tensor):
device_str = str(tensor.device)
if device_str.startswith("mps"):
return True
else:
return False
def op_builder_dir(self):
try:
# is op_builder from deepspeed or a 3p version? this should only succeed if it's deepspeed
# if successful this also means we're doing a local install and not JIT compile path
from op_builder import __deepspeed__ # noqa: F401 # type: ignore
return "op_builder"
except ImportError:
return "deepspeed.ops.op_builder"
# create an instance of op builder, specified by class_name
def create_op_builder(self, op_name):
builder_class = self.get_op_builder(op_name)
if builder_class is not None:
return builder_class()
return None
# return an op builder class, specified by class_name
def get_op_builder(self, class_name):
from deepspeed.ops.op_builder.cpu import NotImplementedBuilder
return NotImplementedBuilder
def build_extension(self):
from torch.utils.cpp_extension import BuildExtension
return BuildExtension
def export_envs(self):
return []
# TODO: mpu's visible envs is confirmed, keep as CUDA_VISIBLE_DEVICES
def visible_devices_envs(self):
# TODO: could not find visible devices env for mps
return ['CUDA_VISIBLE_DEVICES']
def set_visible_devices_envs(self, current_env, local_accelerator_ids):
for env in self.visible_devices_envs():
current_env[env] = ",".join(map(str, local_accelerator_ids))
def get_compile_backend(self):
return self._compile_backend
def set_compile_backend(self, backend):
supported_backends = torch._dynamo.list_backends(exclude_tags=())
if backend in supported_backends:
self._compile_backend = backend
else:
raise ValueError(
f"{backend} not supported by {self.device_name()}. Supported Backends are {supported_backends}")
+294
View File
@@ -0,0 +1,294 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
import importlib
import inspect
from .abstract_accelerator import DeepSpeedAccelerator
# During setup stage torch may not be installed, pass on no torch will
# allow op builder related API to be executed.
try:
import torch.npu
except ImportError:
pass
class NPU_Accelerator(DeepSpeedAccelerator):
def __init__(self):
super().__init__()
self._name = 'npu'
self._communication_backend_name = 'hccl'
self._compile_backend = "inductor"
# dict that holds class name <--> class type mapping i.e.
# 'AsyncIOBuilder': <class 'op_builder.async_io.AsyncIOBuilder'>
# this dict will be filled at init stage
self.class_dict = None
def is_synchronized_device(self):
return False
def use_host_timers(self):
return self.is_synchronized_device()
def resolves_data_dependency(self):
return self.is_synchronized_device()
def handles_memory_backpressure(self):
return self.is_synchronized_device()
# Device APIs
def device_name(self, device_index=None):
if device_index is None:
return 'npu'
return 'npu:{}'.format(device_index)
def device(self, device_index=None):
return torch.device('npu', device_index)
def set_device(self, device_index):
torch.npu.set_device(device_index)
def current_device(self):
return torch.npu.current_device()
def current_device_name(self):
return 'npu:{}'.format(torch.npu.current_device())
def device_count(self):
return torch.npu.device_count()
def synchronize(self, device_index=None):
return torch.npu.synchronize(device_index)
# RNG APIs
def random(self):
return torch.random
def set_rng_state(self, new_state, device_index=None):
if device_index is None:
return torch.npu.set_rng_state(new_state)
return torch.npu.set_rng_state(new_state, device_index)
def get_rng_state(self, device_index=None):
if device_index is None:
return torch.npu.get_rng_state()
return torch.npu.get_rng_state(device_index)
def manual_seed(self, seed):
return torch.npu.manual_seed(seed)
def manual_seed_all(self, seed):
return torch.npu.manual_seed_all(seed)
def initial_seed(self):
return torch.npu.initial_seed()
def default_generator(self, device_index):
return torch.npu.default_generators[device_index]
# Streams/Events
@property
def Stream(self):
return torch.npu.Stream
def stream(self, stream):
return torch.npu.stream(stream)
def current_stream(self, device_index=None):
return torch.npu.current_stream(device_index)
def default_stream(self, device_index=None):
return torch.npu.default_stream(device_index)
@property
def Event(self):
return torch.npu.Event
# Memory management
def empty_cache(self):
return torch.npu.empty_cache()
def memory_allocated(self, device_index=None):
return torch.npu.memory_allocated(device_index)
def max_memory_allocated(self, device_index=None):
return torch.npu.max_memory_allocated(device_index)
def reset_max_memory_allocated(self, device_index=None):
return torch.npu.reset_max_memory_allocated(device_index)
def memory_cached(self, device_index=None):
return torch.npu.memory_cached(device_index)
def max_memory_cached(self, device_index=None):
return torch.npu.max_memory_cached(device_index)
def reset_max_memory_cached(self, device_index=None):
return torch.npu.reset_max_memory_cached(device_index)
def memory_stats(self, device_index=None):
if hasattr(torch.npu, 'memory_stats'):
return torch.npu.memory_stats(device_index)
def reset_peak_memory_stats(self, device_index=None):
if hasattr(torch.npu, 'reset_peak_memory_stats'):
return torch.npu.reset_peak_memory_stats(device_index)
def memory_reserved(self, device_index=None):
if hasattr(torch.npu, 'memory_reserved'):
return torch.npu.memory_reserved(device_index)
def max_memory_reserved(self, device_index=None):
if hasattr(torch.npu, 'max_memory_reserved'):
return torch.npu.max_memory_reserved(device_index)
def total_memory(self, device_index=None):
return torch.npu.get_device_properties(device_index).total_memory
def available_memory(self, device_index=None):
return self.total_memory(device_index) - self.memory_allocated(device_index)
# Data types
def is_bf16_supported(self):
return torch.npu.is_bf16_supported()
def is_fp16_supported(self):
return True
def supported_dtypes(self):
return [torch.float, torch.half, torch.bfloat16]
# Misc
def is_available(self):
return torch.npu.is_available()
def range_push(self, msg, domain=None, category=None):
return
def range_pop(self, domain=None):
return
def lazy_call(self, callback):
return torch.npu._lazy_call(callback)
def communication_backend_name(self):
return self._communication_backend_name
def is_triton_supported(self):
return False
# Graph operations
def create_graph(self):
return None
def capture_to_graph(self, graph, pool=None, stream=None):
from deepspeed.runtime.utils import noop_context
return noop_context()
def replay_graph(self, graph):
return
# Tensor operations
@property
def BFloat16Tensor(self):
return torch.npu.BFloat16Tensor
@property
def ByteTensor(self):
return torch.npu.ByteTensor
@property
def DoubleTensor(self):
return torch.npu.DoubleTensor
@property
def FloatTensor(self):
return torch.npu.FloatTensor
@property
def HalfTensor(self):
return torch.npu.HalfTensor
@property
def IntTensor(self):
return torch.npu.IntTensor
@property
def LongTensor(self):
return torch.npu.LongTensor
def pin_memory(self, tensor, align_bytes=1):
return tensor.pin_memory()
def is_pinned(self, tensor):
return tensor.is_pinned()
def on_accelerator(self, tensor):
device_str = str(tensor.device)
if device_str.startswith('npu:'):
return True
else:
return False
def op_builder_dir(self):
try:
# is op_builder from deepspeed or a 3p version? this should only succeed if it's deepspeed
# if successful this also means we're doing a local install and not JIT compile path
from op_builder import __deepspeed__ # noqa: F401 # type: ignore
return "op_builder.npu"
except ImportError:
return "deepspeed.ops.op_builder.npu"
def _lazy_init_class_dict(self):
if self.class_dict:
return
op_builder_module = importlib.import_module(self.op_builder_dir())
# get op builder class from op_builder/npu/__init__.py
self.class_dict = {}
for class_name, class_obj in inspect.getmembers(op_builder_module, inspect.isclass):
self.class_dict[class_name] = class_obj
# create an instance of op builder and return, name specified by class_name
def create_op_builder(self, class_name):
builder_class = self.get_op_builder(class_name)
return None if builder_class is None else builder_class()
# return an op builder class, name specified by class_name
def get_op_builder(self, class_name):
self._lazy_init_class_dict()
if class_name in self.class_dict:
return self.class_dict[class_name]
else:
return self.class_dict['NotImplementedBuilder'] if 'NotImplementedBuilder' in self.class_dict else None
def build_extension(self):
from torch.utils.cpp_extension import BuildExtension
return BuildExtension
def export_envs(self):
return ['ASCEND', 'HCCL', 'LD_LIBRARY', 'PATH']
def visible_devices_envs(self):
return ['ASCEND_RT_VISIBLE_DEVICES']
def set_visible_devices_envs(self, current_env, local_accelerator_ids):
for env in self.visible_devices_envs():
current_env[env] = ",".join(map(str, local_accelerator_ids))
def get_compile_backend(self):
return self._compile_backend
def set_compile_backend(self, backend):
supported_backends = torch._dynamo.list_backends(exclude_tags=())
if backend in supported_backends:
self._compile_backend = backend
else:
raise ValueError(
f"{backend} not supported by {self.device_name()}. Supported Backends are {supported_backends }")
+299
View File
@@ -0,0 +1,299 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
import os
try:
# Importing logger currently requires that torch is installed, hence the try...except
# TODO: Remove logger dependency on torch.
from deepspeed.utils import logger as accel_logger
except ImportError as e:
accel_logger = None
try:
from accelerator.abstract_accelerator import DeepSpeedAccelerator as dsa1
except ImportError as e:
dsa1 = None
try:
from deepspeed.accelerator.abstract_accelerator import DeepSpeedAccelerator as dsa2
except ImportError as e:
dsa2 = None
SUPPORTED_ACCELERATOR_LIST = ['cuda', 'cpu', 'xpu', 'npu', 'mps', 'hpu', 'mlu', 'sdaa', 'supa']
ds_accelerator = None
def _validate_accelerator(accel_obj):
# because abstract_accelerator has different path during
# build time (accelerator.abstract_accelerator)
# and run time (deepspeed.accelerator.abstract_accelerator)
# and extension would import the
# run time abstract_accelerator/DeepSpeedAccelerator as its base
# class, so we need to compare accel_obj with both base class.
# if accel_obj is instance of DeepSpeedAccelerator in one of
# accelerator.abstractor_accelerator
# or deepspeed.accelerator.abstract_accelerator, consider accel_obj
# is a conforming object
if not ((dsa1 is not None and isinstance(accel_obj, dsa1)) or (dsa2 is not None and isinstance(accel_obj, dsa2))):
raise AssertionError(f"{accel_obj.__class__.__name__} accelerator is not subclass of DeepSpeedAccelerator")
# TODO: turn off is_available test since this breaks tests
# assert accel_obj.is_available(), \
# f'{accel_obj.__class__.__name__} accelerator fails is_available() test'
def is_current_accelerator_supported():
return get_accelerator().device_name() in SUPPORTED_ACCELERATOR_LIST
def get_accelerator():
global ds_accelerator
if ds_accelerator is not None:
return ds_accelerator
accelerator_name = None
ds_set_method = None
# 1. Detect whether there is override of DeepSpeed accelerators from environment variable.
if "DS_ACCELERATOR" in os.environ.keys():
accelerator_name = os.environ["DS_ACCELERATOR"]
if accelerator_name == "xpu":
try:
import torch
assert hasattr(torch, 'xpu') and torch.xpu.is_available(), \
"XPU_Accelerator requires PyTorch with XPU support (torch.xpu)."
except (ImportError, AssertionError) as e:
raise ValueError(f"XPU_Accelerator requires PyTorch with XPU support: {e}")
elif accelerator_name == "cpu":
pass
elif accelerator_name == "npu":
try:
import torch_npu # noqa: F401 # type: ignore
except ImportError as e:
raise ValueError("NPU_Accelerator requires torch_npu, which is not installed on this system.")
pass
elif accelerator_name == "sdaa":
try:
import torch_sdaa # noqa: F401 # type: ignore
except ImportError as e:
raise ValueError("SDAA_Accelerator requires torch_sdaa, which is not installed on this system.")
pass
elif accelerator_name == "mps":
try:
import torch.mps
# should use torch.mps.is_available() if it exists someday but this is used as proxy
torch.mps.current_allocated_memory()
except (RuntimeError, ImportError) as e:
raise ValueError("MPS_Accelerator requires torch.mps, which is not installed on this system.")
elif accelerator_name == "hpu":
try:
import habana_frameworks.torch.hpu # noqa: F401
except ImportError as e:
raise ValueError(
"HPU_Accelerator requires habana_frameworks.torch.hpu, which is not installed on this system.")
elif accelerator_name == "mlu":
try:
import torch_mlu # noqa: F401
except ImportError as e:
raise ValueError("MLU_Accelerator requires torch_mlu, which is not installed on this system.")
elif accelerator_name == "supa":
try:
import torch_supa # noqa: F401 # type: ignore
except ImportError as e:
raise ValueError("SUPA_Accelerator requires torch_supa, which is not installed on this system.")
elif accelerator_name not in SUPPORTED_ACCELERATOR_LIST:
raise ValueError(f'DS_ACCELERATOR must be one of {SUPPORTED_ACCELERATOR_LIST}. '
f'Value "{accelerator_name}" is not supported')
ds_set_method = "override"
# 2. If no override, detect which accelerator to use automatically
if accelerator_name is None:
# We need a way to choose among different accelerator types.
# Currently we detect which accelerator extension is installed
# in the environment and use it if the installing answer is True.
# An alternative might be detect whether CUDA device is installed on
# the system but this comes with two pitfalls:
# 1. the system may not have torch pre-installed, so
# get_accelerator().is_available() may not work.
# 2. Some scenario like install on login node (without CUDA device)
# and run on compute node (with CUDA device) may cause mismatch
# between installation time and runtime.
try:
import torch
# Detect XPU via PyTorch
if hasattr(torch, 'xpu'):
if torch.xpu.is_available():
accelerator_name = "xpu"
except ImportError as e:
pass
if accelerator_name is None:
try:
import torch_npu # noqa: F401,F811 # type: ignore
accelerator_name = "npu"
except ImportError as e:
pass
if accelerator_name is None:
try:
import torch_sdaa # noqa: F401,F811 # type: ignore
accelerator_name = "sdaa"
except ImportError as e:
pass
if accelerator_name is None:
try:
import torch.mps
# should use torch.mps.is_available() if it exists someday but this is used as proxy
torch.mps.current_allocated_memory()
accelerator_name = "mps"
except (RuntimeError, ImportError) as e:
pass
if accelerator_name is None:
try:
import habana_frameworks.torch.hpu # noqa: F401,F811
accelerator_name = "hpu"
except ImportError as e:
pass
if accelerator_name is None:
try:
import torch_mlu # noqa: F401,F811
accelerator_name = "mlu"
except ImportError as e:
pass
if accelerator_name is None:
try:
# Detect Biren SUPA GPU. torch_supa spoofs torch.cuda so this #ignore-cuda
# check must come before the CUDA detection below.
import torch_supa # noqa: F401,F811 # type: ignore
import torch
if hasattr(torch, 'supa') and torch.supa.is_available():
accelerator_name = "supa"
except ImportError as e:
pass
if accelerator_name is None:
try:
import torch
# Determine if we are on a GPU or x86 CPU with torch.
# "torch.cuda.is_available()" provides a stronger guarantee, #ignore-cuda
# ensuring that we are free from CUDA initialization errors.
# While "torch.cuda.device_count() > 0" check ensures that #ignore-cuda
# we won't try to do any CUDA calls when no device is available
# For reference: https://github.com/deepspeedai/DeepSpeed/pull/6810
if torch.cuda.device_count() > 0 and torch.cuda.is_available(): #ignore-cuda
accelerator_name = "cuda"
except (RuntimeError, ImportError) as e:
# TODO need a more decent way to detect which accelerator to use, consider using nvidia-smi command for detection
pass
if accelerator_name is None:
# borrow this log from PR#5084
if accel_logger is not None:
accel_logger.warning(
"Setting accelerator to CPU. If you have GPU or other accelerator, we were unable to detect it.")
# cpu added as catch-all when accelerator detection fails
accelerator_name = "cpu"
ds_set_method = "auto detect"
# 3. Set ds_accelerator accordingly
if accelerator_name == "cuda":
from .cuda_accelerator import CUDA_Accelerator
ds_accelerator = CUDA_Accelerator()
elif accelerator_name == "cpu":
from .cpu_accelerator import CPU_Accelerator
ds_accelerator = CPU_Accelerator()
elif accelerator_name == "xpu":
from .xpu_accelerator import XPU_Accelerator
ds_accelerator = XPU_Accelerator()
elif accelerator_name == "npu":
from .npu_accelerator import NPU_Accelerator
ds_accelerator = NPU_Accelerator()
elif accelerator_name == "sdaa":
from .sdaa_accelerator import SDAA_Accelerator
ds_accelerator = SDAA_Accelerator()
elif accelerator_name == "mps":
from .mps_accelerator import MPS_Accelerator
ds_accelerator = MPS_Accelerator()
elif accelerator_name == 'hpu':
from .hpu_accelerator import HPU_Accelerator
ds_accelerator = HPU_Accelerator()
elif accelerator_name == 'mlu':
from .mlu_accelerator import MLU_Accelerator
ds_accelerator = MLU_Accelerator()
elif accelerator_name == 'supa':
from .supa_accelerator import SUPA_Accelerator
ds_accelerator = SUPA_Accelerator()
_validate_accelerator(ds_accelerator)
if accel_logger is not None:
accel_logger.info(f"Setting ds_accelerator to {ds_accelerator._name} ({ds_set_method})")
return ds_accelerator
def set_accelerator(accel_obj):
global ds_accelerator
_validate_accelerator(accel_obj)
if accel_logger is not None and accel_obj is not None:
accel_logger.info(f"Setting ds_accelerator to {accel_obj._name} (model specified)")
ds_accelerator = accel_obj
"""
-----------[code] test_get.py -----------
from deepspeed.accelerator import get_accelerator
my_accelerator = get_accelerator()
logger.info(f'{my_accelerator._name=}')
logger.info(f'{my_accelerator._communication_backend=}')
logger.info(f'{my_accelerator.HalfTensor().device=}')
logger.info(f'{my_accelerator.total_memory()=}')
-----------[code] test_get.py -----------
---[output] python test_get.py---------
my_accelerator.name()='cuda'
my_accelerator.communication_backend='nccl'
my_accelerator.HalfTensor().device=device(type='cuda', index=0)
my_accelerator.total_memory()=34089730048
---[output] python test_get.py---------
**************************************************************************
-----------[code] test_set.py -----------
from deepspeed.accelerator.cuda_accelerator import CUDA_Accelerator
cu_accel = CUDA_Accelerator()
logger.info(f'{id(cu_accel)=}')
from deepspeed.accelerator import set_accelerator, get_accelerator
set_accelerator(cu_accel)
my_accelerator = get_accelerator()
logger.info(f'{id(my_accelerator)=}')
logger.info(f'{my_accelerator._name=}')
logger.info(f'{my_accelerator._communication_backend=}')
logger.info(f'{my_accelerator.HalfTensor().device=}')
logger.info(f'{my_accelerator.total_memory()=}')
-----------[code] test_set.py -----------
---[output] python test_set.py---------
id(cu_accel)=139648165478304
my_accelerator=<deepspeed.accelerator.cuda_accelerator.CUDA_Accelerator object at 0x7f025f4bffa0>
my_accelerator.name='cuda'
my_accelerator.communication_backend='nccl'
my_accelerator.HalfTensor().device=device(type='cuda', index=0)
my_accelerator.total_memory()=34089730048
---[output] python test_set.py---------
"""
+323
View File
@@ -0,0 +1,323 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# BSD 3- Clause License Copyright (c) 2023, Tecorigin Co., Ltd. All rights
# reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
# OF SUCH DAMAGE.
# DeepSpeed Team
import importlib
import inspect
import functools
from .abstract_accelerator import DeepSpeedAccelerator
# During setup stage torch may not be installed, pass on no torch will
# allow op builder related API to be executed.
try:
import torch.sdaa
except ImportError:
pass
class SDAA_Accelerator(DeepSpeedAccelerator):
def __init__(self):
self._name = 'sdaa'
self._communication_backend_name = 'tccl'
self._compile_backend = "inductor"
self.class_dict = None
def is_synchronized_device(self):
return False
def use_host_timers(self):
return self.is_synchronized_device()
def resolves_data_dependency(self):
return self.is_synchronized_device()
def handles_memory_backpressure(self):
return self.is_synchronized_device()
# Device APIs
def device_name(self, device_index=None):
if device_index is None:
return 'sdaa'
return 'sdaa:{}'.format(device_index)
def device(self, device_index=None):
return torch.sdaa.device(device_index)
def set_device(self, device_index):
torch.sdaa.set_device(device_index)
def current_device(self):
return torch.sdaa.current_device()
def current_device_name(self):
return 'sdaa:{}'.format(torch.sdaa.current_device())
def device_count(self):
return torch.sdaa.device_count()
def synchronize(self, device_index=None):
return torch.sdaa.synchronize(device_index)
# RNG APIs
def random(self):
return torch.random
def set_rng_state(self, new_state, device_index=None):
if device_index is None:
return torch.sdaa.set_rng_state(new_state)
return torch.sdaa.set_rng_state(new_state, device_index)
def get_rng_state(self, device_index=None):
if device_index is None:
return torch.sdaa.get_rng_state()
return torch.sdaa.get_rng_state(device_index)
def manual_seed(self, seed):
return torch.sdaa.manual_seed(seed)
def manual_seed_all(self, seed):
return torch.sdaa.manual_seed_all(seed)
def initial_seed(self):
return torch.sdaa.initial_seed()
def default_generator(self, device_index):
return torch.sdaa.default_generators[device_index]
# Streams/Events
@property
def Stream(self):
return torch.sdaa.Stream
def stream(self, stream):
return torch.sdaa.stream(stream)
def current_stream(self, device_index=None):
return torch.sdaa.current_stream(device_index)
def default_stream(self, device_index=None):
return torch.sdaa.default_stream(device_index)
@property
def Event(self):
return torch.sdaa.Event
# Memory management
def empty_cache(self):
return torch.sdaa.empty_cache()
def memory_allocated(self, device_index=None):
return torch.sdaa.memory_allocated(device_index)
def max_memory_allocated(self, device_index=None):
return torch.sdaa.max_memory_allocated(device_index)
def reset_max_memory_allocated(self, device_index=None):
return torch.sdaa.reset_max_memory_allocated(device_index)
def memory_cached(self, device_index=None):
return torch.sdaa.memory_cached(device_index)
def max_memory_cached(self, device_index=None):
return torch.sdaa.max_memory_cached(device_index)
def reset_max_memory_cached(self, device_index=None):
return torch.sdaa.reset_max_memory_cached(device_index)
def memory_stats(self, device_index=None):
if hasattr(torch.sdaa, 'memory_stats'):
return torch.sdaa.memory_stats(device_index)
def reset_peak_memory_stats(self, device_index=None):
if hasattr(torch.sdaa, 'reset_peak_memory_stats'):
return torch.sdaa.reset_peak_memory_stats(device_index)
def memory_reserved(self, device_index=None):
if hasattr(torch.sdaa, 'memory_reserved'):
return torch.sdaa.memory_reserved(device_index)
def max_memory_reserved(self, device_index=None):
if hasattr(torch.sdaa, 'max_memory_reserved'):
return torch.sdaa.max_memory_reserved(device_index)
def total_memory(self, device_index=None):
return torch.sdaa.get_device_properties(device_index).total_memory
def available_memory(self, device_index=None):
return self.total_memory(device_index) - self.memory_allocated(device_index)
# Data types
def is_bf16_supported(self):
return torch.sdaa.is_bf16_supported()
def is_fp16_supported(self):
return True
def supported_dtypes(self):
supported_dtypes = [torch.float]
if self.is_fp16_supported():
supported_dtypes.append(torch.half)
if self.is_bf16_supported():
supported_dtypes.append(torch.bfloat16)
return supported_dtypes
# Misc
def is_available(self):
return torch.sdaa.is_available()
def range_push(self, msg, domain=None, category=None):
return
def range_pop(self, domain=None):
return
def lazy_call(self, callback):
return torch.sdaa._lazy_call(callback)
def communication_backend_name(self):
return self._communication_backend_name
def is_triton_supported(self):
return False
# Graph operations
def create_graph(self):
return None
def capture_to_graph(self, graph, pool=None, stream=None):
from deepspeed.runtime.utils import noop_context
return noop_context()
def replay_graph(self, graph):
return
# Tensor operations
@property
def BFloat16Tensor(self):
return functools.partial(torch.tensor, dtype=torch.bfloat16, device='sdaa')
@property
def ByteTensor(self):
return functools.partial(torch.tensor, dtype=torch.uint8, device='sdaa')
@property
def DoubleTensor(self):
return functools.partial(torch.tensor, dtype=torch.double, device='sdaa')
@property
def FloatTensor(self):
return functools.partial(torch.tensor, dtype=torch.float, device='sdaa')
@property
def HalfTensor(self):
return functools.partial(torch.tensor, dtype=torch.half, device='sdaa')
@property
def IntTensor(self):
return functools.partial(torch.tensor, dtype=torch.int, device='sdaa')
@property
def LongTensor(self):
return functools.partial(torch.tensor, dtype=torch.long, device='sdaa')
def pin_memory(self, tensor, align_bytes=1):
return tensor.pin_memory()
def is_pinned(self, tensor):
return tensor.is_pinned()
def on_accelerator(self, tensor):
device_str = str(tensor.device)
if device_str.startswith('sdaa:'):
return True
else:
return False
def op_builder_dir(self):
try:
# is op_builder from deepspeed or a 3p version? this should only succeed if it's deepspeed
# if successful this also means we're doing a local install and not JIT compile path
from op_builder import __deepspeed__ # noqa: F401 # type: ignore
return "op_builder.sdaa"
except ImportError:
return "deepspeed.ops.op_builder.sdaa"
def _lazy_init_class_dict(self):
if self.class_dict:
return
op_builder_module = importlib.import_module(self.op_builder_dir())
# get op builder class from op_builder/sdaa/__init__.py
self.class_dict = {}
for class_name, class_obj in inspect.getmembers(op_builder_module, inspect.isclass):
self.class_dict[class_name] = class_obj
# create an instance of op builder and return, name specified by class_name
def create_op_builder(self, class_name):
builder_class = self.get_op_builder(class_name)
return builder_class()
# return an op builder class, name specified by class_name
def get_op_builder(self, class_name):
self._lazy_init_class_dict()
if class_name in self.class_dict:
return self.class_dict[class_name]
else:
return self.class_dict['NotImplementedBuilder']
def build_extension(self):
from torch.utils.cpp_extension import BuildExtension
return BuildExtension
def export_envs(self):
return ['NCCL', 'LD_LIBRARY', 'PATH']
def visible_devices_envs(self):
return ['SDAA_VISIBLE_DEVICES']
def set_visible_devices_envs(self, current_env, local_accelerator_ids):
for env in self.visible_devices_envs():
current_env[env] = ",".join(map(str, local_accelerator_ids))
def get_compile_backend(self):
return self._compile_backend
def set_compile_backend(self, backend):
supported_backends = torch._dynamo.list_backends(exclude_tags=())
if backend in supported_backends:
self._compile_backend = backend
else:
raise ValueError(
f"{backend} not supported by {self.device_name()}. Supported Backends are {supported_backends}")
+293
View File
@@ -0,0 +1,293 @@
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
import os
import sys
import pkgutil
import importlib
import torch
from .abstract_accelerator import DeepSpeedAccelerator
class SUPA_Accelerator(DeepSpeedAccelerator):
def __init__(self):
self._name = 'supa'
# Use BCCL on Linux, fall back to gloo on Windows (no BCCL support yet)
self._communication_backend_name = 'bccl' if sys.platform != 'win32' else 'gloo'
self._compile_backend = "inductor"
def is_synchronized_device(self):
return False
def use_host_timers(self):
return self.is_synchronized_device()
def resolves_data_dependency(self):
return self.is_synchronized_device()
def handles_memory_backpressure(self):
return self.is_synchronized_device()
# Device APIs
def device_name(self, device_index=None):
if device_index is None:
return 'supa'
return 'supa:{}'.format(device_index)
def communication_backend_version(self):
# BCCL does not expose a version via torch.supa
return (0, 0, 0)
def device(self, device_index=None):
return torch.device('supa', device_index)
def set_device(self, device_index):
torch.supa.set_device(device_index)
def current_device(self):
return torch.supa.current_device()
def current_device_name(self):
return 'supa:{}'.format(torch.supa.current_device())
def device_count(self):
return torch.supa.device_count()
def synchronize(self, device_index=None):
return torch.supa.synchronize(device_index)
# RNG APIs
def random(self):
return torch.random
def set_rng_state(self, new_state, device_index=None):
if device_index is None:
return torch.supa.set_rng_state(new_state)
return torch.supa.set_rng_state(new_state, device_index)
def get_rng_state(self, device_index=None):
if device_index is None:
return torch.supa.get_rng_state()
return torch.supa.get_rng_state(device_index)
def manual_seed(self, seed):
return torch.supa.manual_seed(seed)
def manual_seed_all(self, seed):
return torch.supa.manual_seed_all(seed)
def initial_seed(self):
return torch.supa.initial_seed()
def default_generator(self, device_index):
return torch.supa.default_generators[device_index]
# Streams/Events
@property
def Stream(self):
return torch.supa.Stream
def stream(self, stream):
return torch.supa.stream(stream)
def current_stream(self, device_index=None):
return torch.supa.current_stream(device_index)
def default_stream(self, device_index=None):
return torch.supa.default_stream(device_index)
@property
def Event(self):
return torch.supa.Event
# Memory management
def empty_cache(self):
return torch.supa.empty_cache()
def memory_allocated(self, device_index=None):
return torch.supa.memory_allocated(device_index)
def max_memory_allocated(self, device_index=None):
return torch.supa.max_memory_allocated(device_index)
def reset_max_memory_allocated(self, device_index=None):
return torch.supa.reset_max_memory_allocated(device_index)
def memory_cached(self, device_index=None):
return torch.supa.memory_cached(device_index)
def max_memory_cached(self, device_index=None):
return torch.supa.max_memory_cached(device_index)
def reset_max_memory_cached(self, device_index=None):
return torch.supa.reset_max_memory_cached(device_index)
def memory_stats(self, device_index=None):
if hasattr(torch.supa, 'memory_stats'):
return torch.supa.memory_stats(device_index)
def reset_peak_memory_stats(self, device_index=None):
if hasattr(torch.supa, 'reset_peak_memory_stats'):
return torch.supa.reset_peak_memory_stats(device_index)
def memory_reserved(self, device_index=None):
if hasattr(torch.supa, 'memory_reserved'):
return torch.supa.memory_reserved(device_index)
def max_memory_reserved(self, device_index=None):
if hasattr(torch.supa, 'max_memory_reserved'):
return torch.supa.max_memory_reserved(device_index)
def total_memory(self, device_index=None):
return torch.supa.get_device_properties(device_index).total_memory
def available_memory(self, device_index=None):
return self.total_memory(device_index) - self.memory_allocated(device_index)
# Data types
def is_bf16_supported(self):
return True
def is_fp16_supported(self):
return True
def supported_dtypes(self):
return [torch.float, torch.half, torch.bfloat16]
# Misc
def is_available(self):
return torch.supa.is_available()
def range_push(self, msg, domain=None, category=None):
return None
def range_pop(self, domain=None):
return None
def lazy_call(self, callback):
return torch.supa._lazy_call(callback)
def communication_backend_name(self):
return self._communication_backend_name
def is_triton_supported(self):
return True
# Graph operations
def create_graph(self):
return torch.supa.SUPAGraph()
def capture_to_graph(self, graph, pool=None, stream=None):
return torch.supa.graph(graph, pool, stream)
def replay_graph(self, graph):
graph.replay()
# Tensor operations
@property
def BFloat16Tensor(self):
return torch.supa.BFloat16Tensor
@property
def ByteTensor(self):
return torch.supa.ByteTensor
@property
def DoubleTensor(self):
return torch.supa.DoubleTensor
@property
def FloatTensor(self):
return torch.supa.FloatTensor
@property
def HalfTensor(self):
return torch.supa.HalfTensor
@property
def IntTensor(self):
return torch.supa.IntTensor
@property
def LongTensor(self):
return torch.supa.LongTensor
def pin_memory(self, tensor, align_bytes=1):
return tensor.pin_memory()
def is_pinned(self, tensor):
return tensor.is_pinned()
def on_accelerator(self, tensor):
device_str = str(tensor.device)
return device_str.startswith('supa:')
def op_builder_dir(self):
try:
# Local install: op_builder is a top-level package
from op_builder import __deepspeed__ # noqa: F401 # type: ignore
return "op_builder.supa"
except ImportError:
return "deepspeed.ops.op_builder.supa"
# dict that holds class name <--> class type mapping i.e.
# 'FusedAdamBuilder': <class 'op_builder.supa.fused_adam.FusedAdamBuilder'>
# populated lazily on first call to create_op_builder / get_op_builder
class_dict = None
def _lazy_init_class_dict(self):
if self.class_dict is not None:
return
self.class_dict = {}
op_builder_dir = self.op_builder_dir()
op_builder_module = importlib.import_module(op_builder_dir)
op_builder_absolute_path = os.path.dirname(op_builder_module.__file__)
for _, module_name, _ in pkgutil.iter_modules([op_builder_absolute_path]):
if module_name in ('all_ops', 'builder') or os.path.isdir(
os.path.join(op_builder_absolute_path, module_name)):
continue
module = importlib.import_module("{}.{}".format(op_builder_dir, module_name))
for member_name in module.__dir__():
if (member_name.endswith('Builder')
and member_name not in ('OpBuilder', 'CUDAOpBuilder', 'TorchCPUOpBuilder', 'SUPAOpBuilder')):
if member_name not in self.class_dict:
self.class_dict[member_name] = getattr(module, member_name)
def create_op_builder(self, class_name):
self._lazy_init_class_dict()
if class_name in self.class_dict:
return self.class_dict[class_name]()
return None
def get_op_builder(self, class_name):
self._lazy_init_class_dict()
if class_name in self.class_dict:
return self.class_dict[class_name]
return None
def build_extension(self):
from torch.utils.cpp_extension import BuildExtension
return BuildExtension
def export_envs(self):
return ['BCCL', 'BIREN', 'SUPA', 'LD_LIBRARY', 'PATH']
def visible_devices_envs(self):
return ['SUPA_VISIBLE_DEVICES']
def set_visible_devices_envs(self, current_env, local_accelerator_ids):
for env in self.visible_devices_envs():
current_env[env] = ",".join(map(str, local_accelerator_ids))
def get_compile_backend(self):
return self._compile_backend
def set_compile_backend(self, backend):
supported_backends = torch._dynamo.list_backends(exclude_tags=())
if backend in supported_backends:
self._compile_backend = backend
else:
raise ValueError(f"{backend} not supported by {self.device_name()}. "
f"Supported backends: {supported_backends}")
+315
View File
@@ -0,0 +1,315 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
import torch
from deepspeed.accelerator.abstract_accelerator import DeepSpeedAccelerator
import functools
import importlib
import inspect
try:
import oneccl_bindings_for_pytorch # noqa: F401 # type: ignore
oneccl_imported_p = True
except ImportError as e:
oneccl_imported_p = False
class XPU_Accelerator(DeepSpeedAccelerator):
def __init__(self):
self._name = 'xpu'
if oneccl_imported_p:
self._communication_backend_name = 'ccl'
else:
# changed to xccl if not using torch-CCL on XPU device
self._communication_backend_name = 'xccl'
self._compile_backend = "inductor"
self.aligned_tensors = []
self.class_dict = None
def is_synchronized_device(self):
return False
def use_host_timers(self):
return self.is_synchronized_device()
def resolves_data_dependency(self):
return self.is_synchronized_device()
def handles_memory_backpressure(self):
return self.is_synchronized_device()
# Device APIs
def device_name(self, device_index=None):
if device_index == None:
return 'xpu'
return 'xpu:{}'.format(device_index)
def device(self, device_index=None):
return torch.device('xpu', device_index)
def set_device(self, device_index):
torch.xpu.set_device(device_index)
def current_device(self):
return torch.xpu.current_device()
def current_device_name(self):
return 'xpu:{}'.format(torch.xpu.current_device())
def device_count(self):
return torch.xpu.device_count()
def synchronize(self, device_index=None):
return torch.xpu.synchronize(device_index)
# RNG APIs
def random(self):
return torch.xpu.random
def set_rng_state(self, new_state, device_index=None):
if device_index == None:
return torch.xpu.set_rng_state(new_state)
return torch.xpu.set_rng_state(new_state, device_index)
def get_rng_state(self, device_index=None):
if device_index == None:
return torch.xpu.get_rng_state()
return torch.xpu.get_rng_state(device_index)
def manual_seed(self, seed):
return torch.xpu.manual_seed(seed)
def manual_seed_all(self, seed):
return torch.xpu.manual_seed_all(seed)
def initial_seed(self):
return torch.xpu.initial_seed()
def default_generator(self, device_index):
return torch.xpu.default_generators[device_index]
# Streams/Events
@property
def Stream(self):
return torch.xpu.Stream
def stream(self, stream):
return torch.xpu.stream(stream)
def current_stream(self, device_index=None):
return torch.xpu.current_stream(device_index)
def default_stream(self, device_index=None):
# torch.xpu does not support the sync behavior of default stream as cuda
# use current_stream as workaround
# see https://pytorch.org/docs/stable/notes/cuda.html#cuda-streams
return torch.xpu.current_stream(device_index)
@property
def Event(self):
return torch.xpu.Event
# Memory management
def empty_cache(self):
return torch.xpu.empty_cache()
def memory_allocated(self, device_index=None):
return torch.xpu.memory_allocated(device_index)
def max_memory_allocated(self, device_index=None):
return torch.xpu.max_memory_allocated(device_index)
def reset_max_memory_allocated(self, device_index=None):
return torch.xpu.reset_max_memory_allocated(device_index)
def memory_cached(self, device_index=None):
return torch.xpu.memory_reserved(device_index)
def max_memory_cached(self, device_index=None):
return torch.xpu.max_memory_reserved(device_index)
def reset_max_memory_cached(self, device_index=None):
return torch.xpu.reset_max_memory_reserved(device_index)
def memory_stats(self, device_index=None):
return torch.xpu.memory_stats(device_index)
def reset_peak_memory_stats(self, device_index=None):
return torch.xpu.reset_peak_memory_stats(device_index)
def memory_reserved(self, device_index=None):
return torch.xpu.memory_reserved(device_index)
def max_memory_reserved(self, device_index=None):
return torch.xpu.max_memory_reserved(device_index)
def total_memory(self, device_index=None):
return torch.xpu.get_device_properties(device_index).total_memory
def available_memory(self, device_index=None):
return self.total_memory(device_index) - self.memory_allocated(device_index)
# Misc
def is_available(self):
return torch.xpu.is_available()
def range_push(self, msg, domain=None, category=None):
# TODO itt is currently not supported yet
# return torch.profiler.itt.range_push(msg)
return
def range_pop(self, domain=None):
# TODO itt is currently not supported yet
# return torch.profiler.itt.range_pop()
return
def lazy_call(self, callback):
if hasattr(torch.xpu, "_lazy_call"):
return torch.xpu._lazy_call(callback)
else:
return torch.xpu.lazy_init._lazy_call(callback)
def communication_backend_name(self):
return self._communication_backend_name
def is_triton_supported(self):
return False
# Graph operations
def create_graph(self):
return None
def capture_to_graph(self, graph, pool=None, stream=None):
from deepspeed.runtime.utils import noop_context
return noop_context()
def replay_graph(self, graph):
return
# Data types
def is_bf16_supported(self):
return True
def is_fp16_supported(self):
return True
def supported_dtypes(self):
return [torch.float, torch.half, torch.bfloat16]
# Tensor operations
@property
def BFloat16Tensor(self):
return functools.partial(torch.tensor, dtype=torch.bfloat16, device=self._name)
@property
def ByteTensor(self):
return functools.partial(torch.tensor, dtype=torch.uint8, device=self._name)
@property
def DoubleTensor(self):
return functools.partial(torch.tensor, dtype=torch.double, device=self._name)
@property
def FloatTensor(self):
return functools.partial(torch.tensor, dtype=torch.float, device=self._name)
@property
def HalfTensor(self):
return functools.partial(torch.tensor, dtype=torch.half, device=self._name)
@property
def IntTensor(self):
return functools.partial(torch.tensor, dtype=torch.int, device=self._name)
@property
def LongTensor(self):
return functools.partial(torch.tensor, dtype=torch.long, device=self._name)
def pin_memory(self, tensor, align_bytes=1):
if align_bytes == 1:
return tensor.pin_memory(device=self.current_device_name())
elif align_bytes == 0:
from deepspeed.ops.op_builder.xpu import AsyncIOBuilder
self.aio_handle = AsyncIOBuilder().load().aio_handle(128 * 1024, 8, False, False, False)
aligned_t = self.aio_handle.new_cpu_locked_tensor(tensor.numel(), tensor)
aligned_t = aligned_t[:tensor.numel()].copy_(tensor)
self.aligned_tensors.append([aligned_t.data_ptr(), aligned_t[-1].data_ptr()])
return aligned_t
def is_pinned(self, tensor):
if tensor.is_pinned(device=self.current_device_name()):
return True
else:
for begin, end in self.aligned_tensors:
if begin <= tensor.data_ptr() and tensor.data_ptr() <= end:
return True
return False
def op_builder_dir(self):
try:
# is op_builder from deepspeed or a 3p version? this should only succeed if it's deepspeed
# if successful this also means we're doing a local install and not JIT compile path
from op_builder import __deepspeed__ # noqa: F401 # type: ignore
return "op_builder.xpu"
except ImportError:
return "deepspeed.ops.op_builder.xpu"
def on_accelerator(self, tensor):
device_str = str(tensor.device)
if device_str.startswith('xpu:'):
return True
else:
return False
def _lazy_init_class_dict(self):
if self.class_dict:
return
op_builder_module = importlib.import_module(self.op_builder_dir())
# get op builder class from op_builder/xpu/__init__.py
self.class_dict = {}
for class_name, class_obj in inspect.getmembers(op_builder_module, inspect.isclass):
self.class_dict[class_name] = class_obj
# create an instance of op builder and return, name specified by class_name
def create_op_builder(self, class_name):
builder_class = self.get_op_builder(class_name)
return builder_class()
# return an op builder class, name specified by class_name
def get_op_builder(self, class_name):
self._lazy_init_class_dict()
if class_name in self.class_dict:
return self.class_dict[class_name]
else:
return self.class_dict['NotImplementedBuilder']
def build_extension(self):
from torch.utils.cpp_extension import BuildExtension
return BuildExtension
def export_envs(self):
return []
def visible_devices_envs(self):
return ['ZE_AFFINITY_MASK']
def set_visible_devices_envs(self, current_env, local_accelerator_ids):
for env in self.visible_devices_envs():
current_env[env] = ",".join(map(str, local_accelerator_ids))
def get_compile_backend(self):
return self._compile_backend
def set_compile_backend(self, backend):
supported_backends = torch._dynamo.list_backends(exclude_tags=())
if backend in supported_backends:
self._compile_backend = backend
else:
raise ValueError(
f"{backend} not supported by {self.device_name()}. Supported Backends are {supported_backends}")
+3
View File
@@ -0,0 +1,3 @@
# Getting Started with DeepSpeed on Azure
The recommended and simplest method to try DeepSpeed on Azure is through [AzureML](https://azure.microsoft.com/en-us/services/machine-learning/). For more details, please see our [Azure tutorial](https://www.deepspeed.ai/tutorials/azure/).
+6
View File
@@ -0,0 +1,6 @@
# DeepSpeed Benchmarks
If you are looking for DeepSpeed benchmarks, please see the following resources:
1. [Communication Benchmarking Suite](https://github.com/deepspeedai/DeepSpeedExamples/tree/master/benchmarks/communication)
2. [Inference Benchmarks](https://github.com/deepspeedai/DeepSpeedExamples/tree/master/benchmarks/inference)
+275
View File
@@ -0,0 +1,275 @@
# SPDX-License-Identifier: Apache-2.0
# DeepSpeed Team
"""
Benchmark: AutoSP multimodal sequence parallelism (ViT SP + fusion adapter).
Measures per-iteration latency, throughput, and peak GPU memory for the
ViT-SP + fusion-adapter pipeline at a given SP degree.
Launch (from repo root):
# SP degree 2 — two GPUs:
NCCL_P2P_DISABLE=1 torchrun --nproc_per_node=2 \\
benchmarks/autosp/bench_multimodal_sp.py [args]
# Baseline — single GPU (all-gather/scatter are no-ops):
torchrun --nproc_per_node=1 \\
benchmarks/autosp/bench_multimodal_sp.py [args]
Compare the two output tables to quantify memory savings and throughput scaling.
Arguments:
--arch {internvl, qwen2vl} architecture to simulate (default: internvl)
--batch-size N samples per batch (default: 2)
--seq-len N text sequence length (default: 512)
--visual-tokens N total visual tokens per sample (default: 256)
--hidden N hidden dimension (default: 1024)
--num-layers N ViT and LLM layers each (default: 2)
--iters N measured iterations (default: 50)
--warmup N warmup iterations (default: 10)
"""
import argparse
import logging
import statistics
import torch
import torch.nn as nn
import deepspeed
import deepspeed.comm as dist
from deepspeed.accelerator import get_accelerator
from deepspeed.sequence.auto_sp import auto_wrap_model_for_sp
from deepspeed.sequence.autosp_fusion import InternVLFusionAdapter, Qwen2VLFusionAdapter
# ---------------------------------------------------------------------------
# Token IDs
# ---------------------------------------------------------------------------
_INTERNVL_CONTEXT_ID = 92546
_QWEN2VL_START_ID = 151652
_QWEN2VL_END_ID = 151653
# ---------------------------------------------------------------------------
# Mock attention classes — names match autosp_detector registries exactly
# ---------------------------------------------------------------------------
class InternVisionAttention(nn.Module):
def forward(self, hidden_states, **kwargs):
return hidden_states
class InternLM2Attention(nn.Module):
def forward(self, hidden_states, **kwargs):
return hidden_states
class Qwen2VLVisionAttention(nn.Module):
def forward(self, hidden_states, **kwargs):
return hidden_states
class Qwen2Attention(nn.Module):
def forward(self, hidden_states, **kwargs):
return hidden_states
# ---------------------------------------------------------------------------
# Model building blocks
# ---------------------------------------------------------------------------
class _ViTBlock(nn.Module):
"""One ViT transformer block: attention (to be SP-wrapped) + linear FFN."""
def __init__(self, attn_cls, hidden: int) -> None:
super().__init__()
self.attn = attn_cls()
self.ffn = nn.Linear(hidden, hidden, bias=False)
def forward(self, x, **kwargs):
out = self.attn(x, **kwargs)
if isinstance(out, (tuple, list)):
out = out[0]
return self.ffn(out)
class _MinimalInternVLModel(nn.Module):
"""InternVL-like benchmark model.
Module paths detected by autosp_detector:
- ``vision_encoder.*.attn`` -> InternVisionAttention (_VIT_ATTN_CLASSNAMES)
- ``mm_projector`` -> keyword in _VISION_PROJ_KEYWORDS
``language_model`` uses plain nn.Linear layers so it is NOT wrapped by
DistributedAttention (avoids the Q/K/V interface requirement) yet still
contributes realistic compute on the scattered fused sequence.
"""
def __init__(self, hidden: int, num_layers: int) -> None:
super().__init__()
self.vision_encoder = nn.Sequential(*[_ViTBlock(InternVisionAttention, hidden) for _ in range(num_layers)])
self.mm_projector = nn.Identity()
self.language_model = nn.Sequential(*[nn.Linear(hidden, hidden, bias=False) for _ in range(num_layers)])
self.fusion = None
def forward(self, local_patches: torch.Tensor, text_embeds: torch.Tensor, input_ids: torch.Tensor) -> torch.Tensor:
local_visual = self.vision_encoder(local_patches)
local_fused = self.fusion(local_visual, text_embeds, input_ids)
return self.language_model(local_fused)
class _MinimalQwen2VLModel(nn.Module):
"""Qwen2VL-like benchmark model."""
def __init__(self, hidden: int, num_layers: int) -> None:
super().__init__()
self.visual = nn.Sequential(*[_ViTBlock(Qwen2VLVisionAttention, hidden) for _ in range(num_layers)])
self.multi_modal_projector = nn.Identity()
self.model = nn.Sequential(*[nn.Linear(hidden, hidden, bias=False) for _ in range(num_layers)])
self.fusion = None
def forward(self, local_patches: torch.Tensor, text_embeds: torch.Tensor, input_ids: torch.Tensor) -> torch.Tensor:
local_visual = self.visual(local_patches)
local_fused = self.fusion(local_visual, text_embeds, input_ids)
return self.model(local_fused)
# ---------------------------------------------------------------------------
# Setup helpers
# ---------------------------------------------------------------------------
def _build_model_and_inputs(arch: str, args, sp_group, device):
rank = dist.get_rank(sp_group)
world_size = dist.get_world_size(sp_group)
local_v = args.visual_tokens // world_size
bs, text_len, hidden = args.batch_size, args.seq_len, args.hidden
torch.manual_seed(0)
local_patches = torch.randn(bs, local_v, hidden, device=device)
text_embeds = torch.randn(bs, text_len, hidden, device=device)
input_ids = torch.zeros(bs, text_len, dtype=torch.long, device=device)
if arch == "internvl":
num_ctx = min(local_v * world_size, text_len - 2)
input_ids[:, 2:2 + num_ctx] = _INTERNVL_CONTEXT_ID
model = _MinimalInternVLModel(hidden, args.num_layers).to(device)
# Suppress the Phase 2 projection-layer warning: we wrap manually below.
_auto_sp_logger = logging.getLogger("deepspeed.sequence.auto_sp")
_prev_level = _auto_sp_logger.level
_auto_sp_logger.setLevel(logging.ERROR)
auto_wrap_model_for_sp(model, sp_group)
_auto_sp_logger.setLevel(_prev_level)
model.fusion = InternVLFusionAdapter(model.mm_projector, sp_group,
image_token_id=_INTERNVL_CONTEXT_ID).to(device)
else: # qwen2vl
num_inner = min(local_v * world_size, text_len - 3)
input_ids[:, 1] = _QWEN2VL_START_ID
input_ids[:, 2 + num_inner] = _QWEN2VL_END_ID
model = _MinimalQwen2VLModel(hidden, args.num_layers).to(device)
_auto_sp_logger = logging.getLogger("deepspeed.sequence.auto_sp")
_prev_level = _auto_sp_logger.level
_auto_sp_logger.setLevel(logging.ERROR)
auto_wrap_model_for_sp(model, sp_group)
_auto_sp_logger.setLevel(_prev_level)
model.fusion = Qwen2VLFusionAdapter(model.multi_modal_projector,
sp_group,
vision_start_token_id=_QWEN2VL_START_ID,
vision_end_token_id=_QWEN2VL_END_ID).to(device)
return model, local_patches, text_embeds, input_ids
# ---------------------------------------------------------------------------
# Benchmark runner
# ---------------------------------------------------------------------------
def _run(arch: str, args) -> None:
deepspeed.init_distributed(dist_backend="nccl")
rank = dist.get_rank()
world_size = dist.get_world_size()
device = torch.device(get_accelerator().device_name(), rank % get_accelerator().device_count())
get_accelerator().set_device(rank % get_accelerator().device_count())
sp_group = dist.new_group(ranks=list(range(world_size)))
model, local_patches, text_embeds, input_ids = _build_model_and_inputs(arch, args, sp_group, device)
model.eval()
# Warmup
with torch.no_grad():
for _ in range(args.warmup):
model(local_patches, text_embeds, input_ids)
get_accelerator().synchronize()
get_accelerator().reset_peak_memory_stats()
# Timed iterations using CUDA events for accurate GPU-side measurement.
latencies_ms = []
with torch.no_grad():
for _ in range(args.iters):
t_start = get_accelerator().Event(enable_timing=True)
t_end = get_accelerator().Event(enable_timing=True)
t_start.record()
model(local_patches, text_embeds, input_ids)
t_end.record()
get_accelerator().synchronize()
latencies_ms.append(t_start.elapsed_time(t_end))
peak_mem_mb = get_accelerator().max_memory_allocated() / 1024**2
mean_ms = statistics.mean(latencies_ms)
std_ms = statistics.stdev(latencies_ms) if len(latencies_ms) > 1 else 0.0
# tokens/s: fused sequence length approximated by seq_len (length-preserving adapters).
throughput = (args.batch_size * args.seq_len) / (mean_ms / 1000.0)
if rank == 0:
sep = "=" * 62
print(f"\n{sep}")
print(f" AutoSP Benchmark arch={arch} sp_degree={world_size}")
print(sep)
print(f" batch_size : {args.batch_size}")
print(f" seq_len : {args.seq_len}")
print(f" visual_tokens : {args.visual_tokens} (local={args.visual_tokens // world_size}/rank)")
print(f" hidden : {args.hidden}")
print(f" num_layers : {args.num_layers}")
print(f" warmup / iters : {args.warmup} / {args.iters}")
print(f" {'' * 58}")
print(f" Latency : {mean_ms:.2f} ± {std_ms:.2f} ms/iter")
print(f" Throughput : {throughput:,.0f} tokens/s")
print(f" Peak GPU memory : {peak_mem_mb:.1f} MB")
print(f"{sep}\n")
dist.destroy_process_group()
def main() -> None:
parser = argparse.ArgumentParser(description="AutoSP multimodal SP benchmark")
parser.add_argument("--arch",
choices=["internvl", "qwen2vl"],
default="internvl",
help="Model architecture to simulate")
parser.add_argument("--batch-size", type=int, default=2)
parser.add_argument("--seq-len", type=int, default=512)
parser.add_argument("--visual-tokens",
type=int,
default=256,
help="Total visual tokens (must be divisible by --nproc_per_node)")
parser.add_argument("--hidden", type=int, default=1024)
parser.add_argument("--num-layers", type=int, default=2, help="Number of ViT blocks and LLM linear layers each")
parser.add_argument("--iters", type=int, default=50)
parser.add_argument("--warmup", type=int, default=10)
args = parser.parse_args()
_run(args.arch, args)
if __name__ == "__main__":
main()
+1
View File
@@ -0,0 +1 @@
ds
+2
View File
@@ -0,0 +1,2 @@
@echo off
python "%~dp0\ds" %*
+1
View File
@@ -0,0 +1 @@
ds
Executable
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env python3
from deepspeed.launcher.runner import main
if __name__ == '__main__':
main()
Executable
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env python3
from benchmarks.communication.run_all import main
from benchmarks.communication.constants import *
from benchmarks.communication.utils import *
import os
import sys
# Run the same file with deepspeed launcher. This is required since setuptools will auto-detect python files and insert a python shebang for both 'scripts' and 'entry_points', and this benchmarks require the DS launcher
required_env = ["RANK", "WORLD_SIZE", "MASTER_ADDR", "MASTER_PORT", "LOCAL_RANK"]
if not all(map(lambda v: v in os.environ, required_env)):
import subprocess
r = subprocess.check_output(["which", "ds_bench"])
ds_bench_bin = r.decode('utf-8').strip()
safe_cmd = ["deepspeed", ds_bench_bin] + sys.argv[1:]
subprocess.run(safe_cmd)
else:
args = benchmark_parser().parse_args()
rank = args.local_rank
main(args, rank)
Executable
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env python3
import argparse
import json
import deepspeed
from deepspeed.elasticity import compute_elastic_config
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--config', type=str, help="DeepSpeed config json")
parser.add_argument('-w', '--world-size', type=int, default=0, help="Intended/current world size")
args = parser.parse_args()
ds_config = json.load(open(args.config, 'r'))
ds_version = deepspeed.__version__
elastic_config = ds_config['elasticity']
print('------------------------------------------')
print("Elasticity config:")
print('------------------------------------------')
print(json.dumps(elastic_config, indent=4, sort_keys=True))
if args.world_size > 0:
final_batch_size, valid_gpus, micro_batch_size = compute_elastic_config(ds_config=ds_config,
target_deepspeed_version=ds_version,
world_size=args.world_size)
print('------------------------------------------')
print(f"Calculated results for world size {args.world_size}:")
print('------------------------------------------')
print(f'final_batch_size .... {final_batch_size}')
print(f'valid_gpus .......... {valid_gpus}')
print(f'micro_batch_size .... {micro_batch_size}')
else:
final_batch_size, valid_gpus = compute_elastic_config(ds_config=ds_config, target_deepspeed_version=ds_version)
print('------------------------------------------')
print("Calculated results:")
print('------------------------------------------')
print(f'final_batch_size .... {final_batch_size}')
print(f'valid_gpus .......... {valid_gpus}')
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env python3
from deepspeed.nvme import ds_io_main
if __name__ == '__main__':
ds_io_main()
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env python3
from deepspeed.nvme import sweep_main, generate_main, parse_sweep_arguments
if __name__ == '__main__':
args = parse_sweep_arguments()
print(f"Running DeepNVMe performance tuning on {args.nvme_dir}")
sweep_main(args)
generate_main(args.log_dir)
Executable
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env python3
from deepspeed.env_report import cli_main
if __name__ == '__main__':
cli_main()
+2
View File
@@ -0,0 +1,2 @@
@echo off
python "%~dp0\ds_report" %*
Executable
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
# Copyright 2020 The Microsoft DeepSpeed Team
command -v pdsh
if [ $? != 0 ]; then
echo "Cannot find pdsh, please install via 'apt-get install -y pdsh'"
exit 1
fi
hostfile=/job/hostfile
while getopts "h?f:" opt; do
case "$opt" in
h|\?)
echo "-f <hostfile>: specify a hostfile, defaults to /job/hostfile"
exit 0
;;
f)
hostfile=$OPTARG
shift $((OPTIND-1))
;;
esac
done
echo "hostfile=$hostfile"
if [ -f $hostfile ]; then
hosts=`cat $hostfile | awk '{print $1}' | paste -sd "," -`
export PDSH_RCMD_TYPE=ssh
pdsh -w ${hosts} $@
else
echo "Missing hostfile at ${hostfile}, unable to proceed"
fi
Symlink
+1
View File
@@ -0,0 +1 @@
ds_report
+1
View File
@@ -0,0 +1 @@
All DeepSpeed blogs are linked here:
Binary file not shown.

After

Width:  |  Height:  |  Size: 612 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Some files were not shown because too many files have changed in this diff Show More