Skip to content

Commit bd5928d

Browse files
committed
Working cupy methods (power method and eighs)
1 parent 67643a1 commit bd5928d

File tree

10 files changed

+43
-24
lines changed

10 files changed

+43
-24
lines changed

.github/workflows/docs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ on:
55
branches:
66
- main
77
- final_project
8+
- gpu_branch
89

910
pull_request:
1011
branches:
1112
- main
1213
- final_project
14+
- gpu_branch
1315

1416
jobs:
1517
docs:

.github/workflows/formatter.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ on:
55
branches:
66
- main
77
- final_project
8+
- gpu_branch
89

910
pull_request:
1011
branches:
1112
- main
1213
- final_project
14+
- gpu_branch
1315

1416
jobs:
1517
linter:

.github/workflows/tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ jobs:
2323
steps:
2424
- uses: actions/checkout@v3
2525

26+
- name: Install system dependencies
27+
run: |
28+
apt-get update && apt-get install -y python3-venv python3-pip
29+
2630
- name: Install additional dependencies
2731
run: |
2832
python3 -m venv venv

experiments/config.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
dimension: 1000
2-
1+
dim: 1000
32
density: 0.1
3+
tol: 0.001
4+
max_iter: 100

scripts/run.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525

2626

2727
kwargs = read_config(filename)
28-
dim = kwargs["dimension"]
28+
dim = kwargs["dim"]
2929
density = kwargs["density"]
30+
# also tol and max iter
3031

3132

3233
matrix = sp.random(dim, dim, density=density, format="csr")

shell/submit.sbatch

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ export SLURM_NTASKS_PER_NODE=1 # due to Ulysses's bug
2929
module load cuda/12.1
3030
conda init
3131
source ~/.bashrc
32-
conda activate ~/miniconda3/envs/devtools_scicomp
33-
pip install cupy-cuda12x
34-
python -m pip freeze > requirements.txt
35-
# Run the script
32+
conda activate /scratch/ltomada/miniconda3/envs/devtools_scicomp
33+
python -m pytest -v
3634
#python scripts/run.py fit --config=experiments/config.yaml

src/pyclassify/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"eigenvalues_cp",
55
"power_method",
66
"power_method_numba",
7+
"power_method_cp",
78
]
89

910
from .eigenvalues import (
@@ -12,4 +13,5 @@
1213
eigenvalues_cp,
1314
power_method,
1415
power_method_numba,
16+
power_method_cp,
1517
)

src/pyclassify/eigenvalues.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
cp.cuda.Device(0)
99
import cupy.linalg as cpla
1010
import cupyx.scipy.sparse as cpsp
11+
from cupyx.scipy.sparse.linalg._eigen import eigsh as cp_eigsh
1112

1213

1314
@profile
@@ -60,21 +61,29 @@ def eigenvalues_sp(A, symmetric=True):
6061
"""
6162
check_square_matrix(A)
6263
eigenvalues, _ = (
63-
spla.eigsh(A, k=A.shape[0] - 1)
64+
sp.linalg.eigsh(A, k=A.shape[0] - 1)
6465
if symmetric
65-
else spla.eigs(A, k=A.shape[0] - 1)
66+
else sp.linalg.eigs(A, k=A.shape[0] - 1)
6667
)
6768
return eigenvalues
6869

6970

7071
@profile
7172
def eigenvalues_cp(A):
72-
"""
73+
r"""
7374
Compute the eigenvalues of a sparse matrix using CuPy's `eigsh` function.
7475
7576
This function checks if the input matrix is square and symmetric, then computes its eigenvalues using
76-
CupY's sparse linear algebra solvers. For symmetric matrices, it uses `eigsh` for
77-
more efficient computation.
77+
CuPy's sparse linear algebra solvers. It uses `eigsh` for more efficient computation.
78+
IMPORTANT: it important to underline a couple of things regarding this function:
79+
- installing using the command
80+
.. code-block:: shell
81+
82+
python -m pip install cupy-cuda12x
83+
does not allow, for some reason, to import cupyx.scipy.sparse.linalg, and it necessary to import the
84+
function manually form the source code.
85+
- the eighs function in this case does not allow to compute *all* the eigenvalues, but only a number
86+
$m<n$, so here just a reduced portion is computed (starting form the ones which are greater in magnitude).
7887
7988
Args:
8089
A (cpsp.spmatrix): A square sparse matrix whose eigenvalues are to be computed.
@@ -87,7 +96,8 @@ def eigenvalues_cp(A):
8796
ValueError: If number of rows != number of columns.
8897
"""
8998
check_symm_square(A)
90-
eigenvalues, _ = cpla.eigsh(A, k=A.shape[0] - 1)
99+
k = 5 if A.shape[0] > 5 else A.shape[0] - 2
100+
eigenvalues, _ = cp_eigsh(A, k=k)
91101
return eigenvalues
92102

93103

src/pyclassify/utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313

1414
def check_square_matrix(A):
1515
"""
16-
Checks if the input matrix is a square matrix of type NumPy ndarray or SciPy sparse matrix.
16+
Checks if the input matrix is a square matrix of type NumPy ndarray or SciPy or CuPy sparse matrix.
1717
This is done to ensure that the input matrix `A` is both:
18-
1. Of type `np.ndarray` (NumPy array) or `scipy.sparse.spmatrix` (SciPy sparse matrix) or 'cupyx.scipy.sparse.spmatrix'.
18+
1. Of type `np.ndarray` (NumPy array) or `scipy.sparse.spmatrix` (SciPy sparse matrix) or 'cupyx.scipy.sparse.spmatrix' (CuPy sparse matrix).
1919
2. A square matrix.
2020
2121
Args:
@@ -72,7 +72,7 @@ def check_symm_square(A):
7272
check_square_matrix(A)
7373
if isinstance(A, sp.spmatrix) and not np.allclose(A.toarray(), A.toarray().T):
7474
raise ValueError("Matrix must be symmetric!")
75-
elif isinstance(A, cpsp.spmatrix) and not cp.allclose(A.get(), A.get().T):
75+
elif isinstance(A, cpsp.spmatrix) and not cp.allclose(A.toarray(), A.toarray().T):
7676
raise ValueError("Matrix must be symmetric!")
7777

7878

test/test_.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import numpy as np
22
import scipy.sparse as sp
3-
import cupy as cp
4-
import os
5-
os.environ["CUPY_ACCELERATORS"] = "cub"
6-
cp.use_default_memory_pool = False
73
import cupyx.scipy.sparse as cpsp
84
import pytest
95
from pyclassify import (
@@ -12,6 +8,7 @@
128
eigenvalues_cp,
139
power_method,
1410
power_method_numba,
11+
power_method_cp,
1512
)
1613
from pyclassify.utils import check_square_matrix, make_symmetric, check_symm_square
1714

@@ -83,8 +80,10 @@ def test_implementations_power_method(size, density):
8380

8481
biggest_eigenvalue_pm = power_method(matrix)
8582
biggest_eigenvalue_pm_numba = power_method_numba(matrix.toarray())
83+
biggest_eigenvalue_pm_cp = power_method_cp(cp_matrix)
8684

87-
assert np.isclose(biggest_eigenvalue_np, biggest_eigenvalue_sp, rtol=1e-4)
88-
assert np.isclose(biggest_eigenvalue_pm, biggest_eigenvalue_sp, rtol=1e-4)
89-
assert np.isclose(biggest_eigenvalue_cp, biggest_eigenvalue_sp, rtol=1e-4)
90-
assert np.isclose(biggest_eigenvalue_pm_numba, biggest_eigenvalue_sp, rtol=1e-4)
85+
assert np.isclose(biggest_eigenvalue_np, biggest_eigenvalue_sp, rtol=1e-4) # ensure numpy and scipy implementations are consistent
86+
assert np.isclose(biggest_eigenvalue_cp, biggest_eigenvalue_sp, rtol=1e-4) # ensure cupy and scipy implementations are consistent
87+
assert np.isclose(biggest_eigenvalue_pm, biggest_eigenvalue_sp, rtol=1e-4) # ensure power method and scipy implementation are consistent
88+
assert np.isclose(biggest_eigenvalue_pm_numba, biggest_eigenvalue_sp, rtol=1e-4) # ensure numba power method and scipy implementation are consistent
89+
assert np.isclose(biggest_eigenvalue_pm_cp, biggest_eigenvalue_sp, rtol=1e-4) # ensure cupy power method and scipy implementation are consistent

0 commit comments

Comments
 (0)