馃悰 Describe the bug
Issue
torchvision.transforms.v2.ElasticTransform applies a Gaussian blur on the sampled displacement field to achieve a smooth deformation. The degree of smoothing is controlled by a parameter sigma.
The current implementation is fast enough for images up to a size of roughly 256 x 256, where a sigma of 10.0 already achieves a strong deformation.
Higher image resolutions will require larger sigmas to achieve a similarly strong effect. In this case, the Gaussian filter kernel becomes large and the operation quite time-consuming (multiple seconds per image).
Larger images are not uncommon anymore nowadays. For example, SAM 3 uses a resolution of 1008 x 1008 for training.
The following are timings for ElasticTransform.make_params for an image size of 1008 x 1008 and different values of sigma:
| Sigma |
Runtime |
| 5.0 |
49 ms |
| 10.0 |
142 ms |
| 20.0 |
575 ms |
| 30.0 |
1210 ms |
| 40.0 |
2370 ms |
| 50.0 |
3310 ms |
Code to reproduce
from timeit import timeit
import torch
from torchvision.transforms.v2 import ElasticTransform
dummy_input = torch.rand(3, 1008, 1008)
transform = ElasticTransform(sigma=40.0)
nruns = 3
time = timeit("transform.make_params([dummy_input])", number=nruns, globals=globals())
print(time / nruns)
Possible solution
This speed issue could easily be solved by using a separable Gaussian filter for smoothing the displacement field. I will open a PR implementing this solution.
Versions
PyTorch version: 2.13.0+cu130
Is debug build: False
CUDA used to build PyTorch: 13.0
ROCM used to build PyTorch: N/A
OS: Ubuntu 24.04.4 LTS (x86_64)
GCC version: (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
Clang version: Could not collect
CMake version: version 3.28.3
Libc version: glibc-2.39
Python version: 3.12.11 | packaged by Anaconda, Inc. | (main, Jun 5 2025, 13:09:17) [GCC 11.2.0] (64-bit runtime)
Python platform: Linux-6.17.0-35-generic-x86_64-with-glibc2.39
Is CUDA available: True
CUDA runtime version: 13.0.88
CUDA_MODULE_LOADING set to:
GPU models and configuration:
GPU 0: NVIDIA GeForce RTX 5090
GPU 1: NVIDIA RTX A400
Nvidia driver version: 580.95.05
cuDNN version: Could not collect
Is XPU available: False
HIP runtime version: N/A
MIOpen runtime version: N/A
Is XNNPACK available: False
Caching allocator config: N/A
CPU:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Address sizes: 48 bits physical, 48 bits virtual
Byte Order: Little Endian
CPU(s): 24
On-line CPU(s) list: 0-23
Vendor ID: AuthenticAMD
Model name: AMD Ryzen 9 9900X 12-Core Processor
CPU family: 26
Model: 68
Thread(s) per core: 2
Core(s) per socket: 12
Socket(s): 1
Stepping: 0
Frequency boost: enabled
CPU(s) scaling MHz: 96%
CPU max MHz: 5662.0161
CPU min MHz: 613.9540
BogoMIPS: 8782.91
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good amd_lbr_v2 nopl xtopology nonstop_tsc cpuid extd_apicid aperfmperf rapl pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpuid_fault cpb cat_l3 cdp_l3 hw_pstate ssbd mba perfmon_v2 ibrs ibpb stibp ibrs_enhanced vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm rdt_a avx512f avx512dq adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local user_shstk avx_vnni avx512_bf16 clzero irperf xsaveerptr rdpru wbnoinvd cppc arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif x2avic v_spec_ctrl vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid bus_lock_detect movdiri movdir64b overflow_recov succor smca fsrm avx512_vp2intersect flush_l1d amd_lbr_pmc_freeze
Virtualization: AMD-V
L1d cache: 576 KiB (12 instances)
L1i cache: 384 KiB (12 instances)
L2 cache: 12 MiB (12 instances)
L3 cache: 64 MiB (2 instances)
NUMA node(s): 1
NUMA node0 CPU(s): 0-23
Vulnerability Gather data sampling: Not affected
Vulnerability Ghostwrite: Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Old microcode: Not affected
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Not affected
Vulnerability Spec rstack overflow: Mitigation; IBPB on VMEXIT only
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2: Mitigation; Enhanced / Automatic IBRS; IBPB conditional; STIBP always-on; PBRSB-eIBRS Not affected; BHI Not affected
Vulnerability Srbds: Not affected
Vulnerability Tsa: Not affected
Vulnerability Tsx async abort: Not affected
Vulnerability Vmscape: Mitigation; IBPB on VMEXIT
Versions of relevant libraries:
[pip3] flake8==7.3.0
[pip3] mypy==1.18.2
[pip3] mypy_extensions==1.1.0
[pip3] numpy==2.3.3
[pip3] nvidia-cublas==13.1.1.3
[pip3] nvidia-cublas-cu12==12.8.4.1
[pip3] nvidia-cuda-cupti==13.0.85
[pip3] nvidia-cuda-nvrtc==13.0.88
[pip3] nvidia-cuda-runtime==13.0.96
[pip3] nvidia-cudnn-cu13==9.20.0.48
[pip3] nvidia-cufft==12.0.0.61
[pip3] nvidia-cufft-cu12==11.3.3.83
[pip3] nvidia-curand==10.4.0.35
[pip3] nvidia-curand-cu12==10.3.9.90
[pip3] nvidia-cusolver==12.0.4.66
[pip3] nvidia-cusolver-cu12==11.7.3.90
[pip3] nvidia-cusparse==12.6.3.3
[pip3] nvidia-cusparse-cu12==12.5.8.93
[pip3] nvidia-cusparselt-cu12==0.7.1
[pip3] nvidia-cusparselt-cu13==0.8.1
[pip3] nvidia-nccl-cu12==2.27.5
[pip3] nvidia-nccl-cu13==2.29.7
[pip3] nvidia-nvjitlink==13.3.33
[pip3] nvidia-nvjitlink-cu12==12.8.93
[pip3] nvidia-nvtx==13.0.85
[pip3] nvidia-nvtx-cu12==12.8.90
[pip3] torch==2.13.0
[pip3] torchvision==0.29.0a0+10f68db
[pip3] triton==3.7.1
[conda] cuda-cudart 13.0.96 h7354ed3_0
[conda] cuda-cudart-dev 13.0.96 h7354ed3_0
[conda] cuda-cudart-dev_linux-64 13.0.96 hfb20e49_0
[conda] cuda-cudart-static 13.0.96 h7354ed3_0
[conda] cuda-cudart-static_linux-64 13.0.96 hfb20e49_0
[conda] cuda-cudart_linux-64 13.0.96 hfb20e49_0
[conda] cuda-cupti 13.0.85 h7354ed3_0
[conda] cuda-cupti-dev 13.0.85 h7354ed3_0
[conda] cuda-libraries 13.0.3 h06a4308_0
[conda] cuda-libraries-dev 13.0.3 h06a4308_0
[conda] cuda-nvrtc 13.0.88 h7354ed3_0
[conda] cuda-nvrtc-dev 13.0.88 h7354ed3_0
[conda] cuda-nvtx 13.0.85 h7354ed3_0
[conda] cuda-opencl 13.0.85 h6334c1c_0
[conda] cuda-opencl-dev 13.0.85 h7354ed3_0
[conda] libcublas 13.1.1.3 h7354ed3_0
[conda] libcublas-dev 13.1.1.3 h7354ed3_0
[conda] libcufft 12.0.0.61 h7354ed3_0
[conda] libcufft-dev 12.0.0.61 h7354ed3_0
[conda] libcurand 10.4.0.35 h7354ed3_0
[conda] libcurand-dev 10.4.0.35 h7354ed3_0
[conda] libcusolver 12.0.4.66 h7354ed3_0
[conda] libcusolver-dev 12.0.4.66 h7354ed3_0
[conda] libcusparse 12.6.3.3 h7354ed3_0
[conda] libcusparse-dev 12.6.3.3 h7354ed3_0
[conda] libjpeg-turbo 2.0.0 h9bf148f_0 pytorch
[conda] libnvjitlink 13.0.88 h7354ed3_0
[conda] libnvjitlink-dev 13.0.88 h7354ed3_0
[conda] numpy 2.3.3 pypi_0 pypi
[conda] nvidia-cublas 13.1.1.3 pypi_0 pypi
[conda] nvidia-cublas-cu12 12.8.4.1 pypi_0 pypi
[conda] nvidia-cuda-cupti 13.0.85 pypi_0 pypi
[conda] nvidia-cuda-nvrtc 13.0.88 pypi_0 pypi
[conda] nvidia-cuda-runtime 13.0.96 pypi_0 pypi
[conda] nvidia-cudnn-cu13 9.20.0.48 pypi_0 pypi
[conda] nvidia-cufft 12.0.0.61 pypi_0 pypi
[conda] nvidia-cufft-cu12 11.3.3.83 pypi_0 pypi
[conda] nvidia-curand 10.4.0.35 pypi_0 pypi
[conda] nvidia-curand-cu12 10.3.9.90 pypi_0 pypi
[conda] nvidia-cusolver 12.0.4.66 pypi_0 pypi
[conda] nvidia-cusolver-cu12 11.7.3.90 pypi_0 pypi
[conda] nvidia-cusparse 12.6.3.3 pypi_0 pypi
[conda] nvidia-cusparse-cu12 12.5.8.93 pypi_0 pypi
[conda] nvidia-cusparselt-cu12 0.7.1 pypi_0 pypi
[conda] nvidia-cusparselt-cu13 0.8.1 pypi_0 pypi
[conda] nvidia-nccl-cu12 2.27.5 pypi_0 pypi
[conda] nvidia-nccl-cu13 2.29.7 pypi_0 pypi
[conda] nvidia-nvjitlink 13.3.33 pypi_0 pypi
[conda] nvidia-nvjitlink-cu12 12.8.93 pypi_0 pypi
[conda] nvidia-nvtx 13.0.85 pypi_0 pypi
[conda] nvidia-nvtx-cu12 12.8.90 pypi_0 pypi
[conda] torch 2.13.0 pypi_0 pypi
[conda] torchvision 0.29.0a0+10f68db pypi_0 pypi
[conda] triton 3.7.1 pypi_0 pypi
馃悰 Describe the bug
Issue
torchvision.transforms.v2.ElasticTransformapplies a Gaussian blur on the sampled displacement field to achieve a smooth deformation. The degree of smoothing is controlled by a parametersigma.The current implementation is fast enough for images up to a size of roughly 256 x 256, where a sigma of 10.0 already achieves a strong deformation.
Higher image resolutions will require larger sigmas to achieve a similarly strong effect. In this case, the Gaussian filter kernel becomes large and the operation quite time-consuming (multiple seconds per image).
Larger images are not uncommon anymore nowadays. For example, SAM 3 uses a resolution of 1008 x 1008 for training.
The following are timings for
ElasticTransform.make_paramsfor an image size of 1008 x 1008 and different values of sigma:Code to reproduce
Possible solution
This speed issue could easily be solved by using a separable Gaussian filter for smoothing the displacement field. I will open a PR implementing this solution.
Versions