`cupyx.scipy.sparse.linalg.splu` solve is slower than `scipy` equivalent
- Dominant language
- Python
- Stars
- 12.3k
- Forks
- 1.1k
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 45
Description
### Description
While using `cupyx.scipy.sparse.linalg.splu`, I noticed that subsequent `solve()` steps using the `SuperLU` result returned from `cupyx.scipy.sparse.linalg.splu` are a lot slower (~120x slower in the example below) than the equivalent `scipy` operation on the CPU.
### To Reproduce
Here's the `scipy` version (note I'm using the ipython/jupyter `%time` magic for timing the `linalg.splu` and `.solve` lines):
```py
import numpy as np
from scipy.sparse import random, csc_matrix
from scipy.sparse import linalg
size = 10_000
A = random(size, size, density=0.5, random_state=2)
A = csc_matrix(A)
x = np.random.default_rng(seed=2).random(size)
%time B = linalg.splu(A) # 1min 10s
%time result = B.solve(x) # 81.5 ms
```
The output here gives a runtime of 1min 10s for the `B = linalg.splu(A)` line and 81.5 ms for the `result = B.solve(x)` line.
Switching to the equivalent `cupy` version:
```python
import cupy as cp
from cupyx.scipy.sparse import random, csc_matrix
from cupyx.scipy.sparse import linalg
size = 10_000
A = random(size, size, density=0.5, random_state=2)
A = csc_matrix(A)
x = cp.random.default_rng(seed=2).random(size)
%time B = linalg.splu(A) # 1min 15s
%time result = B.solve(x) # 9.86 s
```
In this case, the `B = linalg.splu(A)` line takes ~1min 15s , which is similar to the `scipy` CPU version. This is expected as the docs https://docs.cupy.dev/en/stable/reference/generated/cupyx.scipy.sparse.linalg.splu.html say that this step actually just happens on the CPU with `scipy` anyways. What's surprising is the `result = B.solve(x)` line, which happens on the GPU, takes 9.86 s, which much slower (~120x slower) than the equivalent `scipy` step.
### Installation
Conda-Forge (`conda install ...`)
### Environment
```
OS : Linux-5.15.0-1068-aws-x86_64-with-glibc2.36
Python Version : 3.10.14
CuPy Version : 13.2.0
CuPy Platform : NVIDIA CUDA
NumPy Version : 1.26.4
SciPy Version : 1.14.1
Cython Build Version : 0.29.37
Cython Runtime Version : None
CUDA Root : None
nvcc PATH : None
CUDA Build Version : 12050
CUDA Driver Version : 12060
CUDA Runtime Version : 12050 (linked to CuPy) / RuntimeError('CuPy failed to load libcudart.so.12: OSError: libcudart.so.12: cannot open shared object file: No such file or directory') (locally installed)
cuBLAS Version : (available)
cuFFT Version : 11206
cuRAND Version : 10307
cuSOLVER Version : (11, 6, 4)
cuSPARSE Version : (available)
NVRTC Version : (12, 6)
Thrust Version : 200400
CUB Build Version : 200200
Jitify Build Version :
cuDNN Build Version : None
cuDNN Version : None
NCCL Build Version : None
NCCL Runtime Version : None
cuTENSOR Version : None
cuSPARSELt Build Version : None
Device 0 Name : NVIDIA A10G
Device 0 Compute Capability : 86
Device 0 PCI Bus ID : 0000:00:1E.0
```
### Additional Information
_No response_
Contributor guide
Research direction
Start by reproducing the supplied CuPy/SciPy benchmark at the cupyx.scipy.sparse.linalg.splu entry point, then inspect the SuperLU result's solve path. Compare the factorization handoff and GPU solve timings; done means the reported solve slowdown is explained and addressed with regression coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100