Hugging Face Trainer Integration¶
Install¶
This guide assumes PyTorch and Hugging Face Transformers are already installed. Use Transformers 4.46.1 or newer for training input timing.
pip install traceml-ai
Run¶
traceml run train.py
Run your existing script with TraceML. Standard Trainer training is
instrumented automatically, with no code changes required. For custom training loops or direct
python/torchrun launches, see
Advanced: manual setup.
Read the result¶
When training finishes, TraceML prints a diagnosis of the likely bottleneck and saves the report for comparison or CI.
The timing breakdown shows input waiting, forward, backward, and optimizer work. CUDA runs also show available host-to-device and memory measurements.
See How to Read Output for an example report and explanations.
How TraceML measures Hugging Face training¶
TraceML automatically attaches its Trainer callback and timing hooks. Hugging Face continues to manage batch collection, gradient accumulation, and optimizer updates.
Hugging Face Trainer TraceML measurement
─────────────────────────────────────────────────────────
get_batch_samples() Input Wait + GPU transfer
↓
on_step_begin() Open the step capture
↓
Forward → Backward Record compute timings
(repeated for each microbatch)
↓
Optimizer Record optimizer timing
↓
on_step_end() Complete one reported step
One reported step covers one optimizer update attempt. With
gradient_accumulation_steps=4, four microbatches contribute to that step.
TraceML adds their timings and records peak CUDA memory across the group.
The final group can contain fewer microbatches.
Batch fetching appears separately as Input Wait; GPU transfer and compute contribute to traced training time. Evaluation and prediction are excluded.
Checkpoint resume: Continue using Hugging Face's normal
trainer.train(resume_from_checkpoint=...). TraceML records resumed training
with step numbering local to the new run, which may differ from Hugging
Face's global_step. See Limitations for iterable-dataset
resume handling, or the
developer guide
for exact timing boundaries.
Multi-GPU training¶
For single-node multi-GPU DDP, specify the number of processes:
traceml run train.py --nproc-per-node=4
For multi-node DDP launch commands, see Distributed Training.
Advanced: manual setup¶
Existing scripts using init() and TraceMLTrainerCallback() also work with
traceml run; TraceML reuses compatible setup without adding another callback.
Use this path for a direct python/torchrun launch or a custom Trainer loop
that still dispatches Hugging Face callbacks. A direct launch needs a running
aggregator; start one with traceml serve first (see
Direct Launch). Call
init() once before constructing the Trainer, then register
TraceMLTrainerCallback:
from traceml_ai.integrations import huggingface as traceml_hf
from transformers import Trainer, TrainingArguments
traceml_hf.init()
training_args = TrainingArguments(
output_dir="./output",
report_to="none",
disable_tqdm=True,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
callbacks=[traceml_hf.TraceMLTrainerCallback()],
)
trainer.train()
Use both: the callback groups measurements into completed steps, and init()
installs the process-wide timing patches. Custom loops may still bypass input
timing, as described in Limitations. You do not need to add
traceml.trace_step(...) to your code.
If a custom loop does not dispatch Hugging Face callbacks, instrument that
loop with the core API instead.
Full manual examples¶
Use these examples when you want a complete runnable manual setup. If you
already have a standard Hugging Face training script, start with traceml run.
Install the examples' optional dependencies first:
pip install datasets torchvision
NLP classification example
Save as `fine_tune_nlp.py`:import os
import torch
from datasets import load_dataset
from transformers import (
AutoModelForSequenceClassification,
AutoTokenizer,
Trainer,
TrainingArguments,
)
from traceml_ai.integrations import huggingface as traceml_hf
def main():
traceml_hf.init()
model_name = "prajjwal1/bert-mini"
output_dir = "./hf_nlp_output"
os.makedirs(output_dir, exist_ok=True)
device = "cuda" if torch.cuda.is_available() else "cpu"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(
model_name,
num_labels=4,
).to(device)
raw_dataset = load_dataset("ag_news", split="train[:2000]")
def tokenize(examples):
return tokenizer(
examples["text"],
padding="max_length",
truncation=True,
max_length=64,
)
dataset = raw_dataset.map(tokenize, batched=True)
training_args = TrainingArguments(
output_dir=output_dir,
per_device_train_batch_size=32,
num_train_epochs=3,
logging_steps=10,
save_strategy="no",
use_cpu=(device == "cpu"),
report_to="none",
disable_tqdm=True,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=dataset,
callbacks=[traceml_hf.TraceMLTrainerCallback()],
)
trainer.train()
if __name__ == "__main__":
main()
traceml run fine_tune_nlp.py
Vision classification example
Save as `fine_tune_vision.py`:import os
import torch
from datasets import load_dataset
from torchvision.transforms import Compose, Normalize, RandomResizedCrop, ToTensor
from transformers import (
AutoImageProcessor,
AutoModelForImageClassification,
DefaultDataCollator,
Trainer,
TrainingArguments,
)
from traceml_ai.integrations import huggingface as traceml_hf
def main():
traceml_hf.init()
model_name = "google/vit-base-patch16-224-in21k"
output_dir = "./hf_vision_output"
os.makedirs(output_dir, exist_ok=True)
device = "cuda" if torch.cuda.is_available() else "cpu"
image_processor = AutoImageProcessor.from_pretrained(model_name)
model = AutoModelForImageClassification.from_pretrained(
model_name,
num_labels=10,
).to(device)
dataset = load_dataset("cifar10", split="train[:2000]")
transform = Compose(
[
RandomResizedCrop(
image_processor.size["height"],
scale=(0.8, 1.0),
),
ToTensor(),
Normalize(
mean=image_processor.image_mean,
std=image_processor.image_std,
),
]
)
def preprocess(example):
image = example["img"].convert("RGB")
example["pixel_values"] = transform(image)
example["labels"] = example["label"]
return example
dataset = dataset.map(preprocess)
training_args = TrainingArguments(
output_dir=output_dir,
per_device_train_batch_size=16,
num_train_epochs=2,
logging_steps=10,
save_strategy="no",
report_to="none",
disable_tqdm=True,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=dataset,
data_collator=DefaultDataCollator(),
callbacks=[traceml_hf.TraceMLTrainerCallback()],
)
trainer.train()
if __name__ == "__main__":
main()
traceml run fine_tune_vision.py
API reference¶
For manual setup, init() takes no arguments. Call it once before
constructing the Trainer to install TraceML's process-wide patches
(DataLoader fetch timing, H2D Tensor.to, and the forward/backward/optimizer
auto-timers). It is idempotent and returns the effective TraceMLInitConfig.
TraceMLTrainerCallback() takes no TraceML-specific arguments and records
standard step-level timing and memory.
Limitations¶
- Training input timing. The input collection hook requires
transformers>=4.46.1, whereTrainer.get_batch_samplesis available. If an older version is installed manually, TraceML warns once and lets training continue, but omits training Input Wait and pre-step H2D measurements. - Lifecycle guard. Failure/retry cleanup and duplicate-callback handling
require automatic launch or
traceml_hf.init()to install the Trainer lifecycle guard. If installation fails, TraceML reports the error and training continues without those guarantees. Custom_inner_training_loopoverrides must call the guarded parent implementation to receive this handling. - Custom batch collection. A Trainer subclass that overrides
get_batch_samplesbypasses the standard training-input hook. TraceML warns once for the affected Trainer class and continues without training Input Wait or pre-step H2D signals rather than reporting partial measurements. - Iterable checkpoint resume. When Accelerate lazily consumes skipped batches, the entire first resumed optimizer group is omitted from step telemetry. It still trains normally; subsequent groups are recorded.
- Memory window. Temporary allocation peaks before the callback starts a step are outside its memory measurement.
- Custom loops. Automatic attachment requires the standard
_inner_training_loop. Register the callback beforetrainer.train()for custom loops that drive Hugging Face callbacks themselves.