Same effective batch does not mean same training time with gradient accumulation, tested on LoRA on T4 and L4 [D]
▲ 1 r/deeplearning+1 crossposts

Same effective batch does not mean same training time with gradient accumulation, tested on LoRA on T4 and L4 [D]

I had assumed 1 × 4, 2 × 2 and 4 × 1 will take somewhat similar time because effective batch is 4 in all cases.

They did not.

I ran Qwen3-1.7B with TRL and LoRA for 100 optimizer updates.

GPU 1 × 4 2 × 2 4 × 1
T4 287.6s 258.8s 238.2s
L4 213.02s 119.47s 124.76s

Model, data, sequence length, precision and seed were kept fixed.

Lower is better. On T4, 4 × 1 was around 17% faster than 1 × 4. On L4, difference was around 41%.

The part I had not thought about properly is that effective batch is an optimization knob, but physical batch also decides execution shape which GPU receives.

1 × 4 means four smaller forward and backward passes before one optimizer update. 4 × 1 means one larger forward and backward pass. Same examples reach optimizer, but GPU work is not same.

These are single-GPU runs, henc no communication. Most of difference was inside repeated forward and backward regions, while optimizer time stayed nearly same. Exact reason can still be kernel shapes, tiling, launch overhead or how well each batch uses GPU. This experiment does not separate those kernel-level causes.

Another interesting result is 2 × 2 being slightly faster than 4 × 1 on L4. Difference is small, it shows performance may not be linear as physical batch increases.

Hugging Face documentation also says to use grad accum when larger physical batch does not fit, and that it does not improve throughput over using true larger batch:

https://huggingface.co/docs/transformers/grad_accumulation

So now I treat these as two separate choices:

  • Effective batch for optimization behaviour.
  • Physical batch and accumulation for memory and speed.

I would start with largest physical batch which fits comfortably, then test few nearby combinations on actual GPU.

I used TraceML and its HF callback for step and phase timing. End-to-end runtime comes directly from TRL Trainer.

Runnable notebook:

https://colab.research.google.com/github/traceopt-ai/traceml/blob/main/notebooks/huggingface_trl_lora_gradient_accumulation.ipynb

u/traceml-ai — 14 hours ago

Same effective batch size, but my LoRA run was 17% slower with more gradient accumulation

I was checking one small thing in TRL and I looked at "effective" batch size, but wanted to see how batch changes actual training speed.

I ran Qwen3-1.7B with LoRA on single T4. And I repeated the experiment with different batch configurations but same 100 steps.

| Batch | Accumulation | Effective batch | Runtime | Step time | Peak reserved |
|---:|---:|---:|---:|---:|---:|
| 1 | 4 | 4 | 287.6s | 2871ms | 5.45 GiB |
| 2 | 2 | 4 | 258.8s | 2585ms | 5.58 GiB |
| 4 | 1 | 4 | 238.2s | 2379ms | 5.81 GiB |

So 4 × 1 finished around 49 seconds earlier than 1 × 4. GPU step time was about 17% lower, while reserved memory increased by around 0.36 GiB. The most difference was in forward and backward.

HF docs already tell that gradient accumulation is useful when batch does not fit. I just found the size of difference on T4 interesting from runtime perspective. I made a Colab where the same comparison can be run:

https://colab.research.google.com/github/traceopt-ai/traceml/blob/main/notebooks/huggingface_trl_lora_gradient_accumulation.ipynb

Would be useful to see what numbers people get on L4, A10 or A100.

Disclosure: I maintain TraceML, the open-source tool I used for these measurements.

u/traceml-ai — 2 days ago

In DDP vision training, one slow rank can make every GPU wait. How do you usually find it?

I have been debugging PyTorch DDP slowdown patterns recently, and one framing helped me more than looking at average GPU utilization:

In synchronous DDP, the job moves at the speed of the slowest rank. So the question is not just: Why is DDP slow?

It is: Which rank is slow, and which phase is slowing it down?

In a small repro on 2 nodes / 1 T4 each:

Balanced:
- step time: 124.6 / 124.6 ms
- input: 1.4 / 1.4 ms
- compute: 122.4 / 122.4 ms

Input straggler:
- r0 dataloader: 201.6 ms
- r1 dataloader: 1.4 ms

Compute straggler:
- r0 optimizer: 33.1 ms
- r1 optimizer: 14.5 ms

Same outside symptom, very different fixes. For people who tune DDP jobs regularly: what is your usual escalation path?

Do you start with custom timers, torch.profiler, Nsight Systems, logs, nvidia-smi/dmon, or something else?

Also curious: do you usually separate input, H2D, forward/backward, optimizer, and wait time per rank, or do you jump straight into a full profiler trace?

Disclosure: I am building an open-source tool around this kind of first-pass runtime summary.

reddit.com
u/traceml-ai — 2 months ago

Profiling PyTorch training without accidentally stalling the GPU [D]

Profiling PyTorch training has an interesting measurement problem: the more you measure, the more you can change the behavior of the run itself.

A simple example is torch.cuda.synchronize(). It gives cleaner timing boundaries, but it also inserts synchronization points into an otherwise asynchronous CUDA workload.

An alternative is to use CUDA events around selected boundaries and read them later, so timing can be captured without forcing synchronization in the hot path. This does not replace PyTorch Profiler or Nsight, but it can work as a lightweight first pass before deeper operator-level profiling.

I wrote a short technical note about this while working on an open-source PyTorch training diagnostics tool:

https://medium.com/p/19adf1054bcf

reddit.com
u/traceml-ai — 3 months ago
▲ 15 r/mlops+2 crossposts

Making distributed PyTorch training slowdowns easier to spot

I have been working on TraceML, a local-first runtime diagnostics tool for PyTorch training.

The latest work is focused on distributed runs: making multi-rank / multi-node training easier to inspect after the run finishes. The idea is to produce a compact performance summary for each run, including:

- step time breakdown
- dataloader overhead
- compute vs wait time
- GPU memory behaviour
- rank skew / stragglers

The goal is more of a first-pass regression check: did this run get slower, and where?

For people running DDP/FSDP jobs: what distributed performance issues do you usually miss until too late?

If you have run into these kinds of issues, I would love feedback on what signals would make a distributed training summary actually useful.

Tool info: https://github.com/traceopt-ai/traceml

u/traceml-ai — 3 days ago
▲ 2 r/mlops

How do you diagnose slow PyTorch training runs before using a full profiler?

I wrote a short post about a gap I keep seeing in PyTorch training observability: a run can look healthy from the outside: loss going down, GPUs allocated, no crashes, but still be quietly inefficient inside the training loop.

The question we are trying to answer is:

Before opening PyTorch Profiler or Nsight Systems, how do you quickly tell whether a run is input-bound, compute-bound, rank-skewed, memory-related, or basically balanced?

We’ve been building TraceML around this idea: lightweight step-level diagnostics for PyTorch training, with phase breakdowns, memory signals, rank behavior, live terminal view, and a small final_summary.json artifact.

Post: https://traceopt.medium.com/traceml-stop-flying-blind-inside-your-training-loop-ce82a3dbd26c

Repo: https://github.com/traceopt-ai/traceml

Curious how others handle this today in production training pipelines. Do you rely mostly on profiler traces, custom timers, system metrics, W&B/MLflow logs, or something else?

u/traceml-ai — 3 months ago

For most slow PyTorch runs the first question isn't show me every trace event, it is just: where do I even start?

- where did step time go?
- was the run input-bound, compute-bound, or wait-heavy?
- were ranks imbalanced?
- was memory stable or creeping up?

I haven been thinking about what a compact end-of-run summary would look like: lightweight enough to run on every job, not just dedicated profiling runs.

Here's one example of what that output could look like:

https://preview.redd.it/2q71s9ltkvzg1.png?width=533&format=png&auto=webp&s=cde99ed3224d723bb6dba200b326da826ba4f587

Curious how others are solving this today. What would make something like this useful? What is missing?

reddit.com
u/traceml-ai — 3 months ago