How to fine-tune a 70B model: GPU requirements and workflow

70B fine-tuning GPU requirements at a glance
| Method | What sits in GPU memory | Total before activations | Minimum | Comfortable |
|---|---|---|---|---|
| 8× B300 | ||||
| LoRA on a BF16 base | About 145 GB | 2× 80 GB with short sequences, or one B200 | 8× H100 or 8× H200, or one B300 | |
| One 80 GB H100 | One H200, for longer sequences |
Full fine-tuning : why it takes over 1 TB
| State | Precision | Bytes per parameter | 70B model |
|---|---|---|---|
| Weights | BF16 | 2 | 140 GB |
| Gradients | BF16 | 2 | 140 GB |
| Master copy of the weights | FP32 | 4 | 280 GB |
| Adam first moment | FP32 | 4 | 280 GB |
| Adam second moment | FP32 | 4 | 280 GB |
| Total | 16 | 1,120 GB |
Setups that keep gradients or communication buffers in FP32 land closer to 20 bytes per parameter, or 1.4 TB. Either way, the training state is over 1 TB before a single activation is stored.
No single GPU holds that, and plain data parallelism does not help, because every GPU keeps a full copy. You need sharding: PyTorch FSDP or DeepSpeed ZeRO stage 3 split weights, gradients and optimizer states across all GPUs and gather each layer's weights only while it computes. Across eight GPUs, each one holds 140 GB of state at 16 bytes per parameter, or 175 GB at 20. That arithmetic explains the hardware:
- 8× H100 (640 GB in total) cannot hold the state on one server.
- 8× H200
(141 GB each) holds 140 GB of state per GPU with nothing left for activations. It works only if you move the FP32 master weights and Adam moments to CPU memory (about 840 GB, which fits in the server's 2 TB of RAM) or shrink them with 8-bit optimizer states, if your sharding setup supports them. Offloading slows each step, because the optimizer runs on the CPU and state crosses PCIe. - 8× B200 (180 GB each) leaves about 40 GB per GPU for activations and buffers at 16 bytes per parameter, which is workable with activation checkpointing. A setup closer to 20 bytes per parameter leaves almost nothing, and needs offloading here too.
- 8× B300
(288 GB each) leaves well over 100 GB per GPU, enough for longer sequences and larger micro-batches without tricks.
Activation memory and sequence length
LoRA in BF16: the frozen weights set the floor
- 2× 80 GB is the floor: 160 GB in total, enough only with short sequences.
- 8× H100 or 8× H200 is comfortable. Sharded across eight GPUs, the frozen weights take 17.5 GB per GPU, which leaves room for long sequences and for data parallelism across all eight.
- One GPU also works, with no sharding to configure, at the speed of one GPU: a 180 GB B200 holds the job with about 20 GB to spare at 8,192 tokens, and a 288 GB NVIDIA B300 holds it comfortably.
from peft import LoraConfig
lora_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
task_type="CAUSAL_LM",
)
QLoRA: a 70B model on a single GPU
import torch
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16,
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-70B-Instruct",
quantization_config=bnb_config,
device_map="auto",
)
How to fine-tune a 70B model: a practical workflow
- Prepare the data. Format examples as conversations and render them with the model's own chat template (
tokenizer.apply_chat_templatein Transformers). Deduplicate, filter out low-quality examples, and remove personal data you should not train on. Hold out an evaluation split that is never trained on. Measure token lengths: the longest sequences you keep set your activation memory. - Pick a tool.
Hugging Face TRL with PEFT provides trainers for supervised fine-tuning and preference tuning, with Accelerate, FSDP or DeepSpeed for multiple GPUs. Axolotl wraps the same building blocks in YAML configs. torchtune offersPyTorch-native recipes for full, LoRA and QLoRAfine-tuning. All three handle the methods above; pick the one whose config style your team will maintain. - Pin the environment. Use a container or a virtual environment with fixed versions of PyTorch, Transformers, PEFT and your trainer, so that a rerun next month behaves the same.
Run the same pipeline on an 8B model for a few hundred steps. It catches template, masking and data bugs before they cost you a long run.Smoke-test small.- Launch and watch.
Start multi-GPU jobs withtorchrunor your tool's own launcher, inside--nproc_per_node=8 train.pytmuxso that an SSH disconnect does not kill the run. Watch training and evaluation loss, GPU memory and step time; a loss spike or a rising evaluation loss is a reason to stop early.
Checkpoints on NVMe
Checkpoints are large, and you want them on fast local disks:
Full fine-tuning :a resumable checkpoint with optimizer states is the size of the training state, 1.1–1.4 TB. Write it sharded, with every rank saving its own part in parallel.- Model weights only: about 140 GB in BF16, for evaluation and serving.
- LoRA adapter: about 0.4 GB at rank 16 in BF16, so you can keep many.
Our HGX servers carry 8× 3.84 TB of NVMe, room for datasets, the base model and several full checkpoints. The single H100 plan has 2 TB, plenty for QLoRA, where the BF16 base download is the largest file. Keep the last few checkpoints locally, copy the best one off the server, and remember that we do not back up local disks unless agreed in writing. The local NVMe storage guide has the details.
Evaluate, then serve
Evaluate against the base model with the same prompts, chat template and sampling settings:
Loss on the held-out split, to catch overfitting.- Task metrics on your own evaluation set: exact match, a rubric or pairwise preference.
- A regression set of general prompts, to catch lost capabilities such as instruction following or answers in other languages.
- A human read of a sample of outputs. Automated judges help, but they miss things.
For serving, you have two options. Merge the adapter into the base weights with merge_and_unload() in PEFT, then serve the merged model, quantized to FP8 if you want it on a single H200. Merging needs the base in BF16, about 140 GB, which fits in the 225 GB of RAM on our single H100 plan. Or keep the base model loaded and attach adapters at runtime: vLLM can serve several LoRA adapters on one base model. Our guide to
Frequently asked questions
How much GPU memory do I need to fine-tune a 70B model?
Can I fine-tune a 70B model on a single GPU?
Can 8× H100 fully fine-tune a 70B model?
Is LoRA good enough compared with full fine-tuning ?
How large is a LoRA adapter for a 70B model?
Dedicated GPUs, billed monthly
Whole GPUs from $449/mo, root access, bandwidth included. Pay with crypto.
See GPUs & pricing Size your GPU with the VRAM calculator

