n4nAI

Tokens per second at batch size 1 vs batch size 64

A practical tokens per second batch size comparison: batch size 1 versus 64 across latency, cost, ergonomics, and limits for LLM inference.

n4n Team5 min read1,013 words

Audio narration

Coming soon — every post will get a voice note here.

When you move from processing a single prompt to firing 64 prompts at once, the tokens per second batch size comparison stops being theoretical and starts dictating your infrastructure bill. At batch size 1 the GPU spends most of its cycles waiting on memory; at batch size 64 it finally gets enough parallel work to saturate compute—but per-request latency and memory pressure shift the tradeoff hard. This article breaks down the two operating points across the dimensions that matter when you ship.

What batch size actually changes

Batch size in LLM inference is the number of sequences you forward through the model in the same CUDA kernel launch. At BS=1, the matrix multiplies are tiny: a 7B model with float16 weights still needs ~14GB of memory reads per token, but the math is only a few GFLOPs. The accelerator is memory-bandwidth bound and idle most of the time.

At BS=64, those same weight reads are reused across 64 sequences. Arithmetic intensity climbs, and you approach the GPU’s peak FLOPS. You generate more total tokens per second, but each sequence waits behind the others in the batch for its turn in the attention and MLP layers.

# Static batching with Hugging Face, BS=64
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch, time

tok = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf", torch_dtype=torch.float16, device_map="auto"
)
prompts = ["Summarize: batch inference matters."] * 64
inputs = tok(prompts, return_tensors="pt", padding=True, truncation=True).to("cuda")
start = time.time()
out = model.generate(**inputs, max_new_tokens=128)
elapsed = time.time() - start
generated = (out != tok.pad_token_id).sum().item() - inputs.input_ids.numel()
print(f"Aggregate: {generated/elapsed:.0f} tok/s, per-seq: {elapsed/64:.2f}s")

The same loop with prompts = ["..."] * 1 gives you the BS=1 baseline.

Head-to-head: batch size 1 vs batch size 64

The following table summarizes the operating characteristics. Numbers are qualitative; exact figures depend on model size, GPU, and serving stack.

Dimension Batch size 1 Batch size 64
Aggregate throughput Low (memory-bound) 5–20× higher (compute-bound)
Per-request latency Minimal TTFT, steady inter-token Higher TTFT, variable decode
VRAM footprint Small KV cache, fits easily Large KV cache, needs planning
Cost per token (self-host) High amortized Low amortized
Client complexity Trivial single call Padding, masking, or server batching
Supported seq len Max context freely Reduced by KV cache budget
Best fit Interactive chat, code completion Offline ETL, eval suites

Capabilities

BS=1 handles one stream. You can use speculative decoding, tight timeouts, and per-request sampling params without coordination. BS=64 requires either static padding (wasting compute on pad tokens) or a ragged/batch-aware kernel. Most production servers avoid explicit batching by using continuous batching, but if you run offline generation you still choose how many prompts to pack.

Price and cost model

Cloud APIs charge per output token regardless of how many concurrent requests you open. The tokens per second batch size comparison matters because higher batch throughput on your side reduces the wall-clock during which you hold connections and retries. Self-hosting, the math is direct: a fixed GPU hour yields N tokens at BS=1 and ~10N at BS=64, so cost per million tokens drops proportionally.

Latency and throughput

This is the core of the tokens per second batch size comparison. BS=1 gives you, say, 30–50 tok/s on a 7B model on one A100, with time-to-first-token under 50 ms. BS=64 might push aggregate decode to 1500+ tok/s, but each user in the batch sees TTFT in the hundreds of ms and per-token latency that depends on batch position. For synchronous UX, that is unacceptable; for a nightly corpus rewrite, it is ideal.

Ergonomics

A BS=1 call is a single POST /v1/completions with one prompt. BS=64 either means 64 parallel requests (handled by a continuous-batching server) or one request with an array of prompts if the server supports it. You must manage padding, attention masks, and uneven generation lengths. In practice, engineers lean on vLLM or TGI to hide this, but the mental model still shifts from “one answer” to “a queue drained together.”

# 64 concurrent requests against an OpenAI-compatible endpoint
for i in $(seq 1 64); do
  curl -s localhost:8000/v1/completions \
    -H "Content-Type: application/json" \
    -d '{"model":"local","prompt":"batch test","max_tokens":128}' &
done
wait

Ecosystem and tooling

Nearly every high-performance inference server (vLLM, TensorRT-LLM, Hugging Face TGI) implements continuous batching, so the client rarely sets batch size explicitly. For offline workloads, PyTorch DataLoader with batch_size=64 and generate() is standard. If you aggregate throughput across providers via a gateway such as n4n.ai, per-token metering and automatic fallback let you sustain large batch jobs without hand-rolling retry and rate-limit logic.

Hard limits

VRAM is the wall. KV cache size = 2 * batch * seq_len * n_layers * n_heads * head_dim * dtype_bytes. At BS=64 with 4k context on a 13B model, that cache alone can exceed 20GB, leaving little for weights. You also hit scheduler queues: some endpoints cap concurrent requests. Finally, long-tail latency appears when one sequence in the batch requests 2k tokens while others finish at 32—the batch stays alive until the longest completes unless the server supports chunked eviction.

Benchmark methodology that doesn’t lie

Synthetic “hello world” prompts produce misleading tokens per second batch size comparison results because they exit early. Use real-length prompts and a fixed max_new_tokens. Measure wall-clock from first byte to last, then compute:

aggregate_tok_s = total_generated_tokens / elapsed_seconds
per_seq_latency = elapsed_seconds / batch_size   # naive, ignores overlap

Better: log per-request completion timestamps from the client side when using concurrent calls. That captures the true queuing penalty at BS=64.

Continuous batching erases the binary

The BS=1 vs BS=64 framing is clean for benchmarks, but production servers don’t wait for a full batch. They admit new requests as old ones finish, holding GPU occupancy near 90% even at low traffic. So the practical tokens per second batch size comparison is really “static batched offline” vs “dynamic batched online.” If you control the serving layer, tune --max-num-seqs (vLLM) rather than forcing a fixed batch.

Which to choose

Interactive applications — chatbots, autocomplete, agent tool calls. Use BS=1 semantics (or continuous batching with low concurrency caps). Prioritize TTFT and stable inter-token delay. Pay the higher per-token cost; users notice latency before they notice your GPU bill.

Offline transformation — document summarization, training-data generation, embedding backfills. Pack to BS=64 or the maximum your VRAM allows. Throughput per dollar is the only metric; latency of minutes is fine.

Evaluation and benchmarking — accuracy suites over 10k prompts. Batch aggressively, but shard across multiple workers to avoid a single stuck sequence. Use the aggregate tok/s number to size your fleet.

Hybrid RAG pipelines — if you retrieve 64 chunks and need a single synthesized answer, that’s not BS=64; it’s one long context. Keep the generation call at BS=1 and parallelize only the embedding or retrieval steps.

Pick the batch size that matches the latency budget, not the headline throughput. The tokens per second batch size comparison is a tool for capacity planning, not a setting you ship to users.

Tagsthroughputbatch-sizetokens-per-secondbenchmark

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All batch inference throughput benchmarks posts →