def METHOD_NAME(reduce_after=True,
                     no_scale=False,
                     fp32_allreduce=False):
    if (self.needs_reduction):
        self.needs_reduction = False
        buckets = {}
        for name, param in self.module.named_parameters():
            if param.requires_grad and param.grad is not None:
                tp = (param.data.type())
                if tp not in buckets:
                    buckets[tp] = []
                buckets[tp].append(param)
        if self.warn_on_half:
            if torch.cuda.HalfTensor in buckets:
                print(
                    'WARNING: gloo dist backend for half parameters may be extremely slow. It is recommended to use the NCCL backend in this case.'  # noqa
                )
                self.warn_on_half = False
        for tp in buckets:
            bucket = buckets[tp]
            grads = [param.grad.data for param in bucket]
            coalesced = _flatten_dense_tensors(grads)
            if fp32_allreduce:
                coalesced = coalesced.float()
            if not no_scale and not reduce_after:
                coalesced /= dist.get_world_size(
                    group=self.data_parallel_group)
            dist.all_reduce(coalesced, group=self.data_parallel_group)
            torch.cuda.synchronize()
            if not no_scale and reduce_after:
                coalesced /= dist.get_world_size(
                    group=self.data_parallel_group)
            for buf, synced in zip(
                    grads, _unflatten_dense_tensors(coalesced, grads)):
                buf.copy_(synced)