SymPy-to-Torch Transcompilation for Massively Batched, GPU-Accelerated Numerical Integration
TorchSymPy solves a fundamental bottleneck in computational science: evaluating parameterized integrals over massive parameter grids is prohibitively slow with traditional scalar methods.
When analyzing physics models, optics, or machine learning objectives, analytical integrals often must be computed across dense meshes containing millions of points. Standard solvers like SciPy process these sequentially on the CPU, which can take hours. TorchSymPy addresses this by bridging the gap between exact symbolic mathematics (SymPy) and parallel GPU execution (PyTorch). It takes symbolic integral expressions, performs structural optimizations, and automatically transcompiles them into native, highly optimized PyTorch kernels. Through this "compile-once, evaluate-many" architecture, you achieve zero-overhead numerical evaluation across enormous parameter sweeps—regularly executing thousands of times faster than standard numerical libraries.
Note: this module was first developed for libphysics — then split out into a standalone library to tackle generalized parallel computational bottlenecks in integration.
When working with analytical integrals in computational physics, optics, or machine learning, researchers often hit performance bottlenecks:
- SymPy is great for exact mathematical manipulation but is painfully slow (or completely fails) for heavy numerical grid evaluations.
- SciPy (e.g.,
scipy.integrate.quad) is highly accurate but inherently sequential, single-threaded, and cannot natively leverage GPUs. - PyTorch thrives on massively parallel grid evaluations, but writing structural integrators by hand is tedious and error-prone.
TorchSymPy gives you the best of all worlds. You write the math symbolically in SymPy, and TorchSymPy applies automated changes-of-variables (to handle infinite domains) and structural optimizations before transpiling it into highly optimized TorchExpr kernels. These kernels can run up to 3,400x faster than SciPy by leveraging tensor-product grids and batched GPU execution.
To install the latest stable version from PyPI:
pip install torchsympyTo install from source (development):
git clone https://github.com/ibeuler/TorchSymPy.git
cd TorchSymPy
pip install -e .Note on PyTorch: For GPU acceleration, ensure you have a CUDA-compatible
torchwheel installed (e.g.,torch==2.5.1+cu121).
The easiest path from a symbolic integral to a batched GPU evaluation:
import torch
import torchsympy
import sympy as sp
# 1. Define your integrand symbolically
x = sp.Symbol("x", real=True)
p = sp.Symbol("p", real=True)
expr = sp.Integral(sp.exp(-p * x**2), (x, -sp.oo, sp.oo))
# 2. Compile to a TorchSymPy engine
lt = torchsympy.TorchSymPy()
texpr = lt.torchify(expr)
# 3. Evaluate massively batched parameter grids on accelerators
p_grid = torch.linspace(0.5, 100.0, 10000, dtype=torch.float64, device="cuda").unsqueeze(-1)
re, im = texpr.torch_integrate_batched(
params_values=p_grid,
method="gauss-legendre",
N=501, # Quadrature nodes
device="cuda", # Target accelerator
dtype=torch.float64,
chunk_size_params=4096 # Safely chunk massive batches to avoid OOM
)
print(f"Real part shape: {re.shape}") # Output: torch.Size([10000])Once you define a symbolic integration expression, TorchSymPy provides distinct evaluation paths tailored to your mathematical structure and parameter scale:
This is the recommended high-level entry point. It traverses the SymPy expression tree and detects mathematical structures that can be vastly optimized. For instance, in highly oscillatory multi-dimensional integrals (like Fresnel diffraction), it automatically factors the problem into a separable path, avoiding the catastrophic
The workhorse for small-to-large deterministic parameter sweeps. This backend natively implements PyTorch tensor-product rules (Gauss-Legendre, Simpson). It features zero setup overhead (
Delegates evaluation entirely to the external torchquad library. It uses dynamic PyTorch broadcasting to avoid creating dense parameter meshgrids in memory. However, because it dynamically instantiates IntegrationGrid objects and performs an
TorchSymPy evaluates parameterized integrals across vast grids immensely faster than traditional methods. In our benchmark suite evaluating a parameterized Damped Cosine
The following table demonstrates the inherent trade-off between quadrature resolution (
| Execution | Time per Point | Speedup vs SciPy | Accuracy (vs Analytical) |
|---|---|---|---|
| SciPy (nquad) | 1.29816 ms | 1.0x | |
| TorchSymPy (Vectorized, N=121) | 0.00056 ms | 2,320x |
|
| TorchSymPy (Batched, N=121) | 0.00030 ms | 4,264x |
|
| TorchSymPy (Vectorized, N=2001) | 0.00970 ms | 138x |
|
| TorchSymPy (Batched, N=2001) | 0.00545 ms | 245x |
|
| TorchSymPy (Vectorized, N=5001) | 0.02904 ms | 42x |
|
| TorchSymPy (Batched, N=5001) | 0.01382 ms | 90x |
|
(Benchmarks run on an NVIDIA RTX GPU across a 10,000 parameter grid. TorchSymPy converges to parity with SciPy while remaining orders of magnitude faster at standard resolutions).
While TorchSymPy achieves numeric parity with SciPy for well-behaved integrals (like
Consider the famously difficult oscillatory integral:
The true, analytical exact value (calculated symbolically via SymPy hypergeometric functions) is 0.873084. However, if we force pure numerical evaluation without symbolic reduction:
| Method | Output Value | Absolute Error | Notes |
|---|---|---|---|
| SymPy (True Analytical) | 0.873084 |
0.0 | Solved symbolically via Hypergeometric functions |
SymPy (Pure evalf()) |
-4.000000 |
4.873 |
Completely fails convergence natively |
SciPy (nquad) |
1.550175 |
0.677 |
Fails with IntegrationWarning (Divergent) |
TorchSymPy (GaussLegendre) |
-1.343219 |
2.216 |
Breaks due to mapped infinite oscillations |
Takeaway: TorchSymPy provides incredible performance scaling and accurate results matching SciPy on standard mapping domains. However, for pathological integrands (like conditionally convergent oscillations at infinity), you should rely on SymPy's exact symbolic analytical integrations before attempting numerical grid sweeps.
When evaluating integrals in high dimensions (TorchSymPy natively supports MonteCarlo sampling through its vectorized backend to overcome this.
For example, evaluating an 8-Dimensional Gaussian Integral
| Method (8D Gaussian) | Output Value | Analytical Truth ( |
|---|---|---|
| TorchSymPy (MonteCarlo) | 97.5273 |
97.4090 |
| TorchSymPy (GaussLegendre) | 89.9769 |
97.4090 |
At this dimensionality, Monte Carlo successfully approximates the integral within $\sim 0.1%$ error, while deterministic grids severely degrade given the exact same computational budget.
pytest tests/ -vCheck the examples/ directory for specific physics applications and basic integration usage, including generating Wigner functions.
Distributed under the MIT License. See LICENSE for more information.