Why LLM Temperature 0 Is Not Reproducible: The Hidden Impact of Dynamic Batching
- Authors

- Name
- Nino
- Occupation
- Senior Tech Editor
Many AI engineers assume that setting temperature=0 (or temperature=0.0) on a Large Language Model (LLM) guarantees 100% deterministic output. Under this belief, sending the exact same prompt, document, and hyperparameters to models like DeepSeek-V3, Claude 3.5 Sonnet, or OpenAI o3 should yield byte-identical results every single time.
However, empirical testing reveals a unsettling reality: identical requests with temperature=0 can experience up to a 30% difference in output between runs when executed under concurrent conditions.
The root cause of this variance is not sampling randomness or greedy decoding failure. It is GPU-level dynamic batching and the non-associative nature of floating-point arithmetic in parallel CUDA kernels.
If you build data extraction pipelines, evaluation benchmarks, or automated agentic workflows via unified LLM routing platforms like n1n.ai, understanding this non-determinism is vital. In this guide, we break down the empirical data, explain the underlying GPU mechanics, and detail actionable techniques to achieve true reproducibility.
The Empirical Discovery: Batching vs. Sampling
To isolate the root cause of temperature 0 variance, an experiment was designed around a structured data extraction task. The pipeline extracted key information records from a test corpus of documents. The model, prompt, document text, and temperature setting (0.0) were kept strictly constant.
The benchmark measured reproducibility using the Jaccard Similarity Index at the extracted record level:
Where and represent the sets of extracted records from two identical runs. A score of 1.0000 indicates absolute byte-identical agreement, while lower values reflect variance.
Experimental Results
| Execution Mode | Concurrency | Total Records Extracted (Run 1 / Run 2) | Byte-Identical Matching | Record-Level Jaccard Similarity |
|---|---|---|---|---|
| Single-Threaded | concurrency=1 | 137 / 137 | Yes | 1.0000 |
| Multi-Threaded | concurrency=4 | 160 / 164 | No | 0.7050 |
| Cross-Comparison | concurrency=1 vs concurrency=4 | 137 / 160 | No | 0.5490 |
Key Takeaways from the Data:
- Concurrency 1 is 100% Deterministic: Running requests strictly sequentially (
concurrency=1) resulted in 137 out of 137 identical records across runs ( Jaccard agreement). - Concurrency 4 Introduces ~30% Drift: Running the exact same code with 4 concurrent requests dropped the Jaccard similarity to 0.7050—meaning nearly 30% of the extracted outputs shifted or degraded.
- Cross-Concurrency Disagreement is Severe: Comparing the outputs of
concurrency=1againstconcurrency=4dropped agreement further to 0.5490.
This proves conclusively that sampling is not the culprit. If greedy sampling were non-deterministic, concurrency=1 would also fail to achieve 1.0000 Jaccard agreement. The variance is directly driven by batch size and dynamic scheduling.
The Technical Root Cause: CUDA FP16/BF16 Non-Associativity
Why does changing the number of concurrent requests alter the mathematical output of a neural network?
To optimize GPU throughput, modern LLM serving engines (such as vLLM, TensorRT-LLM, and cloud API endpoints behind providers available on n1n.ai) utilize Continuous Batching and PagedAttention. Instead of processing one request end-to-end, the engine packs tokens from multiple concurrent requests into unified matrix operations executed across CUDA tensor cores.
Request A (Concurrency 1): [Prompt A] --------> [Kernel Execution Order 1] -> Output A
Request A (Concurrency 4): [Prompt A] \\
Request B: [Prompt B] ===> [Dynamic Batch Tensor Operations] -> Output A'
Request C: [Prompt C] /
Floating-Point Arithmetic Is Not Associative
In standard pure mathematics, addition is associative: .
In computer floating-point arithmetic (especially reduced precision formats like FP16 or BF16 used in LLM inference), floating-point addition is non-associative:
eq a + (b + c)$$ When a GPU executes matrix multiplications (e.g., calculating Attention logits $\\text\{Softmax\}(\\frac\{QK^T\}\{\\sqrt\{d_k\}\})V$), it performs sum reductions across thousands of parallel threads. * At `concurrency=1`, the GPU allocates matrix reduction trees across specific fixed thread blocks. * At `concurrency=4`, tokens from requests B, C, and D alter the batch dimension, sequence lengths, and memory alignment. The GPU's low-level execution scheduler changes the **order of reduction operations** across CUDA cores to maximize hardware utilization. ### The Butterfly Effect of Logit Flipping Because reduced-precision floating-point math depends on reduction order, the final logit values output by the model's final linear layer might shift slightly in the 6th or 7th decimal place: * **Run 1 (Batch size 1):** Logit for Token `"apple"` = `14.000002`, Logit for Token `"banana"` = `14.000001` $\\rightarrow$ Selected: `"apple"` * **Run 2 (Batch size 4):** Logit for Token `"apple"` = `14.000000`, Logit for Token `"banana"` = `14.000003` $\\rightarrow$ Selected: `"banana"` Even with `temperature=0` (greedy decoding choosing `argmax`), a floating-point drift of `0.000003` is sufficient to select a different token. Because LLM generation is autoregressive, **flipping a single token alters the context for all subsequent tokens**, cascading into completely different sentences, JSON structures, or extracted records. --- ## Impact on Benchmarks and Evaluation Metrics How does this non-determinism impact real-world LLM evaluation? To test this, we re-ran a standardized benchmark suite at `concurrency=1` vs high concurrency. | Benchmark Metric | Batched (High Concurrency) | Deterministic (`concurrency=1`) | Variance Delta | | :--- | :--- | :--- | :--- | | **Headline Accuracy Metric** | 0.980 | 0.980 | **0.000** | | **Positional Ordering Task** | 0.942 | 0.904 | **+0.038** | | **Overall Aggregate Score** | 0.899 | 0.870 | **+0.029** | ### Metric-Level Analysis 1. **Macro Metrics Mask Micro Noise:** The headline accuracy metric remained identical at `0.980`. High-level classification or pass/fail evals often hide underlying record-level volatility. 2. **Positional Tasks Are Highly Sensitive:** Tasks requiring specific ordering or sequence extraction moved by up to **0.038 (3.8%)**. These tasks rely on exact token boundaries where floating-point logit shifts occur frequently. 3. **False Positive Risks in A/B Testing:** In prompt engineering experiments, a developer might try a new filter and see performance improve. However, if concurrency is unconstrained, that performance delta may simply be GPU batch noise rather than an actual prompt improvement. --- ## Step-by-Step Implementation: Auditing LLM Determinism To ensure your pipeline or benchmark is robust against concurrency noise, you can implement a Jaccard agreement test using Python. The following script connects to an OpenAI-compatible API endpoint (such as those aggregated on [n1n.ai](https://n1n.ai)) and measures record agreement across concurrent vs sequential runs. ```python import asyncio import json from openai import AsyncOpenAI # Initialize OpenAI client pointing to n1n.ai unified API platform client = AsyncOpenAI( api_key="YOUR_N1N_API_KEY