lanczos-triton
简体中文 · Installation · API · Algorithm · Benchmark
Lanczos Triton implements antialiased Lanczos-2 and Lanczos-3 image resizing as Triton GPU kernels. It provides a PyTorch tensor API and a reusable resizer for fixed-resolution image and video pipelines.
Both axes support integer and fractional scale ratios, including reduction, enlargement and mixed directions. Kernels retain the full Lanczos support and are compiled by Triton on first use. There are no pretrained weights or project-specific C++/CUDA extensions to build.
| Capability | What you get |
|---|---|
| Tensor API | NCHW input, batch support, independently processed channels |
| Resampling | Lanczos-2/3, half-pixel coordinates, antialiased reduction |
| Repeated processing | Reusable geometry weights and optional device autotuning |
| Integration | Contiguous float32 output on the input CUDA device |
| Inspectable implementation | Triton source, independent numerical tests, benchmark tools |
Qualitative illustration
Figure 1. A common input resized by independent per-channel Pillow float Lanczos and this implementation. The upper row reduces resolution; the lower row enlarges it. Dimensions are given as height × width. Outputs use Lanczos-3 and antialiased reduction, without sharpening or learned postprocessing.
Floating outputs are compared before display clipping. Panels use nearest-neighbor rendering and fit their respective axes; compare the reference and Triton panels at the same output dimensions. The illustration is not a ground-truth reconstruction benchmark.
Get started
Use Python 3.10+, Linux, an NVIDIA GPU and a compatible CUDA-enabled PyTorch build. Install PyTorch using its installation selector, then run this from the checkout:
python -m pip install -e .
The package requires PyTorch ≥2.6 and Triton ≥3.2. Keep their versions
compatible; check torch.cuda.is_available() before use. The first call for
a new kernel specialization includes JIT compilation.
Python
import torch
from lanczos_triton import resize
# Replace with your own finite floating-point NCHW image.
image = torch.rand(1, 3, 2160, 3840, device="cuda")
output = resize(image, (1537, 2731), a=3, antialias=True)
assert output.shape == (1, 3, 1537, 2731)
assert torch.isfinite(output).all()
| Argument / contract | Behavior |
|---|---|
image |
Nonempty NCHW NVIDIA CUDA tensor; float16, bfloat16 or float32 |
size |
Positive integer (height, width) target dimensions |
a=3 |
Lanczos support parameter; choose 2 or 3 |
antialias=True |
Widen the filter support on each shrinking axis |
| Output | Same device, target size, contiguous float32; input unchanged |
Noncontiguous inputs are accepted and copied to contiguous storage. Equal input/output dimensions return an independent float32 copy. Finite values are required, but the API does not scan for NaN/Inf and synchronize the GPU. Inputs requiring gradients are rejected; detach explicitly for inference.
Input and output values are not clipped or normalized. Lanczos has negative
lobes and can overshoot near sharp edges; use output.clamp(0, 1) when that
is appropriate for display. Each channel is processed independently,
including alpha. Color-space conversion and alpha premultiplication belong
to the calling pipeline.
Reuse weights across frames
from lanczos_triton import Resizer
resizer = Resizer(
(2160, 3840),
(1537, 2731),
a=3,
antialias=True,
device=image.device,
autotune=True,
)
output = resizer(image)
Resizer fixes the input/output height, width and device, while allowing
different batches, channel counts and supported dtypes. It shares geometry
weights, not mutable image buffers. autotune=False is the default;
True benchmarks several equivalent launch configurations on first use.
Report this startup cost separately from steady-state inference.
Calls support different CUDA streams; input production and output consumption
still follow PyTorch stream synchronization rules. For CUDA Graphs, construct
the resizer outside capture, warm up the exact shape/dtype and synchronize
before capture. Keep the resizer and input alive for the graph's lifetime.
This class is a callable utility, not an nn.Module or serialized model.
How it works
Figure 2. (a) Lanczos-2 and Lanczos-3 reconstruction kernels.
(b) Continuous Lanczos-3 kernels L(x/s)/s for scales s=1,3 illustrate
support widening. Actual discrete weights are normalized separately at each
output position, including image boundaries.
The one-dimensional kernel is L(t) = sinc(t) * sinc(t/a) for |t| < a,
and zero elsewhere, where sinc(t) = sin(pi*t)/(pi*t) and sinc(0)=1.
Two one-dimensional passes implement separable two-dimensional resampling.
| Convention | Definition |
|---|---|
| Pixel centers | Output index j maps to (j + 0.5) * input_size / output_size - 0.5 |
| Antialias scale | s = max(input_size/output_size, 1); s=1 when disabled |
| Sample weight | L((i-center)/s), normalized over valid input indices |
| Boundaries | Exclude samples outside the image and renormalize remaining weights |
| Arithmetic | Float32 weights, accumulation and intermediate images |
Reduction expands the full sampling window. The implementation does not replace it with repeated smaller resizes or an area/bilinear prefilter. Coordinate calculation uses integer quotient/remainder decomposition to preserve local fractional positions at large image coordinates. Fused multiply-add and parallel reductions can change final rounding; bitwise agreement with other implementations is not promised.
The sampling conventions correspond to Pillow's floating single-channel Lanczos path. Pillow's uint8 path includes intermediate quantization/clipping and is not a strict floating-point reference. Disabling antialiasing changes the reduction filter and can produce aliasing.
Scale-aware execution
| Workload | Execution strategy |
|---|---|
| Identity / one unchanged axis | Copy / filter only the changing axis |
| Windows up to 32 samples | Unrolled sampling, horizontal row reuse, shared vertical row weights |
| Wider reduction windows | Parallel, chunked reductions over every valid sample |
| Extreme reduction | Bound support to available input; process it in chunks |
| Singleton width | Reuse contiguous horizontal filtering for the vertical axis |
| Mixed / unequal axis scales | Independent weights; choose the smaller intermediate image |
| Repeated geometry | Reuse weights; optional autotuning changes layout, not the filter |
Weights are stored by sample offset and output position for contiguous
horizontal access. With horizontal-first execution, work is approximately
N*C*(IH*OW*Kx + OH*OW*Ky). Memory includes the float32 intermediate and
weight tables; noncontiguous input adds a contiguous copy. There is no global
GPU weight cache. A Resizer owns its tables, whose reuse/freeing follows
CUDA stream lifetimes and PyTorch's allocator.
Image sizes are limited by device memory and int32 element indexing capacity.
Run your own benchmarks
python -m pip install -e ".[test]"
# Validate 14 scale families from a 2160×3840 input, without timing.
python benchmarks/benchmark.py --suite --check-only
# Time ordinary calls and prepared/autotuned calls separately.
python benchmarks/benchmark.py --suite --autotune
python benchmarks/benchmark.py --input 2160 3840 --output 1537 2731 --dtype float16
# Warm CUDA Graph execution, excluding per-call Python dispatch.
python benchmarks/benchmark.py --input 1080 1920 --output 2160 3840 --autotune --timing graph
# Optional trusted local comparator exposing the same resize API.
python benchmarks/benchmark.py --compare /path/to/reference_lanczos.py
The suite covers integer/fractional enlargement and reduction, near-identity
sizes, strong reduction, one-axis changes, both mixed directions and 1×1
output. Defaults are batch=1, RGB and float32. Use --help for batch,
channels, dtype, antialiasing and timing options. Results print to stdout;
no dataset is downloaded or result file written automatically.
Every Lanczos method first checks output shape and finiteness. Boundary and interior samples from the first batch/channel are compared against independent CPU float64 direct convolution. The test suite additionally checks complete small multichannel outputs, Pillow float references, large coordinates, constants, checkerboards, impulses, edges and chirps.
Timing reports warm median device latency. resize includes weight generation;
prepared excludes construction and autotuning. Neither includes first JIT,
image I/O or CPU/GPU transfers. CUDA event/graph timing is not end-to-end
wall-clock latency. Keep GPU load and inputs consistent, and report cold-start
costs separately. --alternatives adds PyTorch bicubic/bilinear as different
filters; their timings do not establish a speedup over another Lanczos implementation.
Tests
python -m pip install -e ".[test]"
pytest -q tests/test_api.py # CPU contracts
pytest -q # includes actual GPU tests when available
Independent floating references use atol=rtol=2e-5; tests also cover
noncontiguous input, supported dtypes, streams, CUDA Graphs and autotuning.
GPU tests skip on CPU-only machines.
License
MIT. See LICENSE. The documentation photograph has separate provenance in assets/README.md.
Publishing
Version tags automatically build and publish to PyPI after CI passes. See RELEASING.md for one-time Trusted Publisher setup and release steps.
Metadata
Release files for lanczos-triton 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lanczos_triton-0.1.0.tar.gz | 674.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lanczos_triton-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 685.9 kB
Release files / lanczos_triton-0.1.0.tar.gz
| Download URL | lanczos_triton-0.1.0.tar.gz |
|---|---|
| Size | 674.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6db5a46f9538a18a62fcea82b497f8720b1e3d75ff3433357544cc8d66921050
|
|
BLAKE2b-256 checksum How to use checksums |
65d6b86e5fd60229ff2baab1d0d716b8bbd38b46eda9cd355770e7ffad1865fe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 15, 2026.
Transparency logRelease files / lanczos_triton-0.1.0-py3-none-any.whl
| Download URL | lanczos_triton-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
55ae95ca6e982666c06d4b511e2c8e4728915ad211a362d57ebf859e560d543b
|
|
BLAKE2b-256 checksum How to use checksums |
e80634fd6b83fa44349cd4f3241fad6562edf9da3292a608c67833612372d0a5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 15, 2026.
Transparency log