Skip to content

[WIP] support tps#9513

Open
Jintao-Huang wants to merge 1 commit into
modelscope:mainfrom
Jintao-Huang:support_tps
Open

[WIP] support tps#9513
Jintao-Huang wants to merge 1 commit into
modelscope:mainfrom
Jintao-Huang:support_tps

Conversation

@Jintao-Huang

Copy link
Copy Markdown
Collaborator

No description provided.

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request introduces token-level tracking and logging during training, including computing token counts in the data collator, accumulating them in the trainer state, and reporting token throughput in the progress logs. It also adds a reduction option to MeanMetric. However, several critical issues were identified in the review: an undefined variable reduction in MeanMetric.compute, missing imports and unsupported CPU tensor operations for distributed reduction in patcher.py, an incomplete statement (logs['']), a potential AttributeError when accessing self.state.num_tokens, and an inefficient list-flattening operation in the data collator.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread swift/metrics/utils.py
self.state, self.count = tensor[0].item(), int(tensor[1].item())
if self.count == 0:
value = self.nan_value
if reduction == '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.

high

The variable reduction is not defined in the compute method. It should be accessed via self.reduction as initialized in __init__.

Suggested change
if reduction == 'sum':
if self.reduction == 'sum':

Comment thread swift/trainers/patcher.py
Comment on lines +31 to +39
num_tokens = getattr(state, 'num_tokens', None)
if num_tokens is not None:
num_tokens = float(num_tokens)
if dist.is_initialized():
num_tokens = torch.tensor(num_tokens)
dist.all_reduce(num_tokens, op=dist.ReduceOp.SUM)
tps = num_tokens / elapsed
logs['num_input_tokens_seen'] = round(num_tokens, 6)
logs['train_speed(tokens/s)'] = round(tps, 6)

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.

high

There are several issues here:\n1. torch and dist are not imported in this file, which will cause a NameError at runtime.\n2. torch.tensor(num_tokens) creates a CPU tensor by default. In distributed training with NCCL backend, all_reduce on CPU tensors is not supported and will fail.\n3. num_tokens becomes a torch.Tensor after all_reduce, and calling round() on it or dividing it might cause issues or keep it as a tensor. It should be converted back to a float using .item().

    num_tokens = getattr(state, 'num_tokens', None)\n    if num_tokens is not None:\n        import torch\n        import torch.distributed as dist\n        from swift.utils import get_current_device\n        num_tokens = float(num_tokens)\n        if dist.is_initialized():\n            device = get_current_device()\n            num_tokens_tensor = torch.tensor(num_tokens, device=device)\n            dist.all_reduce(num_tokens_tensor, op=dist.ReduceOp.SUM)\n            num_tokens = num_tokens_tensor.item()\n        tps = num_tokens / elapsed\n        logs['num_input_tokens_seen'] = round(num_tokens, 6)\n        logs['train_speed(tokens/s)'] = round(tps, 6)

Comment thread swift/trainers/patcher.py
n_steps = state.global_step - self.current_step
num_tokens = logs.pop('num_tokens', None)
if num_tokens is not None and n_steps > 0:
logs['']

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.

high

This line is incomplete and will raise a KeyError at runtime because '' is not a valid key in logs. Please complete the logging logic or remove this line.

Comment on lines +142 to +143
if num_tokens is not None:
self.state.num_tokens += num_tokens

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.

high

self.state (which is a TrainerState from transformers) does not have a num_tokens attribute by default. This will raise an AttributeError on the first training step. It should be initialized safely.

        if num_tokens is not None:\n            self.state.num_tokens = getattr(self.state, 'num_tokens', 0) + num_tokens

Comment thread swift/template/base.py
if self.packing and isinstance(batch[0], list):
batch = sum(batch, start=[])
num_samples = len(batch)
num_tokens = sum(sum([b['lengths'] for b in batch], start=[]))

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.

medium

Using sum(..., start=[]) to flatten lists is highly inefficient ($O(N^2)$ complexity) and can cause performance bottlenecks with larger batch sizes. Additionally, if any batch element is missing the 'lengths' key, it will raise a KeyError. A more efficient and robust approach is to sum the lengths generator-style.

Suggested change
num_tokens = sum(sum([b['lengths'] for b in batch], start=[]))
num_tokens = sum(sum(b.get('lengths', [])) for b in batch)

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.

1 participant