cupy / cupy/cupy

`cupyx.scipy.sparse.linalg.splu` solve is slower than `scipy` equivalent

Open
#8,580 9 comments 0 reactions 0 assignees View on GitHub
cat:performance prio:medium
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.