From 9fc33416e5e11abbfec0515c1e779db5034a26c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicholas=20Kr=C3=A4mer?= Date: Tue, 1 Sep 2020 09:51:14 +0200 Subject: [PATCH] Resolve pylint benchmarks (#178) * resolved pylint complaints in distribution benchmarks * cleaned up pylint messages in linearsolver, too * pulled out random spd matrix * finalised distribution and linearsolver * blacked results * black messed up my pylint ignore * removed benchmark directory from tox pylint ignore * blacked * re-fix ivpsolver and linearsolver * added pylint ignores, renamed property into method * renamed random spd matrix * globally ignored missing-function-docstring * documented benchmark change in tox file * blacked * mini docstring updates --- benchmarks/benchmark_utils.py | 14 ++++++++ benchmarks/ivpsolve.py | 3 ++ benchmarks/linearsolvers.py | 44 ++++++++++++++---------- benchmarks/random_variables.py | 63 ++++++++++++++++------------------ tox.ini | 2 +- 5 files changed, 73 insertions(+), 53 deletions(-) create mode 100644 benchmarks/benchmark_utils.py diff --git a/benchmarks/benchmark_utils.py b/benchmarks/benchmark_utils.py new file mode 100644 index 000000000..febc976a5 --- /dev/null +++ b/benchmarks/benchmark_utils.py @@ -0,0 +1,14 @@ +"""Reocurring constants and methods for benchmarking functions.""" + +import numpy as np + + +SPD_MATRIX_5x5 = np.array( + [ + [2.3, -2.3, 3.5, 4.2, 1.8], + [-2.3, 3.0, -3.5, -4.8, -1.9], + [3.5, -3.5, 6.9, 5.8, 0.8], + [4.2, -4.8, 5.8, 10.1, 6.3], + [1.8, -1.9, 0.8, 6.3, 12.1], + ] +) diff --git a/benchmarks/ivpsolve.py b/benchmarks/ivpsolve.py index 759b1e7ce..c80da7888 100644 --- a/benchmarks/ivpsolve.py +++ b/benchmarks/ivpsolve.py @@ -21,10 +21,12 @@ class IVPSolve: params = [["eks0", "ekf0"], ["with", "without"], ["ibm4", "ioup4", "matern92"]] def setup(self, method, precond, prior): + # pylint: disable=attribute-defined-outside-init,invalid-name,unused-argument self.ivp = load_lotkavolterra() self.stepsize = 1e-2 def time_solve(self, method, precond, prior): + # pylint: disable=missing-function-docstring precond_step = self.stepsize if precond == "with" else 1.0 probsolve_ivp( self.ivp, @@ -35,6 +37,7 @@ def time_solve(self, method, precond, prior): ) def peakmem_solve(self, method, precond, prior): + # pylint: disable=missing-function-docstring precond_step = self.stepsize if precond == "with" else 1.0 probsolve_ivp( self.ivp, diff --git a/benchmarks/linearsolvers.py b/benchmarks/linearsolvers.py index c4c90eb3e..0b9c64610 100644 --- a/benchmarks/linearsolvers.py +++ b/benchmarks/linearsolvers.py @@ -7,6 +7,7 @@ import scipy.sparse from probnum.linalg import problinsolve +from benchmarks.benchmark_utils import SPD_MATRIX_5x5 def load_poisson_linear_system(): @@ -21,6 +22,7 @@ def load_poisson_linear_system(): Linear system resulting from discretization on an elliptic grid. """ + # pylint: disable=invalid-name fpath = os.path.join(os.path.dirname(__file__), "../tests/resources") A = scipy.sparse.load_npz(file=fpath + "/matrix_poisson.npz") f = np.load(file=fpath + "/rhs_poisson.npy") @@ -28,52 +30,55 @@ def load_poisson_linear_system(): class LinSolve: - """ - Benchmark solving a linear system. - """ + """Benchmark solving a linear system.""" param_names = ["system"] params = [["sparse", "dense"]] # , "large-scale"] def setup(self, system): + # pylint: disable=attribute-defined-outside-init,invalid-name + # Seed np.random.seed(42) if system == "sparse": - self.A, self.b = load_poisson_linear_system() + ( + self.A, + self.b, + ) = load_poisson_linear_system() elif system == "dense": - self.A = np.array( - [ - [2.3, -2.3, 3.5, 4.2, 1.8], - [-2.3, 3.0, -3.5, -4.8, -1.9], - [3.5, -3.5, 6.9, 5.8, 0.8], - [4.2, -4.8, 5.8, 10.1, 6.3], - [1.8, -1.9, 0.8, 6.3, 12.1], - ] - ) + self.A = SPD_MATRIX_5x5 self.b = np.random.normal(size=self.A.shape[0]) elif system == "large-scale": self.A = None self.b = None def time_solve(self, system): - # Solve linear system - self.xhat, self.Ahat, self.Ainvhat, _ = problinsolve(A=self.A, b=self.b) + """Time solving a linear system""" + # pylint: disable=unused-argument + problinsolve(A=self.A, b=self.b) def mem_solve(self, system): - # Solve linear system - self.xhat, self.Ahat, self.Ainvhat, _ = problinsolve(A=self.A, b=self.b) + """Time solving a linear system""" + # pylint: disable=unused-argument + problinsolve(A=self.A, b=self.b) def peakmem_solve(self, system): - # Solve linear system - self.xhat, self.Ahat, self.Ainvhat, _ = problinsolve(A=self.A, b=self.b) + """Time solving a linear system""" + # pylint: disable=unused-argument + problinsolve(A=self.A, b=self.b) class PosteriorDist: + """Benchmark sampling from the posterior distribution.""" + param_names = ["output"] params = [["solution", "matrix", "matrix_inverse"]] def setup(self, output): + # pylint: disable=attribute-defined-outside-init + # pylint: disable=unused-argument, invalid-name + # Sparse system self.A, self.b = load_poisson_linear_system() @@ -84,6 +89,7 @@ def setup(self, output): self.n_samples = 10 def time_sample(self, output): + """Time sampling from the posterior distribution""" if output == "solution": self.xhat.sample(self.n_samples) elif output == "matrix": diff --git a/benchmarks/random_variables.py b/benchmarks/random_variables.py index 1e09ea2ef..cf67ee73b 100644 --- a/benchmarks/random_variables.py +++ b/benchmarks/random_variables.py @@ -7,8 +7,10 @@ from probnum import random_variables as rvs import probnum.linalg.linops as linops +from benchmarks.benchmark_utils import SPD_MATRIX_5x5 + # Module level variables -rv_names = [ +RV_NAMES = [ "univar_normal", "multivar_normal", "matrixvar_normal", @@ -18,27 +20,17 @@ def get_randvar(rv_name): - """ - Return a random variable for a given distribution name - """ + """Return a random variable for a given distribution name.""" # Distribution Means and Covariances - spd_mat = np.array( - [ - [2.3, -2.3, 3.5, 4.2, 1.8], - [-2.3, 3.0, -3.5, -4.8, -1.9], - [3.5, -3.5, 6.9, 5.8, 0.8], - [4.2, -4.8, 5.8, 10.1, 6.3], - [1.8, -1.9, 0.8, 6.3, 12.1], - ] - ) + mean_0d = np.random.rand() mean_1d = np.random.rand(5) - mean_2d_mat = spd_mat - mean_2d_linop = linops.MatrixMult(spd_mat) + mean_2d_mat = SPD_MATRIX_5x5 + mean_2d_linop = linops.MatrixMult(SPD_MATRIX_5x5) cov_0d = np.random.rand() + 10 ** -12 - cov_1d = spd_mat - cov_2d_kron = linops.Kronecker(A=spd_mat, B=spd_mat) - cov_2d_symkron = linops.SymmetricKronecker(A=spd_mat) + cov_1d = SPD_MATRIX_5x5 + cov_2d_kron = linops.Kronecker(A=SPD_MATRIX_5x5, B=SPD_MATRIX_5x5) + cov_2d_symkron = linops.SymmetricKronecker(A=SPD_MATRIX_5x5) if rv_name == "univar_normal": randvar = rvs.Normal(mean=mean_0d, cov=cov_0d) @@ -55,50 +47,55 @@ def get_randvar(rv_name): class Functions: - """ - Benchmark various functions of distributions. - """ + """Benchmark various functions of random variables.""" + + param_names = ["randvar", "method"] + params = [RV_NAMES, ["pdf", "logpdf", "cdf", "logcdf"]] - param_names = ["randvar", "property"] - params = [rv_names, ["pdf", "logpdf", "cdf", "logcdf"]] + def setup(self, randvar, method): + # pylint: disable=unused-argument,attribute-defined-outside-init,missing-function-docstring - def setup(self, randvar, property): self.randvar = get_randvar(rv_name=randvar) self.eval_point = np.random.uniform(size=self.randvar.shape) self.quantile = np.random.uniform(size=self.randvar.shape) - def time_distr_functions(self, randvar, property): + def time_distr_functions(self, randvar, method): """Times evaluation of the pdf, logpdf, cdf and logcdf.""" + # pylint: disable=unused-argument + try: - if property == "pdf": + if method == "pdf": self.randvar.pdf(x=self.eval_point) - elif property == "logpdf": + elif method == "logpdf": self.randvar.logpdf(x=self.eval_point) - elif property == "cdf": + elif method == "cdf": self.randvar.cdf(x=self.quantile) - elif property == "logcdf": + elif method == "logcdf": self.randvar.logcdf(x=self.quantile) except NotImplementedError: pass class Sampling: - """ - Benchmark sampling routines for various distributions. - """ + """Benchmark sampling routines for various distributions.""" param_names = ["randvar"] - params = [rv_names] + params = [RV_NAMES] def setup(self, randvar): + # pylint: disable=unused-argument,attribute-defined-outside-init,missing-function-docstring np.random.seed(42) self.n_samples = 1000 self.randvar = get_randvar(rv_name=randvar) def time_sample(self, randvar): """Times sampling from this distribution.""" + # pylint: disable=unused-argument + self.randvar.sample(self.n_samples) def peakmem_sample(self, randvar): """Peak memory of sampling process.""" + # pylint: disable=unused-argument + self.randvar.sample(self.n_samples) diff --git a/tox.ini b/tox.ini index 5405d5d8e..35b81e228 100644 --- a/tox.ini +++ b/tox.ini @@ -62,5 +62,5 @@ commands = pylint src/probnum/quad --disable="attribute-defined-outside-init,too-few-public-methods,redefined-builtin,arguments-differ,unused-argument,missing-module-docstring" pylint src/probnum/random_variables --disable="missing-function-docstring" pylint src/probnum/utils --disable="duplicate-code,missing-module-docstring,missing-function-docstring" + pylint benchmarks --disable="missing-function-docstring" # not a work in progress, but final pylint tests --disable="line-too-long,duplicate-code,missing-class-docstring,unnecessary-pass,unused-variable,protected-access,attribute-defined-outside-init,no-self-use,abstract-class-instantiated,too-many-arguments,too-many-instance-attributes,too-many-locals,unused-argument,fixme,missing-module-docstring,missing-function-docstring" - pylint benchmarks --disable="attribute-defined-outside-init,unused-argument,redefined-builtin,missing-class-docstring,duplicate-code,missing-function-docstring"