Skip to content

Add configurable sum gradient reduction - #8232

Open
zupengwang wants to merge 1 commit into
deepspeedai:masterfrom
zupengwang:feature/gradient-allreduce-sum
Open

Add configurable sum gradient reduction#8232
zupengwang wants to merge 1 commit into
deepspeedai:masterfrom
zupengwang:feature/gradient-allreduce-sum

Conversation

@zupengwang

Copy link
Copy Markdown
Contributor

Summary

  • add a gradient_allreduce_op configuration with "mean" as the default and "sum" as the new option
  • support unscaled gradient sums for ZeRO stages 0, 1, and 2 across reduce-scatter, allreduce, and non-contiguous fallback paths
  • reject unsupported ZeRO stage 3 and ZenFlow combinations with clear configuration errors
  • document the option and preserve existing mean-reduction behavior

Addresses #7107.

Motivation

Some distributed objectives, including contrastive learning over globally gathered embeddings, require summing data-parallel gradients rather than averaging them. Today users need to rescale the loss manually to cancel DeepSpeed's world-size normalization.

This change makes the reduction semantics explicit while keeping the current behavior as the default.

Validation

Tested on two NVIDIA GeForce RTX 3090 GPUs with PyTorch 2.13.0+cu130:

  • pytest --forked -q tests/unit/v1/zero/test_zero.py::TestGradientAllreduceOp — 18 passed
  • targeted configuration tests in tests/unit/runtime/test_ds_config_dict.py — 6 passed
  • pytest --forked -q tests/unit/v1/zero/test_zero_coalesce_grad_reduction.py::TestCoalesceCombinations — 12 passed
  • pytest --forked -q tests/unit/runtime/sparse_tensor/test_averaging_sparse_gradients.py — 1 passed
  • changed-file pre-commit hooks, including YAPF, flake8, codespell, license, check-torchdist, and check-torchcuda — passed

The distributed test matrix covers ZeRO stages 0/1/2, mean and sum reductions, reduce-scatter, gradient predivide, prescale, and non-contiguous gradient fallback.

Limitations

gradient_allreduce_op="sum" is intentionally not supported with ZeRO stage 3 or ZenFlow. These combinations fail during configuration instead of silently applying mean semantics.

Signed-off-by: Wang Zupeng <zupenwang@gmail.com>
@zupengwang
zupengwang marked this pull request as ready for review August 7, 2026 11:07

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a3b05de83

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

self._unmanaged_backward_count = 0
self.skipped_steps = 0
self.gradient_average = True
self.gradient_average = config_class.gradient_allreduce_op == GRADIENT_ALLREDUCE_OP_MEAN

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Propagate sum mode into DeepCompile reductions

When ZeRO stage 1 or 2 runs with an active DeepCompile backend, allreduce_gradients() returns at engine.py:2842 before any of the new sum-aware paths execute. DeepCompile instead keeps pre_div_reduce = true (csrc/compile/deepcompile.cpp:21) and unconditionally divides every bucket by the process-group size in CustomOpExecutor::applyPreDivision() (csrc/includes/deepcompile.h:590-600), so gradient_allreduce_op="sum" silently still produces a mean and scales updates down by the data-parallel world size. Pass this mode into the compiled reducer or reject the combination during configuration.

Useful? React with 👍 / 👎.

return get_scalar_param(param_dict, GRADIENT_PREDIVIDE_FACTOR, GRADIENT_PREDIVIDE_FACTOR_DEFAULT)


def get_gradient_allreduce_op(param_dict):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add the required Signed-off-by trailer

The reviewed commit is a non-merge commit, but its message contains no Signed-off-by trailer. Add the trailer using the configured Git identity before merging so the commit satisfies the repository's commit and CI requirements.

AGENTS.md reference: AGENTS.md:L8-L8

Useful? React with 👍 / 👎.

<= ZeroStageEnum.max_stage), "DeepSpeedConfig: Maximum supported ZeRO stage is {}".format(
ZeroStageEnum.max_stage)

if (self.gradient_allreduce_op == GRADIENT_ALLREDUCE_OP_SUM

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

any reason why zero3 is not supported at this moment?

else:
values.mul_(1. / (dp_world_size))
else:
values.mul_(1. / (dp_world_size))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is this where we divide by dp world size to make sure the gradients used for optimizer is still scaled?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants