Parity Augmentation — bit-exact CPU/GPU parity for image augmentation
Project description
paraug
Bit-exact CPU/GPU parity for image augmentation.
Languages: English | 繁體中文
paraug is a PyTorch-native augmentation library that guarantees the same
seed produces the same output on CPU and CUDA. Per-primitive RNG is sampled
on CPU regardless of tensor device, so a training run that randomly switches
between CPU and GPU stages — or a unit test that swaps backends — stays
deterministic.
Why parity matters
Most augmentation libraries (albumentations, kornia, torchvision) use device- local RNG. Same seed, different output across CPU/CUDA. This bites in three places:
- Reproducibility: paper-to-code lineage breaks when a reviewer can't match published numbers.
- Debugging: CPU-side unit tests don't catch GPU-only bugs and vice versa.
- Distributed training: workers on heterogeneous hardware drift apart.
paraug fixes this by isolating RNG to CPU (torch.Generator(device="cpu"))
and routing only the deterministic torch ops through device. Tolerance:
- Elementwise ops (gamma, noise, color jitter, …): atol 1e-6
grid_sample-class ops (affine, perspective, tps, …): atol 2e-4 (bilinear ulp drift across ATen vs cuDNN)
Installation
pip install git+https://github.com/alieuidsh/paraug.git
PyPI release (
pip install paraug) coming once the v0.1.x publish workflow is wired up — see issue tracker for status.
Quickstart
import torch
from paraug import AugPipeline
aug = AugPipeline({
"geometric": {
"affine": {"p": 1.0, "rot_deg": 15.0, "scale_range": (0.9, 1.1)},
"tps": {"p": 0.5, "max_disp": 12.0, "n_ctrl": 5},
},
"photometric": {
"gamma": {"p": 0.5},
"color_jitter": {"p": 0.5},
"gaussian_blur": {"p": 0.3},
},
})
img = torch.rand(2, 3, 256, 256) # (B, C, H, W)
mask = torch.ones(2, 1, 256, 256) # optional
img_out, mask_out = aug(img, mask=mask, seed_base=42, epoch=0, step=0)
The same call on GPU is bit-exact within tolerance:
img_gpu = img.cuda()
mask_gpu = mask.cuda()
img_cuda, mask_cuda = aug(img_gpu, mask=mask_gpu, seed_base=42, epoch=0, step=0)
assert (img_out - img_cuda.cpu()).abs().max() < 2e-4
Primitives
Geometric (7)
| Name | Description |
|---|---|
affine |
Rotation + scale + translation via F.affine_grid |
perspective |
4-point homography from corner jitter |
random_crop_pad |
Scale-then-pad crop, area-preserving |
elastic_transform |
Bilinear-upsampled random displacement field |
optical_distortion |
Radial barrel / pincushion (k·r²) |
random_shadow |
Soft-blurred triangle multiplicative shadow |
tps |
Thin-plate-spline-like warp from low-res control grid |
Photometric (24)
Intensity / color: gamma, color_jitter, hue_shift, random_grayscale,
lighting, clahe, local_contrast, sharpness.
Noise: gaussian_noise, salt_pepper_noise, salt_patches.
Blur / artifacts: gaussian_blur, motion_blur, jpeg_approx.
Lighting: vignette, specular_highlight, specular_streaks.
Content overlays: cutout, paper_texture_overlay, watermark,
random_text_overlay, background_compose, stains, creases.
Parity comparison
| Library | Bit-exact CPU↔GPU | Per-item RNG | GPU native | Mask-aware | Batch-native | # Geometric¹ | # Photometric¹ | License |
|---|---|---|---|---|---|---|---|---|
| paraug | ✓ (1e-6 / 2e-4)² | ✓ | ✓ (torch) | ✓ | ✓ | 7 | 24 | Apache 2.0 |
| albumentations | ✗ (numpy-only) | ✓ | ✗ | ✓ | partial | ~20 | ~50+ | MIT |
| kornia | ✗ (device-local RNG) | ✓ | ✓ (torch) | ✓ | ✓ | ~10 | ~45 | Apache 2.0 |
| torchvision.v2 | ✗ (device-local RNG) | ✓ | ✓ (torch) | partial | ✓ | ~18 | ~12 | BSD-3 |
| imgaug | ✗ (numpy-only) | ✓ | ✗ | ✓ | partial | ~20 | ~40 | MIT |
| augly | ✗ (PIL-only) | ✓ | ✗ | ✗ | ✗ | ~5 | ~20 | MIT |
¹ External counts are approximate as of 2026-05 (sampled from each project's
__init__.py / docs index). Versions move fast — consult each project's
authoritative API reference for current numbers. paraug counts are
code-exact (len(GEOMETRIC_PRIMITIVES) / len(PHOTOMETRIC_PRIMITIVES)).
² Tolerance verified by tests/test_parity.py on NVIDIA 5060 Ti + 4080
at v0.1.0; exact bounds: 1e-6 for the 6 elementwise photometric ops listed
in PHOTO_ELEMENTWISE (gamma / gaussian_noise / color_jitter / vignette /
cutout / hue_shift), 2e-4 for grid_sample-class (geometric) and conv-class
(blur) ops. GitHub free CI runners are CPU-only, so the 13 CUDA parity
tests skip on CI — community verification on additional GPU SKUs is
welcome (open a PR with the result, or run pytest tests/test_parity.py -k cpu_vs_cuda locally and post the output).
When to use paraug
- Cross-device reproducibility (paper-grade ablation where CPU↔GPU drift breaks a baseline)
- Distributed training on heterogeneous hardware
- Unit-test-friendly augmentation pipelines (CPU-side RNG means a test on a free CI runner reproduces a developer's GPU result)
When NOT to use paraug
- You need 50+ primitive options out of the box → try
albumentationsorimgaug - You need PIL-style per-image API → try
augly - You need built-in compositional ops like
OneOf/SomeOf→ tryalbumentations
Examples
See examples/:
01_quickstart.py— minimal load → augment → save02_mask_aware.py— image + segmentation mask warped together03_cpu_gpu_parity.py— same seed on CPU and CUDA, assertmax_abs_diff < 2e-4
Citation
@software{paraug2026,
author = {alieuidsh},
title = {paraug: Bit-exact CPU/GPU parity for image augmentation},
year = {2026},
url = {https://github.com/alieuidsh/paraug},
}
License
Apache 2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file paraug-0.1.1.tar.gz.
File metadata
- Download URL: paraug-0.1.1.tar.gz
- Upload date:
- Size: 2.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
836b1a7865e8ac19d85121af120d46b9e5cfe3924da855c7ab45dfa9bd4a8520
|
|
| MD5 |
641ca8a2703dacd9665ee5cc419425a1
|
|
| BLAKE2b-256 |
10aec0befe99a8ef4a2a4abd1fff8681968fc18b7ea87e6335fa864831f729e2
|
Provenance
The following attestation bundles were made for paraug-0.1.1.tar.gz:
Publisher:
publish.yml on alieuidsh/paraug
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
paraug-0.1.1.tar.gz -
Subject digest:
836b1a7865e8ac19d85121af120d46b9e5cfe3924da855c7ab45dfa9bd4a8520 - Sigstore transparency entry: 1547032467
- Sigstore integration time:
-
Permalink:
alieuidsh/paraug@f6cd3e41ab74d2a4ef61690c1a4beec93541bec2 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/alieuidsh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f6cd3e41ab74d2a4ef61690c1a4beec93541bec2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file paraug-0.1.1-py3-none-any.whl.
File metadata
- Download URL: paraug-0.1.1-py3-none-any.whl
- Upload date:
- Size: 28.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c05855051c6f1de5b9c63aa1549f222f401fde55b4b5be881f5edc5382ad267
|
|
| MD5 |
3a75070bf88c853dbfa9cba5c741dad6
|
|
| BLAKE2b-256 |
479cb36b777c894b7b012dd789db2c22ca82f8a383dc0f80fcf33d89f0da2b45
|
Provenance
The following attestation bundles were made for paraug-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on alieuidsh/paraug
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
paraug-0.1.1-py3-none-any.whl -
Subject digest:
2c05855051c6f1de5b9c63aa1549f222f401fde55b4b5be881f5edc5382ad267 - Sigstore transparency entry: 1547032477
- Sigstore integration time:
-
Permalink:
alieuidsh/paraug@f6cd3e41ab74d2a4ef61690c1a4beec93541bec2 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/alieuidsh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f6cd3e41ab74d2a4ef61690c1a4beec93541bec2 -
Trigger Event:
push
-
Statement type: