Skip to content

Commit af923e5

Browse files
committed
Comment cupy functions, add todo list, add tests, add secular function
1 parent 3115386 commit af923e5

File tree

13 files changed

+455
-135
lines changed

13 files changed

+455
-135
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,12 @@ Names: Lorenzo Tomada, Gaspare Li Causi
33
email: ltomada@sissa.it, glicausi@sissa.it
44

55
This repository contains the final project for the course in Development Tools in Scientific Computing.
6+
7+
8+
TO DO:
9+
1) Integrate the new code in the parallel solver
10+
2) Profile runtime and memory usage, saving the results and plotting
11+
3) Runtime vs matrix size comparison (follow in detail the instructions on the course repo)
12+
4) Accuracy vs efficiency
13+
5) Script to run on Ulysses
14+
6) Add missing tests

requirements.txt

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,44 @@
11
alabaster==1.0.0
2-
asttokens==3.0.0
32
babel==2.17.0
43
black==25.1.0
54
certifi==2025.1.31
65
charset-normalizer==3.4.1
76
click==8.1.8
87
contourpy==1.3.1
9-
cupy-cuda12x==13.4.0
108
cycler==0.12.1
11-
decorator==5.2.1
12-
distro==1.9.0
139
docutils==0.21.2
1410
exceptiongroup==1.2.2
15-
executing==2.2.0
16-
fastrlock==0.8.3
1711
fonttools==4.56.0
1812
idna==3.10
1913
imagesize==1.4.1
2014
iniconfig==2.0.0
21-
ipython==8.33.0
22-
ipython_pygments_lexers==1.1.1
23-
jedi==0.19.2
2415
Jinja2==3.1.5
2516
kiwisolver==1.4.8
2617
line_profiler==4.2.0
2718
llvmlite==0.44.0
2819
MarkupSafe==3.0.2
2920
matplotlib==3.10.0
30-
matplotlib-inline==0.1.7
3121
memory-profiler==0.61.0
3222
mypy-extensions==1.0.0
3323
numba==0.61.0
3424
numpy==2.1.3
35-
nvprof==0.2
3625
packaging==24.2
3726
pandas==2.2.3
38-
parso==0.8.4
3927
pathspec==0.12.1
40-
pexpect==4.9.0
4128
pillow==11.1.0
4229
platformdirs==4.3.6
4330
pluggy==1.5.0
44-
prompt_toolkit==3.0.50
4531
psutil==7.0.0
46-
ptyprocess==0.7.0
47-
pure_eval==0.2.3
4832
pybind11==2.13.6
4933
Pygments==2.19.1
5034
pyparsing==3.2.1
5135
pytest==8.3.4
5236
python-dateutil==2.9.0.post0
53-
pytz==2025.1
37+
pytz==2025.2
5438
PyYAML==6.0.2
5539
requests==2.32.3
56-
roman-numerals-py==3.1.0
57-
scikit-build==0.18.1
5840
scipy==1.15.2
59-
setuptools==75.8.0
41+
setuptools==78.1.1
6042
six==1.17.0
6143
snowballstemmer==2.2.0
6244
Sphinx==8.1.3
@@ -68,12 +50,8 @@ sphinxcontrib-jquery==4.1
6850
sphinxcontrib-jsmath==1.0.1
6951
sphinxcontrib-qthelp==2.0.0
7052
sphinxcontrib-serializinghtml==2.0.0
71-
stack-data==0.6.3
72-
tokenize_rt==6.1.0
7353
tomli==2.2.1
74-
traitlets==5.14.3
7554
typing_extensions==4.12.2
76-
tzdata==2025.1
55+
tzdata==2025.2
7756
urllib3==2.3.0
78-
wcwidth==0.2.13
7957
wheel==0.45.1

scripts/profiling.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@
33
from pyclassify import (
44
eigenvalues_np,
55
eigenvalues_sp,
6-
#eigenvalues_cp,
6+
# eigenvalues_cp,
77
power_method,
88
power_method_numba,
9-
#power_method_cp,
9+
# power_method_cp,
1010
QR,
11-
#QR_cp,
11+
# QR_cp,
1212
)
1313
from pyclassify.utils import (
1414
make_symmetric,
1515
read_config,
1616
profile_with_cprofile,
17-
#profile_with_cupy_profiler,
17+
# profile_with_cupy_profiler,
1818
)
1919
import numpy as np
2020
import scipy.sparse as sp
@@ -25,7 +25,7 @@
2525

2626
seed = 8422
2727
random.seed(seed)
28-
#cp.random.seed(seed)
28+
# cp.random.seed(seed)
2929
np.random.seed(seed)
3030

3131

@@ -51,7 +51,7 @@
5151
A = U @ A @ U.T
5252
A = make_symmetric(A)
5353
A = sp.csr_matrix(A)
54-
#A_cp = cpsp.csr_matrix(A)
54+
# A_cp = cpsp.csr_matrix(A)
5555

5656

5757
log_file = "./logs/timings.csv"
@@ -73,6 +73,6 @@
7373
)
7474

7575

76-
#profile_with_cupy_profiler(log_file, dim, "eigenvalues_cp", eigenvalues_cp, A_cp)
77-
#profile_with_cupy_profiler(log_file, dim, "power_method_cp", power_method_cp, A_cp)
78-
#profile_with_cupy_profiler(log_file, dim, "QR_cp", QR_cp, A_cp, q0=cp.random.rand(dim), tol=1e-3, max_iter=iteration_factor * dim)
76+
# profile_with_cupy_profiler(log_file, dim, "eigenvalues_cp", eigenvalues_cp, A_cp)
77+
# profile_with_cupy_profiler(log_file, dim, "power_method_cp", power_method_cp, A_cp)
78+
# profile_with_cupy_profiler(log_file, dim, "QR_cp", QR_cp, A_cp, q0=cp.random.rand(dim), tol=1e-3, max_iter=iteration_factor * dim)

scripts/run.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
#import cupyx.scipy.sparse as cpsp
2-
#import cupy as cp
1+
# import cupyx.scipy.sparse as cpsp
2+
# import cupy as cp
33
from pyclassify import (
44
eigenvalues_np,
55
eigenvalues_sp,
6-
#eigenvalues_cp,
6+
# eigenvalues_cp,
77
power_method,
88
power_method_numba,
9-
#power_method_cp,
9+
# power_method_cp,
1010
QR,
11-
#QR_cp,
11+
# QR_cp,
1212
)
1313
from pyclassify.utils import (
1414
make_symmetric,
1515
read_config,
1616
profile_with_cprofile,
17-
#profile_with_cupy_profiler,
17+
# profile_with_cupy_profiler,
1818
)
1919
import numpy as np
2020
import scipy.sparse as sp
@@ -23,13 +23,13 @@
2323
import argparse
2424

2525

26-
#cp.cuda.Device(0).use()
27-
#cp.get_default_memory_pool().free_all_blocks()
26+
# cp.cuda.Device(0).use()
27+
# cp.get_default_memory_pool().free_all_blocks()
2828

2929

3030
seed = 8422
3131
random.seed(seed)
32-
#cp.random.seed(seed)
32+
# cp.random.seed(seed)
3333
np.random.seed(seed)
3434

3535

@@ -55,7 +55,7 @@
5555
A = U @ A @ U.T
5656
A = make_symmetric(A)
5757
A = sp.csr_matrix(A)
58-
#A_cp = cpsp.csr_matrix(A)
58+
# A_cp = cpsp.csr_matrix(A)
5959

6060

6161
log_file = "./logs/timings.csv"
@@ -76,6 +76,6 @@
7676
log_file, dim, "QR", QR, A.toarray(), max_iter=iteration_factor * dim
7777
)
7878

79-
#profile_with_cupy_profiler(log_file, dim, "eigenvalues_cp", eigenvalues_cp, A_cp)
80-
#profile_with_cupy_profiler(log_file, dim, "power_method_cp", power_method_cp, A_cp)
81-
#profile_with_cupy_profiler(log_file, dim, "QR_cp", QR_cp, A_cp, q0=cp.random.rand(dim), tol=1e-3, max_iter=iteration_factor * dim)
79+
# profile_with_cupy_profiler(log_file, dim, "eigenvalues_cp", eigenvalues_cp, A_cp)
80+
# profile_with_cupy_profiler(log_file, dim, "power_method_cp", power_method_cp, A_cp)
81+
# profile_with_cupy_profiler(log_file, dim, "QR_cp", QR_cp, A_cp, q0=cp.random.rand(dim), tol=1e-3, max_iter=iteration_factor * dim)

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ def build_extension(self, ext):
4141
setup(
4242
name="pyclassify",
4343
version="0.0.1",
44-
author="Lorenzo, Gaspare",
45-
author_email="mail.it",
44+
author="Lorenzo Tomada, Gaspare Li Causi",
45+
author_email="ltomada@sissa.it, glicausi@sissa.it",
4646
description="Final project",
4747
long_description="Eigenvalue computation",
4848
ext_modules=[CMakeExtension("pyclassify.QR_cpp")],

shell/submit.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
#!/bin/bash
22

3-
pytest -v > output_pytest.txt
3+
module load cmake/3.29.1
4+
module load intel/2021.2

src/pyclassify/__init__.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,39 @@
11
__all__ = [
22
"eigenvalues_np",
33
"eigenvalues_sp",
4-
#"eigenvalues_cp",
4+
# "eigenvalues_cp",
55
"power_method",
66
"power_method_numba",
7-
#"power_method_cp",
7+
# "power_method_cp",
88
"EigenSolver",
9-
#"Lanczos_PRO_cp",
10-
#"QR_method_cp",
11-
#"QR_cp",
9+
# "Lanczos_PRO_cp",
10+
# "QR_method_cp",
11+
# "QR_cp",
1212
]
1313

1414
from .QR_cpp import QR_algorithm, Eigen_value_calculator
1515

1616
from .eigenvalues import (
1717
eigenvalues_np,
1818
eigenvalues_sp,
19-
#eigenvalues_cp,
19+
# eigenvalues_cp,
2020
power_method,
2121
power_method_numba,
22-
#power_method_cp,
22+
# power_method_cp,
2323
EigenSolver,
24-
#Lanczos_PRO_cp,
25-
#QR_method_cp,
26-
#QR_cp,
24+
# Lanczos_PRO_cp,
25+
# QR_method_cp,
26+
# QR_cp,
27+
)
28+
29+
from .helpers_secular import (
30+
inner_outer_eigs,
31+
return_secular_f,
32+
secular_function,
33+
check_is_root,
34+
bisection,
35+
compute_outer_zero,
36+
compute_psi_s,
37+
compute_inner_zero,
38+
compute_eigenvalues,
2739
)

src/pyclassify/eigenvalues.py

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
import scipy.sparse as sp
33
import scipy.linalg as spla
44
from numpy.linalg import eig, eigh
5-
#import cupy as cp
6-
#import cupy.linalg as cpla
7-
#from cupyx.scipy.sparse.linalg import eigsh as eigsh_cp
5+
6+
# import cupy as cp
7+
# import cupy.linalg as cpla
8+
# from cupyx.scipy.sparse.linalg import eigsh as eigsh_cp
89
from numba import jit, prange
910
from .QR_cpp import QR_algorithm, Eigen_value_calculator
1011
from pyclassify.utils import (
@@ -14,7 +15,6 @@
1415
)
1516

1617

17-
1818
def eigenvalues_np(A, symmetric=True):
1919
"""
2020
Compute the eigenvalues of a square matrix using NumPy's `eig` or `eigh` function.
@@ -43,7 +43,6 @@ def eigenvalues_np(A, symmetric=True):
4343
return eigenvalues
4444

4545

46-
4746
def eigenvalues_sp(A, symmetric=True):
4847
"""
4948
Compute the eigenvalues of a sparse matrix using SciPy's `eigsh` or `eigs` function.
@@ -73,8 +72,7 @@ def eigenvalues_sp(A, symmetric=True):
7372
return eigenvalues
7473

7574

76-
77-
#def eigenvalues_cp(A):
75+
# def eigenvalues_cp(A):
7876
# """
7977
# Compute the eigenvalues of a sparse matrix using CuPy's `eigsh` function.
8078
#
@@ -100,7 +98,6 @@ def eigenvalues_sp(A, symmetric=True):
10098
# return eigenvalues
10199

102100

103-
104101
def power_method(A, max_iter=500, tol=1e-4, x=None):
105102
"""
106103
Compute the dominant eigenvalue of a square matrix using the power method.
@@ -139,7 +136,6 @@ def power_method(A, max_iter=500, tol=1e-4, x=None):
139136
return x @ A @ x
140137

141138

142-
143139
@jit(nopython=True, nogil=True, parallel=True)
144140
def power_method_numba(A, max_iter=500, tol=1e-4, x=None):
145141
"""
@@ -166,7 +162,9 @@ def power_method_numba(A, max_iter=500, tol=1e-4, x=None):
166162
because of numba technicalities.
167163
"""
168164
if A.shape[0] != A.shape[1]:
169-
raise ValueError("Matrix must be square!") # not possible to use the helper function due to the fact that we are using JIT-compilation
165+
raise ValueError(
166+
"Matrix must be square!"
167+
) # not possible to use the helper function due to the fact that we are using JIT-compilation
170168
if x is None:
171169
x = np.random.rand(A.shape[0])
172170
x /= np.linalg.norm(x)
@@ -186,7 +184,6 @@ def power_method_numba(A, max_iter=500, tol=1e-4, x=None):
186184
return x @ A @ x
187185

188186

189-
190187
class EigenSolver:
191188
"""
192189
Class solving the eigenvalue problem for a given symmetric matrix.
@@ -384,8 +381,7 @@ def eig(self, diag=None, off_diag=None):
384381
return np.array(eig), Q_triangular @ self.Q.T
385382

386383

387-
388-
#def power_method_cp(A, max_iter=500, tol=1e-4, x=None):
384+
# def power_method_cp(A, max_iter=500, tol=1e-4, x=None):
389385
# """
390386
# Compute the dominant eigenvalue of a square matrix using the power method.
391387
# Implemented using cupy.
@@ -425,7 +421,7 @@ def eig(self, diag=None, off_diag=None):
425421
# return x @ A @ x
426422
#
427423
#
428-
#def Lanczos_PRO_cp(A, q=None, m=None, tol=1e-8):
424+
# def Lanczos_PRO_cp(A, q=None, m=None, tol=1e-8):
429425
# r"""
430426
# Perform the Lanczos algorithm for symmetric matrices.
431427
#
@@ -492,7 +488,7 @@ def eig(self, diag=None, off_diag=None):
492488
# return Q, cp.array(alpha), cp.array(beta[:-1])
493489
#
494490
#
495-
#def QR_method_cp(diag, off_diag, tol=1e-8, max_iter=1000):
491+
# def QR_method_cp(diag, off_diag, tol=1e-8, max_iter=1000):
496492
# """
497493
# Compute the eigenvalues of a tridiagonal matrix using the QR algorithm.
498494
#
@@ -620,7 +616,7 @@ def eig(self, diag=None, off_diag=None):
620616
# return diag, Q
621617
#
622618
#
623-
#def QR_cp(A, q0=None, tol=1e-8, max_iter=1000):
619+
# def QR_cp(A, q0=None, tol=1e-8, max_iter=1000):
624620
# """
625621
# Compute the eigenvalues of a square matrix using the QR algorithm.
626622
# Done using the Lanczos algorithm to compute the tridiagonal matrix and then the QR

0 commit comments

Comments
 (0)