From 67e61f7b173930b83edb1bf3abaf5fc4dfbd8566 Mon Sep 17 00:00:00 2001 From: Bart van Erp <44952318+bartvanerp@users.noreply.github.com> Date: Tue, 21 Nov 2023 17:31:01 +0100 Subject: [PATCH 01/14] update gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 95731a5..3fd84ec 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ /Manifest.toml /docs/Manifest.toml /docs/build/ + +.vscode \ No newline at end of file From 592e907a360424d64e508643f98926df757c138c Mon Sep 17 00:00:00 2001 From: Bart van Erp <44952318+bartvanerp@users.noreply.github.com> Date: Tue, 21 Nov 2023 17:39:38 +0100 Subject: [PATCH 02/14] update gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3fd84ec..be08504 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ *.jl.*.cov *.jl.cov *.jl.mem -/Manifest.toml +Manifest.toml /docs/Manifest.toml /docs/build/ From 1ecb20a4e67c8ee22f741ff8ba4a234785a184a3 Mon Sep 17 00:00:00 2001 From: Bart van Erp <44952318+bartvanerp@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:10:21 +0100 Subject: [PATCH 03/14] add speed benchmarks --- .gitignore | 4 +++- Makefile | 22 ++++++++++++++++++++++ benchmarks/speed/Project.toml | 4 ++++ benchmarks/speed/benchmarks.jl | 25 +++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 benchmarks/speed/Project.toml create mode 100644 benchmarks/speed/benchmarks.jl diff --git a/.gitignore b/.gitignore index be08504..a4d3aac 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ Manifest.toml /docs/Manifest.toml /docs/build/ -.vscode \ No newline at end of file +.vscode +benchmark +exports \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7c1bebc --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +SHELL = /bin/bash +.DEFAULT_GOAL = help + +# Windows has different commands in shell +# - `RM` command: use for removing files +ifeq ($(OS), Windows_NT) + RM = del /Q /F + PATH_SEP = \\ +else + RM = rm -rf + PATH_SEP = / +endif + +.PHONY: test + +test: ## Run tests, use test_args="folder1:test1 folder2:test2" argument to run reduced testset, use dev=true to use `dev-ed` version of core packages + julia -e 'ENV["USE_DEV"]="$(dev)"; import Pkg; Pkg.activate("."); Pkg.test(test_args = split("$(test_args)") .|> string);' + +.PHONY: benchmark + +benchmark: ## Run benchmarks + julia -e 'ENV["USE_DEV"]="$(dev)"; import Pkg; Pkg.activate("benchmarks/speed"); using PkgBenchmark, FastCholesky, Dates; results = benchmarkpkg("FastCholesky"; script="benchmarks/speed/benchmarks.jl"); export_markdown("benchmarks/speed/exports/benchmark-"*Dates.format(Dates.now(), "yyyy-mm-ddTHH-MM")*".md", results);' \ No newline at end of file diff --git a/benchmarks/speed/Project.toml b/benchmarks/speed/Project.toml new file mode 100644 index 0000000..eed2655 --- /dev/null +++ b/benchmarks/speed/Project.toml @@ -0,0 +1,4 @@ +[deps] +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" +FastCholesky = "2d5283b6-8564-42b6-bb00-83ed8e915756" +PkgBenchmark = "32113eaa-f34f-5b0d-bd6c-c81e245fc73d" diff --git a/benchmarks/speed/benchmarks.jl b/benchmarks/speed/benchmarks.jl new file mode 100644 index 0000000..3e159aa --- /dev/null +++ b/benchmarks/speed/benchmarks.jl @@ -0,0 +1,25 @@ +using BenchmarkTools +using FastCholesky + +const SUITE = BenchmarkGroup() + +for T in (Float32, Float64, BigFloat) + + for dim in (2, 5, 10)#, 20, 50, 100, 200, 500) + + # generate positive-definite matrix of specified dimensions + A = randn(dim, dim) + B = A * A' + C = similar(B) + + # define benchmarks + SUITE["fastcholesky-"*string(T)*"-"*string(dim)] = @benchmarkable fastcholesky($B) + SUITE["fastcholesky!-"*string(T)*"-"*string(dim)] = @benchmarkable fastcholesky!($C) + SUITE["cholinv-"*string(T)*"-"*string(dim)] = @benchmarkable cholinv($B) + SUITE["cholsqrt-"*string(T)*"-"*string(dim)] = @benchmarkable cholsqrt($B) + SUITE["chollogdet-"*string(T)*"-"*string(dim)] = @benchmarkable chollogdet($B) + SUITE["cholinv_logdet-"*string(T)*"-"*string(dim)] = @benchmarkable cholinv_logdet($B) + + end + +end \ No newline at end of file From 30f9719bd3e33d584690d984db7473f42ec882b3 Mon Sep 17 00:00:00 2001 From: Bart van Erp <44952318+bartvanerp@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:19:30 +0100 Subject: [PATCH 04/14] rm ugly tuning file --- Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7c1bebc..db2449d 100644 --- a/Makefile +++ b/Makefile @@ -19,4 +19,11 @@ test: ## Run tests, use test_args="folder1:test1 folder2:test2" argument to run .PHONY: benchmark benchmark: ## Run benchmarks - julia -e 'ENV["USE_DEV"]="$(dev)"; import Pkg; Pkg.activate("benchmarks/speed"); using PkgBenchmark, FastCholesky, Dates; results = benchmarkpkg("FastCholesky"; script="benchmarks/speed/benchmarks.jl"); export_markdown("benchmarks/speed/exports/benchmark-"*Dates.format(Dates.now(), "yyyy-mm-ddTHH-MM")*".md", results);' \ No newline at end of file + julia -e '\ + ENV["USE_DEV"]="$(dev)"; \ + import Pkg; \ + Pkg.activate("benchmarks/speed"); \ + using PkgBenchmark, FastCholesky, Dates; \ + results = benchmarkpkg("FastCholesky"; script="benchmarks/speed/benchmarks.jl"); \ + export_markdown("benchmarks/speed/exports/benchmark-"*Dates.format(Dates.now(), "yyyy-mm-ddTHH-MM")*".md", results); \ + Base.Filesystem.rm("benchmark"; force=true, recursive=true)' \ No newline at end of file From cf97ec833e87274b41b519f1c3a15ed978eb7ab0 Mon Sep 17 00:00:00 2001 From: Bart van Erp <44952318+bartvanerp@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:52:49 +0100 Subject: [PATCH 05/14] extend methods --- src/FastCholesky.jl | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/FastCholesky.jl b/src/FastCholesky.jl index 86aa4aa..73cb747 100644 --- a/src/FastCholesky.jl +++ b/src/FastCholesky.jl @@ -35,17 +35,10 @@ end fastcholesky(input::Diagonal) = cholesky(input) fastcholesky(input::Hermitian) = cholesky(PositiveFactorizations.Positive, input) fastcholesky(input::Number) = input +fastcholesky!(input::Number) = input -function fastcholesky(x::UniformScaling) - return error( - "`fastcholesky` is not defined for `UniformScaling`. The shape is not determined." - ) -end -function fastcholesky!(x::UniformScaling) - return error( - "`fastcholesky!` is not defined for `UniformScaling`. The shape is not determined." - ) -end +fastcholesky(x::UniformScaling) = sqrt(x.λ) * I +fastcholesky!(x::UniformScaling) = sqrt(x.λ) * I function fastcholesky(input::Matrix{<:BlasFloat}) C = fastcholesky!(copy(input)) From 40a2460c7b97989e1b0bce43592d03155df4d0de Mon Sep 17 00:00:00 2001 From: Bart van Erp <44952318+bartvanerp@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:52:55 +0100 Subject: [PATCH 06/14] add benchmarks --- benchmarks/speed/Project.toml | 1 + benchmarks/speed/benchmarks.jl | 38 +++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/benchmarks/speed/Project.toml b/benchmarks/speed/Project.toml index eed2655..a464e29 100644 --- a/benchmarks/speed/Project.toml +++ b/benchmarks/speed/Project.toml @@ -1,4 +1,5 @@ [deps] BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" FastCholesky = "2d5283b6-8564-42b6-bb00-83ed8e915756" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" PkgBenchmark = "32113eaa-f34f-5b0d-bd6c-c81e245fc73d" diff --git a/benchmarks/speed/benchmarks.jl b/benchmarks/speed/benchmarks.jl index 3e159aa..a4c3de2 100644 --- a/benchmarks/speed/benchmarks.jl +++ b/benchmarks/speed/benchmarks.jl @@ -1,8 +1,9 @@ -using BenchmarkTools +using BenchmarkTools, LinearAlgebra using FastCholesky const SUITE = BenchmarkGroup() +# general benchmarks for T in (Float32, Float64, BigFloat) for dim in (2, 5, 10)#, 20, 50, 100, 200, 500) @@ -13,13 +14,34 @@ for T in (Float32, Float64, BigFloat) C = similar(B) # define benchmarks - SUITE["fastcholesky-"*string(T)*"-"*string(dim)] = @benchmarkable fastcholesky($B) - SUITE["fastcholesky!-"*string(T)*"-"*string(dim)] = @benchmarkable fastcholesky!($C) - SUITE["cholinv-"*string(T)*"-"*string(dim)] = @benchmarkable cholinv($B) - SUITE["cholsqrt-"*string(T)*"-"*string(dim)] = @benchmarkable cholsqrt($B) - SUITE["chollogdet-"*string(T)*"-"*string(dim)] = @benchmarkable chollogdet($B) - SUITE["cholinv_logdet-"*string(T)*"-"*string(dim)] = @benchmarkable cholinv_logdet($B) + SUITE["fastcholesky-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable fastcholesky($B) + SUITE["fastcholesky!-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable fastcholesky!($C) + SUITE["cholinv-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholinv($B) + SUITE["cholsqrt-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholsqrt($B) + SUITE["chollogdet-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable chollogdet($B) + SUITE["cholinv_logdet-"*"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholinv_logdet($B) end -end \ No newline at end of file +end + +# Float64 benchmarks +SUITE["fastcholesky-" *"Type:Float64"] = @benchmarkable fastcholesky($3.0) +SUITE["fastcholesky!-" *"Type:Float64"] = @benchmarkable fastcholesky!($3.0) +SUITE["cholinv-" *"Type:Float64"] = @benchmarkable cholinv($3.0) +SUITE["cholsqrt-" *"Type:Float64"] = @benchmarkable cholsqrt($3.0) +SUITE["chollogdet-" *"Type:Float64"] = @benchmarkable chollogdet($3.0) +SUITE["cholinv_logdet-"*"Type:Float64"] = @benchmarkable cholinv_logdet($3.0) + +# Diagonal{Float64} benchmarks +SUITE["fastcholesky-" *"Type:Diagonal{Float64}"] = @benchmarkable fastcholesky($(Diagonal(3.0*ones(100)))) +SUITE["cholinv-" *"Type:Diagonal{Float64}"] = @benchmarkable cholinv($(Diagonal(3.0*ones(100)))) +SUITE["cholsqrt-" *"Type:Diagonal{Float64}"] = @benchmarkable cholsqrt($(Diagonal(3.0*ones(100)))) +SUITE["chollogdet-" *"Type:Diagonal{Float64}"] = @benchmarkable chollogdet($(Diagonal(3.0*ones(100)))) +SUITE["cholinv_logdet-"*"Type:Diagonal{Float64}"] = @benchmarkable cholinv_logdet($(Diagonal(3.0*ones(100)))) + +# Uniformscaling benchmarks +SUITE["fastcholesky-" *"Type:UniformScaling"] = @benchmarkable fastcholesky($(3.0I)) +SUITE["fastcholesky!-" *"Type:UniformScaling"] = @benchmarkable fastcholesky!($(3.0I)) +SUITE["cholinv-" *"Type:UniformScaling"] = @benchmarkable cholinv($(3.0I)) +SUITE["cholsqrt-" *"Type:UniformScaling"] = @benchmarkable cholsqrt($(3.0I)) From bd9656b657b71326bc2898f5961a01c30000fda3 Mon Sep 17 00:00:00 2001 From: Bart van Erp <44952318+bartvanerp@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:53:47 +0100 Subject: [PATCH 07/14] update benchmarks --- benchmarks/speed/benchmarks.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/speed/benchmarks.jl b/benchmarks/speed/benchmarks.jl index a4c3de2..a9c73af 100644 --- a/benchmarks/speed/benchmarks.jl +++ b/benchmarks/speed/benchmarks.jl @@ -6,7 +6,7 @@ const SUITE = BenchmarkGroup() # general benchmarks for T in (Float32, Float64, BigFloat) - for dim in (2, 5, 10)#, 20, 50, 100, 200, 500) + for dim in (2, 5, 10, 20, 50, 100, 200, 500) # generate positive-definite matrix of specified dimensions A = randn(dim, dim) From 7e8e9c0b6090599cf3c18a6fa2d046fb615a06dc Mon Sep 17 00:00:00 2001 From: Bart van Erp <44952318+bartvanerp@users.noreply.github.com> Date: Wed, 22 Nov 2023 09:03:48 +0100 Subject: [PATCH 08/14] Update fastcholesky_tests.jl --- test/fastcholesky_tests.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/fastcholesky_tests.jl b/test/fastcholesky_tests.jl index 9617230..2af3f05 100644 --- a/test/fastcholesky_tests.jl +++ b/test/fastcholesky_tests.jl @@ -59,8 +59,8 @@ end @test chollogdet(I) ≈ zero @test all(cholinv_logdet(one * I) .≈ (one * I, zero)) @test_throws ArgumentError chollogdet(two * I) - @test_throws ErrorException fastcholesky(I) - @test_throws ErrorException fastcholesky!(I) + @test fastcholesky(I) ≈ I + @test fastcholesky!(I) ≈ I end end @@ -91,4 +91,4 @@ end @test inv(fastcholesky(F)) * F ≈ Diagonal(ones(4)) rtol=1e-4 @test cholinv(F) * F ≈ Diagonal(ones(4)) rtol=1e-4 @test fastcholesky(F).L ≈ cholesky(F).L -end \ No newline at end of file +end From 2868647b66ed3527a2b17e728611098c03614e2b Mon Sep 17 00:00:00 2001 From: Bart van Erp <44952318+bartvanerp@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:24:30 +0100 Subject: [PATCH 09/14] Apply suggestions from code review Co-authored-by: Bagaev Dmitry --- .gitignore | 2 +- Makefile | 14 ++----------- benchmarks/speed/benchmarks.jl | 38 ++++++++++++++++++---------------- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index a4d3aac..bfbc0aa 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ Manifest.toml .vscode benchmark -exports \ No newline at end of file +benchmarks/**/exports \ No newline at end of file diff --git a/Makefile b/Makefile index db2449d..ad99557 100644 --- a/Makefile +++ b/Makefile @@ -1,26 +1,16 @@ SHELL = /bin/bash .DEFAULT_GOAL = help -# Windows has different commands in shell -# - `RM` command: use for removing files -ifeq ($(OS), Windows_NT) - RM = del /Q /F - PATH_SEP = \\ -else - RM = rm -rf - PATH_SEP = / -endif .PHONY: test -test: ## Run tests, use test_args="folder1:test1 folder2:test2" argument to run reduced testset, use dev=true to use `dev-ed` version of core packages - julia -e 'ENV["USE_DEV"]="$(dev)"; import Pkg; Pkg.activate("."); Pkg.test(test_args = split("$(test_args)") .|> string);' +test: ## Run tests + julia -e 'import Pkg; Pkg.activate("."); Pkg.test();' .PHONY: benchmark benchmark: ## Run benchmarks julia -e '\ - ENV["USE_DEV"]="$(dev)"; \ import Pkg; \ Pkg.activate("benchmarks/speed"); \ using PkgBenchmark, FastCholesky, Dates; \ diff --git a/benchmarks/speed/benchmarks.jl b/benchmarks/speed/benchmarks.jl index a9c73af..fbaac60 100644 --- a/benchmarks/speed/benchmarks.jl +++ b/benchmarks/speed/benchmarks.jl @@ -6,11 +6,21 @@ const SUITE = BenchmarkGroup() # general benchmarks for T in (Float32, Float64, BigFloat) + # number + a = rand(T) + + SUITE["fastcholesky-" *"Type:"*string(T)] = @benchmarkable fastcholesky($a) + SUITE["fastcholesky!-" *"Type:"*string(T)] = @benchmarkable fastcholesky!($a) + SUITE["cholinv-" *"Type:"*string(T)] = @benchmarkable cholinv($a) + SUITE["cholsqrt-" *"Type:"*string(T)] = @benchmarkable cholsqrt($a) + SUITE["chollogdet-" *"Type:"*string(T)] = @benchmarkable chollogdet($a) + SUITE["cholinv_logdet-"*"Type:"*string(T)] = @benchmarkable cholinv_logdet($a) + for dim in (2, 5, 10, 20, 50, 100, 200, 500) # generate positive-definite matrix of specified dimensions - A = randn(dim, dim) - B = A * A' + A = randn(T, dim, dim) + B = A * A' + dim * I(dim) C = similar(B) # define benchmarks @@ -20,26 +30,18 @@ for T in (Float32, Float64, BigFloat) SUITE["cholsqrt-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholsqrt($B) SUITE["chollogdet-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable chollogdet($B) SUITE["cholinv_logdet-"*"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholinv_logdet($B) - + + # Diagonal{T} benchmarks + SUITE["fastcholesky-" *"Type:Diagonal{"*string(T)*"}"] = @benchmarkable fastcholesky($(Diagonal(ones(T, dim)))) + SUITE["cholinv-" *"Type:Diagonal{"*string(T)*"}"] = @benchmarkable cholinv($(Diagonal(ones(T, dim)))) + SUITE["cholsqrt-" *"Type:Diagonal{"*string(T)*"}"] = @benchmarkable cholsqrt($(Diagonal(ones(T, dim)))) + SUITE["chollogdet-" *"Type:Diagonal{"*string(T)*"}"] = @benchmarkable chollogdet($(Diagonal(ones(T, dim)))) + SUITE["cholinv_logdet-"*"Type:Diagonal{"*string(T)*"}"] = @benchmarkable cholinv_logdet($(Diagonal(ones(T, dim)))) + end end -# Float64 benchmarks -SUITE["fastcholesky-" *"Type:Float64"] = @benchmarkable fastcholesky($3.0) -SUITE["fastcholesky!-" *"Type:Float64"] = @benchmarkable fastcholesky!($3.0) -SUITE["cholinv-" *"Type:Float64"] = @benchmarkable cholinv($3.0) -SUITE["cholsqrt-" *"Type:Float64"] = @benchmarkable cholsqrt($3.0) -SUITE["chollogdet-" *"Type:Float64"] = @benchmarkable chollogdet($3.0) -SUITE["cholinv_logdet-"*"Type:Float64"] = @benchmarkable cholinv_logdet($3.0) - -# Diagonal{Float64} benchmarks -SUITE["fastcholesky-" *"Type:Diagonal{Float64}"] = @benchmarkable fastcholesky($(Diagonal(3.0*ones(100)))) -SUITE["cholinv-" *"Type:Diagonal{Float64}"] = @benchmarkable cholinv($(Diagonal(3.0*ones(100)))) -SUITE["cholsqrt-" *"Type:Diagonal{Float64}"] = @benchmarkable cholsqrt($(Diagonal(3.0*ones(100)))) -SUITE["chollogdet-" *"Type:Diagonal{Float64}"] = @benchmarkable chollogdet($(Diagonal(3.0*ones(100)))) -SUITE["cholinv_logdet-"*"Type:Diagonal{Float64}"] = @benchmarkable cholinv_logdet($(Diagonal(3.0*ones(100)))) - # Uniformscaling benchmarks SUITE["fastcholesky-" *"Type:UniformScaling"] = @benchmarkable fastcholesky($(3.0I)) SUITE["fastcholesky!-" *"Type:UniformScaling"] = @benchmarkable fastcholesky!($(3.0I)) From 319f166fe83c57860e2c9ad2303c305818c2d028 Mon Sep 17 00:00:00 2001 From: Bagaev Dmitry Date: Fri, 24 Nov 2023 10:02:25 +0100 Subject: [PATCH 10/14] fix first time instantiation --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index ad99557..55a004e 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,8 @@ benchmark: ## Run benchmarks julia -e '\ import Pkg; \ Pkg.activate("benchmarks/speed"); \ + Pkg.develop(Pkg.PackageSpec(path=pwd())); \ + Pkg.instantiate(); \ using PkgBenchmark, FastCholesky, Dates; \ results = benchmarkpkg("FastCholesky"; script="benchmarks/speed/benchmarks.jl"); \ export_markdown("benchmarks/speed/exports/benchmark-"*Dates.format(Dates.now(), "yyyy-mm-ddTHH-MM")*".md", results); \ From d31923a07e08b33feff5d744fb35ff65536dbe09 Mon Sep 17 00:00:00 2001 From: Bagaev Dmitry Date: Fri, 24 Nov 2023 10:17:53 +0100 Subject: [PATCH 11/14] fix some broken benchmarks and add more tests --- benchmarks/speed/benchmarks.jl | 17 +++++++++++++++-- test/fastcholesky_tests.jl | 4 ++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/benchmarks/speed/benchmarks.jl b/benchmarks/speed/benchmarks.jl index fbaac60..f24975f 100644 --- a/benchmarks/speed/benchmarks.jl +++ b/benchmarks/speed/benchmarks.jl @@ -18,16 +18,29 @@ for T in (Float32, Float64, BigFloat) for dim in (2, 5, 10, 20, 50, 100, 200, 500) + # Skip `BigFloat` benchmarks for large dimensions because they are extremely slow + if (T == BigFloat) && (dim >= 100) + continue + end + # generate positive-definite matrix of specified dimensions A = randn(T, dim, dim) B = A * A' + dim * I(dim) C = similar(B) + # The inplace version works only for `Matrix{<:BlasFloat}` + if T <: LinearAlgebra.BlasFloat + SUITE["fastcholesky!-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable fastcholesky!($C) + end + + # `sqrt` does not work for `BigFloat` inputs + if T != BigFloat + SUITE["cholsqrt-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholsqrt($B) + end + # define benchmarks SUITE["fastcholesky-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable fastcholesky($B) - SUITE["fastcholesky!-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable fastcholesky!($C) SUITE["cholinv-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholinv($B) - SUITE["cholsqrt-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholsqrt($B) SUITE["chollogdet-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable chollogdet($B) SUITE["cholinv_logdet-"*"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholinv_logdet($B) diff --git a/test/fastcholesky_tests.jl b/test/fastcholesky_tests.jl index 2af3f05..adfdb18 100644 --- a/test/fastcholesky_tests.jl +++ b/test/fastcholesky_tests.jl @@ -28,6 +28,10 @@ @test all(cholinv_logdet(input) .≈ (inv(input), logdet(input))) @test cholsqrt(input) * cholsqrt(input)' ≈ input + if Type <: LinearAlgebra.BlasFloat && input isa Matrix + @test collect(fastcholesky(input).L) ≈ collect(fastcholesky!(deepcopy(input)).L) + end + # `sqrt` does not work on `BigFloat` matrices if Type !== BigFloat @test cholsqrt(input) * cholsqrt(input)' ≈ sqrt(input) * sqrt(input)' From 64ef9bdcffa0d8c290b96d36d4dce5bdb05052c1 Mon Sep 17 00:00:00 2001 From: Bagaev Dmitry Date: Fri, 24 Nov 2023 10:26:21 +0100 Subject: [PATCH 12/14] create path if run for the first time --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 55a004e..70be4f1 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ benchmark: ## Run benchmarks Pkg.develop(Pkg.PackageSpec(path=pwd())); \ Pkg.instantiate(); \ using PkgBenchmark, FastCholesky, Dates; \ + Base.Filesystem.mkpath("benchmarks/speed/exports/"); \ results = benchmarkpkg("FastCholesky"; script="benchmarks/speed/benchmarks.jl"); \ export_markdown("benchmarks/speed/exports/benchmark-"*Dates.format(Dates.now(), "yyyy-mm-ddTHH-MM")*".md", results); \ Base.Filesystem.rm("benchmark"; force=true, recursive=true)' \ No newline at end of file From 1c08e1221df543951a7f415a30204df43ee633cc Mon Sep 17 00:00:00 2001 From: Bagaev Dmitry Date: Fri, 24 Nov 2023 11:30:43 +0100 Subject: [PATCH 13/14] create benchmark groups --- .JuliaFormatter.toml | 1 + benchmarks/speed/benchmarks.jl | 64 ++++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index d808d22..fc2cb94 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -1,2 +1,3 @@ # See https://domluna.github.io/JuliaFormatter.jl/stable/ for a list of options style = "blue" +margin = 140 diff --git a/benchmarks/speed/benchmarks.jl b/benchmarks/speed/benchmarks.jl index f24975f..847c36c 100644 --- a/benchmarks/speed/benchmarks.jl +++ b/benchmarks/speed/benchmarks.jl @@ -2,22 +2,32 @@ using BenchmarkTools, LinearAlgebra using FastCholesky const SUITE = BenchmarkGroup() +const BenchmarkFloatTypes = (Float32, Float64, BigFloat) + +for T in BenchmarkFloatTypes + SUITE[string(T)] = BenchmarkGroup() + SUITE[string(T)]["Number"] = BenchmarkGroup() + SUITE[string(T)]["Matrix"] = BenchmarkGroup() + SUITE[string(T)]["Diagonal"] = BenchmarkGroup() +end # general benchmarks -for T in (Float32, Float64, BigFloat) +for T in BenchmarkFloatTypes # number a = rand(T) - - SUITE["fastcholesky-" *"Type:"*string(T)] = @benchmarkable fastcholesky($a) - SUITE["fastcholesky!-" *"Type:"*string(T)] = @benchmarkable fastcholesky!($a) - SUITE["cholinv-" *"Type:"*string(T)] = @benchmarkable cholinv($a) - SUITE["cholsqrt-" *"Type:"*string(T)] = @benchmarkable cholsqrt($a) - SUITE["chollogdet-" *"Type:"*string(T)] = @benchmarkable chollogdet($a) - SUITE["cholinv_logdet-"*"Type:"*string(T)] = @benchmarkable cholinv_logdet($a) + + SUITE[string(T)]["Number"]["fastcholesky"] = @benchmarkable fastcholesky($a) + SUITE[string(T)]["Number"]["fastcholesky!"] = @benchmarkable fastcholesky!($a) + SUITE[string(T)]["Number"]["cholinv"] = @benchmarkable cholinv($a) + SUITE[string(T)]["Number"]["cholsqrt"] = @benchmarkable cholsqrt($a) + SUITE[string(T)]["Number"]["chollogdet"] = @benchmarkable chollogdet($a) + SUITE[string(T)]["Number"]["cholinv_logdet"] = @benchmarkable cholinv_logdet($a) for dim in (2, 5, 10, 20, 50, 100, 200, 500) + SUITE[string(T)]["Matrix"]["dim:" * string(dim)] = BenchmarkGroup() + # Skip `BigFloat` benchmarks for large dimensions because they are extremely slow if (T == BigFloat) && (dim >= 100) continue @@ -30,33 +40,35 @@ for T in (Float32, Float64, BigFloat) # The inplace version works only for `Matrix{<:BlasFloat}` if T <: LinearAlgebra.BlasFloat - SUITE["fastcholesky!-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable fastcholesky!($C) + SUITE[string(T)]["Matrix"]["dim:" * string(dim)]["fastcholesky!"] = @benchmarkable fastcholesky!($C) end # `sqrt` does not work for `BigFloat` inputs if T != BigFloat - SUITE["cholsqrt-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholsqrt($B) + SUITE[string(T)]["Matrix"]["dim:" * string(dim)]["cholsqrt"] = @benchmarkable cholsqrt($B) end # define benchmarks - SUITE["fastcholesky-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable fastcholesky($B) - SUITE["cholinv-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholinv($B) - SUITE["chollogdet-" *"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable chollogdet($B) - SUITE["cholinv_logdet-"*"Type:Matrix{"*string(T)*"}-Dim:"*string(dim)] = @benchmarkable cholinv_logdet($B) - + SUITE[string(T)]["Matrix"]["dim:" * string(dim)]["fastcholesky"] = @benchmarkable fastcholesky($B) + SUITE[string(T)]["Matrix"]["dim:" * string(dim)]["cholinv"] = @benchmarkable cholinv($B) + SUITE[string(T)]["Matrix"]["dim:" * string(dim)]["chollogdet"] = @benchmarkable chollogdet($B) + SUITE[string(T)]["Matrix"]["dim:" * string(dim)]["cholinv_logdet"] = @benchmarkable cholinv_logdet($B) + + SUITE[string(T)]["Diagonal"]["dim:" * string(dim)] = BenchmarkGroup() + # Diagonal{T} benchmarks - SUITE["fastcholesky-" *"Type:Diagonal{"*string(T)*"}"] = @benchmarkable fastcholesky($(Diagonal(ones(T, dim)))) - SUITE["cholinv-" *"Type:Diagonal{"*string(T)*"}"] = @benchmarkable cholinv($(Diagonal(ones(T, dim)))) - SUITE["cholsqrt-" *"Type:Diagonal{"*string(T)*"}"] = @benchmarkable cholsqrt($(Diagonal(ones(T, dim)))) - SUITE["chollogdet-" *"Type:Diagonal{"*string(T)*"}"] = @benchmarkable chollogdet($(Diagonal(ones(T, dim)))) - SUITE["cholinv_logdet-"*"Type:Diagonal{"*string(T)*"}"] = @benchmarkable cholinv_logdet($(Diagonal(ones(T, dim)))) - + SUITE[string(T)]["Diagonal"]["dim:" * string(dim)]["fastcholesky"]= @benchmarkable fastcholesky($(Diagonal(ones(T, dim)))) + SUITE[string(T)]["Diagonal"]["dim:" * string(dim)]["cholinv"] = @benchmarkable cholinv($(Diagonal(ones(T, dim)))) + SUITE[string(T)]["Diagonal"]["dim:" * string(dim)]["cholsqrt"] = @benchmarkable cholsqrt($(Diagonal(ones(T, dim)))) + SUITE[string(T)]["Diagonal"]["dim:" * string(dim)]["chollogdet"] = @benchmarkable chollogdet($(Diagonal(ones(T, dim)))) + SUITE[string(T)]["Diagonal"]["dim:" * string(dim)]["cholinv_logdet"] = @benchmarkable cholinv_logdet($(Diagonal(ones(T, dim)))) end - end +SUITE["UniformScaling"] = BenchmarkGroup() + # Uniformscaling benchmarks -SUITE["fastcholesky-" *"Type:UniformScaling"] = @benchmarkable fastcholesky($(3.0I)) -SUITE["fastcholesky!-" *"Type:UniformScaling"] = @benchmarkable fastcholesky!($(3.0I)) -SUITE["cholinv-" *"Type:UniformScaling"] = @benchmarkable cholinv($(3.0I)) -SUITE["cholsqrt-" *"Type:UniformScaling"] = @benchmarkable cholsqrt($(3.0I)) +SUITE["UniformScaling"]["fastcholesky"] = @benchmarkable fastcholesky($(3.0I)) +SUITE["UniformScaling"]["fastcholesky!"] = @benchmarkable fastcholesky!($(3.0I)) +SUITE["UniformScaling"]["cholinv"] = @benchmarkable cholinv($(3.0I)) +SUITE["UniformScaling"]["cholsqrt"] = @benchmarkable cholsqrt($(3.0I)) From df7b7d5556f3ea08158af0a676aa288247c66320 Mon Sep 17 00:00:00 2001 From: Bagaev Dmitry Date: Fri, 24 Nov 2023 12:56:53 +0100 Subject: [PATCH 14/14] change the definition of fastcholesky for numbers and uniform scaling --- src/FastCholesky.jl | 16 ++++++++++++---- test/fastcholesky_tests.jl | 7 ++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/FastCholesky.jl b/src/FastCholesky.jl index 73cb747..789ecc2 100644 --- a/src/FastCholesky.jl +++ b/src/FastCholesky.jl @@ -32,13 +32,21 @@ function fastcholesky(input::AbstractMatrix) # The `PositiveFactorizations.default_δ` should small enough in majority of the cases return cholesky(PositiveFactorizations.Positive, Hermitian(input), tol = PositiveFactorizations.default_δ(input)) end + +fastcholesky(input::Number) = cholesky(input) fastcholesky(input::Diagonal) = cholesky(input) fastcholesky(input::Hermitian) = cholesky(PositiveFactorizations.Positive, input) -fastcholesky(input::Number) = input -fastcholesky!(input::Number) = input -fastcholesky(x::UniformScaling) = sqrt(x.λ) * I -fastcholesky!(x::UniformScaling) = sqrt(x.λ) * I +function fastcholesky(x::UniformScaling) + return error( + "`fastcholesky` is not defined for `UniformScaling`. The shape is not determined." + ) +end +function fastcholesky!(x::UniformScaling) + return error( + "`fastcholesky!` is not defined for `UniformScaling`. The shape is not determined." + ) +end function fastcholesky(input::Matrix{<:BlasFloat}) C = fastcholesky!(copy(input)) diff --git a/test/fastcholesky_tests.jl b/test/fastcholesky_tests.jl index adfdb18..1692408 100644 --- a/test/fastcholesky_tests.jl +++ b/test/fastcholesky_tests.jl @@ -63,8 +63,8 @@ end @test chollogdet(I) ≈ zero @test all(cholinv_logdet(one * I) .≈ (one * I, zero)) @test_throws ArgumentError chollogdet(two * I) - @test fastcholesky(I) ≈ I - @test fastcholesky!(I) ≈ I + @test_throws ErrorException fastcholesky(I) + @test_throws ErrorException fastcholesky!(I) end end @@ -73,7 +73,8 @@ end for Type in SupportedTypes let number = rand(Type) - @test fastcholesky(number) === number + @test size(fastcholesky(number).L) == (1, 1) + @test all(fastcholesky(number).L .≈ sqrt(number)) @test cholinv(number) ≈ inv(number) @test cholsqrt(number) ≈ sqrt(number) @test chollogdet(number) ≈ logdet(number)