traingen-parity¶
traingen-parity contains deterministic training-parity primitives for comparing two training implementations in design-generators. It records named tensors from one training step, captures and restores RNG state, applies deterministic runtime settings, and reports tensor differences for step traces, optimizer states, and dataloader streams.
Keep package-specific trace-point selection in the model package. The shared trace_training_step() primitive accepts model-owned structured batch types while this library remains agnostic to their schemas.
The repository-wide methodology for S0-S5 training reproduction, topology guards, dataset coverage, seed policy, and evidence recording is defined in the training reproduction protocol.
Install¶
uv sync --package traingen-parity
Install from outside the workspace with pip's direct-reference subdirectory form. Install traingen alongside this package when using the shared training CLI.
pip install "traingen @ git+https://github.com/creative-graphic-design/design-generators.git#subdirectory=lib/traingen"
pip install "traingen-parity @ git+https://github.com/creative-graphic-design/design-generators.git#subdirectory=lib/traingen-parity"
API Entry Points¶
Compare exact tensor traces for a single training step.
uv run --package traingen-parity python
import torch
from traingen_parity.compare import compare_step_trace
from traingen_parity.trace import build_step_trace
reference = build_step_trace("reference", {"loss": torch.tensor(0.0)})
target = build_step_trace("target", {"loss": torch.tensor(0.0)})
print(compare_step_trace(reference, target).passed)
Capture deterministic summaries and RNG state for reproducible parity hooks.
import torch
from traingen_parity.determinism import (
DeterminismConfig,
apply_determinism,
capture_rng_state,
)
from traingen_parity.trace import summarize_tensor
apply_determinism(DeterminismConfig(seed=1, deterministic_algorithms=False))
state = capture_rng_state()
summary = summarize_tensor(torch.ones(2))
print(bool(state.torch_cpu.numel()))
print(summary.shape)
Compare optimizer parameters after one update.
import torch
from traingen_parity.compare import compare_optimizer_step
reference_state = {"weight": torch.ones(2)}
target_state = {"weight": torch.ones(2)}
print(compare_optimizer_step(reference_state, target_state).passed)
Let reference code written for TensorFlow 2.8 Keras import its preprocessing layers on TensorFlow 2.15. Call this before importing that code, in an environment that has TensorFlow installed.
from traingen_parity.tensorflow_compat import install_keras_preprocessing_compat
install_keras_preprocessing_compat()
Scope¶
- Keep comparison dataclasses, tensor summaries, RNG helpers, and deterministic runtime controls here.
- Keep
traingen_parity.tensorflow_compathere:install_keras_preprocessing_compat()lets reference scripts run TensorFlow 2.8 Keras code on TensorFlow 2.15 by registeringtensorflow.keras.layers.experimental.preprocessingand renamingmask_valuetomask_token. It imports TensorFlow only when called. - Import helpers from their submodules (
compare,determinism,trace,tensorflow_compat); the package root re-exports nothing, so a TensorFlow reference process can importtraingen_parity.tensorflow_compatwithout importing PyTorch (the package still installs PyTorch as a dependency). - Keep model-specific fixture construction, trace-point names, and parity pytest markers in
models/*. - Keep routine Lightning hooks and CLI integration in
traingen.
Pointers¶
API Reference¶
Shared training parity helpers for generator packages.
Import helpers from their submodules: traingen_parity.compare,
traingen_parity.determinism, traingen_parity.trace, and
traingen_parity.tensorflow_compat. The package root re-exports nothing, so
importing traingen_parity.tensorflow_compat in a TensorFlow reference
environment does not import PyTorch.
compare ¶
Comparison reports for training parity traces.
TensorTolerance
dataclass
¶
Absolute and relative tolerances for tensor comparison.
Source code in lib/traingen-parity/src/traingen_parity/compare.py
14 15 16 17 18 19 | |
TensorComparison
dataclass
¶
Result for one tensor comparison.
Source code in lib/traingen-parity/src/traingen_parity/compare.py
22 23 24 25 26 27 28 29 30 | |
StepReport
dataclass
¶
Comparison report for two training-step traces.
Source code in lib/traingen-parity/src/traingen_parity/compare.py
33 34 35 36 37 38 39 | |
OptimizerStepReport
dataclass
¶
Comparison report for parameters after an optimizer step.
Source code in lib/traingen-parity/src/traingen_parity/compare.py
42 43 44 45 46 47 48 | |
BatchStreamReport
dataclass
¶
Comparison report for two dataloader streams.
Source code in lib/traingen-parity/src/traingen_parity/compare.py
51 52 53 54 55 56 57 | |
compare_tensors ¶
compare_tensors(
name: str,
actual: Shaped[Tensor, "..."],
expected: Shaped[Tensor, "..."],
tolerance: TensorTolerance | None = None,
) -> TensorComparison
Compare two tensors and return max-difference diagnostics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Tensor name. |
required |
actual
|
Shaped[Tensor, '...']
|
Actual tensor. |
required |
expected
|
Shaped[Tensor, '...']
|
Expected tensor. |
required |
tolerance
|
TensorTolerance | None
|
Absolute and relative tolerance. Defaults to exact equality. |
None
|
Returns:
| Type | Description |
|---|---|
TensorComparison
|
Tensor comparison report. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If tensors cannot be broadcast for comparison. |
Examples:
>>> compare_tensors("x", torch.ones(1), torch.ones(1)).passed
True
Source code in lib/traingen-parity/src/traingen_parity/compare.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | |
compare_step_trace ¶
compare_step_trace(
reference: StepTrace,
target: StepTrace,
tolerances: Mapping[str, TensorTolerance] | None = None,
) -> StepReport
Compare two named step traces.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reference
|
StepTrace
|
Reference trace. |
required |
target
|
StepTrace
|
Converted implementation trace. |
required |
tolerances
|
Mapping[str, TensorTolerance] | None
|
Per-tensor tolerance map. |
None
|
Returns:
| Type | Description |
|---|---|
StepReport
|
Step comparison report. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If tensor comparisons fail unexpectedly. |
Examples:
>>> from traingen_parity.trace import build_step_trace
>>> a = build_step_trace("a", {"x": torch.ones(1)})
>>> compare_step_trace(a, a).passed
True
Source code in lib/traingen-parity/src/traingen_parity/compare.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
compare_optimizer_step ¶
compare_optimizer_step(
reference_state: Mapping[str, Shaped[Tensor, "..."]],
target_state: Mapping[str, Shaped[Tensor, "..."]],
tolerances: Mapping[str, TensorTolerance] | None = None,
) -> OptimizerStepReport
Compare two state dictionaries after an optimizer step.
Source code in lib/traingen-parity/src/traingen_parity/compare.py
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | |
compare_batch_stream ¶
compare_batch_stream(
reference_loader: Iterable[
Mapping[str, Shaped[Tensor, "..."]]
],
target_loader: Iterable[
Mapping[str, Shaped[Tensor, "..."]]
],
*,
steps: int,
) -> BatchStreamReport
Compare two dataloader streams for exact tensor equality.
Source code in lib/traingen-parity/src/traingen_parity/compare.py
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | |
determinism ¶
Determinism controls and RNG snapshots for training parity.
DeterminismConfig
dataclass
¶
Determinism options used by parity harnesses.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int
|
Seed used when strict deterministic mode is enabled. |
42975
|
deterministic_algorithms
|
bool
|
Whether to require deterministic torch kernels. |
True
|
cudnn_benchmark
|
bool
|
Value for |
False
|
allow_tf32
|
bool
|
Whether TF32 matmul and cuDNN kernels are allowed. |
False
|
cublas_workspace_config
|
str | None
|
Optional CUBLAS workspace config. This must be present before CUDA kernels start for strict bitwise checks. |
':4096:8'
|
Returns:
| Type | Description |
|---|---|
|
Configuration dataclass. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If deterministic algorithms are unavailable. |
Examples:
>>> cfg = DeterminismConfig(seed=1)
>>> cfg.seed
1
Source code in lib/traingen-parity/src/traingen_parity/determinism.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
RNGState
dataclass
¶
Captured Python, NumPy, torch CPU, and torch CUDA RNG state.
Source code in lib/traingen-parity/src/traingen_parity/determinism.py
48 49 50 51 52 53 54 55 | |
apply_determinism ¶
apply_determinism(config: DeterminismConfig) -> None
Apply deterministic runtime settings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
DeterminismConfig
|
Determinism configuration. |
required |
Returns:
| Type | Description |
|---|---|
None
|
None. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If torch cannot enable deterministic algorithms. |
Examples:
>>> apply_determinism(DeterminismConfig(deterministic_algorithms=False))
Source code in lib/traingen-parity/src/traingen_parity/determinism.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
capture_rng_state ¶
capture_rng_state() -> RNGState
Capture all RNG states needed for step-level parity.
Returns:
| Type | Description |
|---|---|
RNGState
|
RNG state dataclass. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If torch cannot read CUDA RNG state. |
Examples:
>>> state = capture_rng_state()
>>> isinstance(state.torch_cpu, torch.Tensor)
True
Source code in lib/traingen-parity/src/traingen_parity/determinism.py
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | |
restore_rng_state ¶
restore_rng_state(state: RNGState) -> None
Restore a state captured with :func:capture_rng_state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
RNGState
|
Previously captured RNG state. |
required |
Returns:
| Type | Description |
|---|---|
None
|
None. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If CUDA state restoration fails. |
Examples:
>>> state = capture_rng_state()
>>> restore_rng_state(state)
Source code in lib/traingen-parity/src/traingen_parity/determinism.py
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | |
tensorflow_compat ¶
TensorFlow 2.15 compatibility for reference code written for TensorFlow 2.8 Keras.
Reference-output scripts run original-code dependencies that import
tensorflow.keras.layers.experimental.preprocessing and pass mask_value to
lookup layers. TensorFlow 2.15 removed that module path and renamed the argument
to mask_token. TensorFlow is imported only when the shim is installed.
normalize_lookup_kwargs ¶
normalize_lookup_kwargs(
kwargs: Mapping[str, KerasLookupKwarg],
) -> dict[str, KerasLookupKwarg]
Rename the TensorFlow 2.8 mask_value lookup argument to mask_token.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kwargs
|
Mapping[str, KerasLookupKwarg]
|
Keyword arguments passed to a Keras lookup layer. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, KerasLookupKwarg]
|
A copy of |
Source code in lib/traingen-parity/src/traingen_parity/tensorflow_compat.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | |
install_keras_preprocessing_compat ¶
install_keras_preprocessing_compat() -> None
Register tensorflow.keras.layers.experimental.preprocessing for TF 2.15.
The registered module provides StringLookup and IntegerLookup that
accept mask_value and expose vocab_size(), plus Discretization.
Raises:
| Type | Description |
|---|---|
ImportError
|
If TensorFlow is not installed. |
Source code in lib/traingen-parity/src/traingen_parity/tensorflow_compat.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | |
trace ¶
Tensor summaries and step traces for training parity.
TrainingStepModule ¶
Bases: Protocol[BatchT]
Protocol for objects that expose a Lightning-like training step.
Source code in lib/traingen-parity/src/traingen_parity/trace.py
18 19 20 21 22 23 24 | |
training_step ¶
training_step(
batch: BatchT, batch_idx: int
) -> Shaped[torch.Tensor, "..."]
Run one training step.
Source code in lib/traingen-parity/src/traingen_parity/trace.py
21 22 23 24 | |
TensorSummary
dataclass
¶
Compact deterministic summary of a tensor.
Source code in lib/traingen-parity/src/traingen_parity/trace.py
27 28 29 30 31 32 33 34 35 36 37 | |
StepTrace
dataclass
¶
Named tensor trace from a training step.
Source code in lib/traingen-parity/src/traingen_parity/trace.py
40 41 42 43 44 45 46 47 | |
tensor_sha256 ¶
tensor_sha256(tensor: Shaped[Tensor, '...']) -> str
Return a SHA-256 digest for tensor bytes on CPU.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor
|
Shaped[Tensor, '...']
|
Tensor to hash. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Hex digest of the contiguous CPU tensor bytes. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the tensor cannot be copied to CPU. |
Examples:
>>> tensor_sha256(torch.tensor([1, 2])).startswith("0")
False
Source code in lib/traingen-parity/src/traingen_parity/trace.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
summarize_tensor ¶
summarize_tensor(
tensor: Shaped[Tensor, "..."],
) -> TensorSummary
Build a deterministic tensor summary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor
|
Shaped[Tensor, '...']
|
Tensor to summarize. |
required |
Returns:
| Type | Description |
|---|---|
TensorSummary
|
Tensor summary dataclass. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If tensor statistics cannot be computed. |
Examples:
>>> summarize_tensor(torch.ones(2)).mean
1.0
Source code in lib/traingen-parity/src/traingen_parity/trace.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | |
build_step_trace ¶
build_step_trace(
name: str,
tensors: dict[str, Shaped[Tensor, "..."]],
*,
metadata: TraceMetadata | None = None,
) -> StepTrace
Build a trace from named tensors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Trace name. |
required |
tensors
|
dict[str, Shaped[Tensor, '...']]
|
Named tensor values. |
required |
metadata
|
TraceMetadata | None
|
Optional non-tensor metadata. |
None
|
Returns:
| Type | Description |
|---|---|
StepTrace
|
Step trace with summaries. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If tensor summaries cannot be computed. |
Examples:
>>> trace = build_step_trace("step", {"loss": torch.tensor(1.0)})
>>> "loss" in trace.summaries
True
Source code in lib/traingen-parity/src/traingen_parity/trace.py
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |
trace_training_step ¶
trace_training_step(
module: TrainingStepModule[BatchT],
batch: BatchT,
rng_state: RNGState | None,
trace_points: tuple[str, ...],
) -> StepTrace
Run module.training_step and collect requested trace points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
TrainingStepModule[BatchT]
|
Object exposing |
required |
batch
|
BatchT
|
Training batch. |
required |
rng_state
|
RNGState | None
|
Optional RNG state restored before the step. |
required |
trace_points
|
tuple[str, ...]
|
Requested tensor names. |
required |
Returns:
| Type | Description |
|---|---|
StepTrace
|
Step trace for requested tensor names. |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If the module does not expose |
Examples:
>>> class M:
... def training_step(self, batch, batch_idx):
... self.latest_step_trace = {"loss": torch.tensor(1.0)}
... return torch.tensor(1.0)
>>> trace_training_step(M(), {}, None, ("loss",)).tensors["loss"].item()
1.0
Source code in lib/traingen-parity/src/traingen_parity/trace.py
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | |
scalar_trace_value ¶
scalar_trace_value(value: Float[Tensor, '']) -> float
Return a Python scalar from a scalar tensor.
Source code in lib/traingen-parity/src/traingen_parity/trace.py
183 184 185 | |