From b48d39d9b2664b04a038c61e6ead78b37023acf6 Mon Sep 17 00:00:00 2001 From: odow Date: Fri, 4 Dec 2020 09:50:34 +1300 Subject: [PATCH 1/2] Add a work-around on Julia 1.0 for #857 `StaticVecOrMatLike` is a very large union, and this caused Julia 1.0.x to use a large amount of memory when compiling StaticArrays in the presence of other packages that also extend `LinearAlgebra.mul!` in a similar fashion. As an example, this led to JuMP using more than 4 GB of RAM when running `using JuMP`, causing its CI to crash. Computing the eltypes within the function, rather than specifying them in the type arguments greatly improves the issue, with `using JuMP` going from: julia> @time using JuMP [ Info: Precompiling JuMP [4076af6c-e467-56ae-b986-b466b2749572] Killed to: julia> @time using JuMP [ Info: Precompiling JuMP [4076af6c-e467-56ae-b986-b466b2749572] 97.868305 seconds (12.75 M allocations: 805.413 MiB, 0.30% gc time) --- src/matrix_multiply_add.jl | 48 +++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/src/matrix_multiply_add.jl b/src/matrix_multiply_add.jl index 5d25483b..3805de7b 100644 --- a/src/matrix_multiply_add.jl +++ b/src/matrix_multiply_add.jl @@ -218,13 +218,45 @@ const StaticVecOrMatLikeForFiveArgMulDest{T} = Union{ α::Number, β::Number) = _mul!(TSize(dest), mul_parent(dest), Size(A), Size(B), A, B, AlphaBeta(α,β)) -@inline function LinearAlgebra.mul!(dest::StaticVecOrMatLike{TDest}, A::StaticVecOrMatLike{TA}, - B::StaticVecOrMatLike{TB}) where {TDest,TA,TB} - TMul = promote_op(matprod, TA, TB) - return _mul!(TSize(dest), mul_parent(dest), Size(A), Size(B), A, B, NoMulAdd{TMul, TDest}()) +if VERSION < v"1.1" + # See https://github.com/JuliaArrays/StaticArrays.jl/issues/857. + # `StaticVecOrMatLike` is a very large union, and this caused Julia 1.0.x to + # use a large amount of memory when compiling StaticArrays in the presence + # of other packages that also extend `LinearAlgebra.mul!` in a similar + # fashion. As an example, this led to JuMP using more than 4 GB of RAM when + # running `using JuMP`, causing its CI to crash. + # + # Computing the eltypes within the function, rather than specifying them in + # the type arguments greatly improves the issue, with `using JuMP` going + # from: + # julia> @time using JuMP + # [ Info: Precompiling JuMP [4076af6c-e467-56ae-b986-b466b2749572] + # Killed + # to: + # julia> @time using JuMP + # [ Info: Precompiling JuMP [4076af6c-e467-56ae-b986-b466b2749572] + # 97.868305 seconds (12.75 M allocations: 805.413 MiB, 0.30% gc time) + @inline _eltype(::StaticVecOrMatLike{T}) where {T} = T + @inline function LinearAlgebra.mul!( + dest::StaticVecOrMatLike, + A::StaticVecOrMatLike, + B::StaticVecOrMatLike, + ) + TDest, TA, TB = _eltype(dest), _eltype(A), _eltype(B) + TMul = promote_op(matprod, TA, TB) + return _mul!(TSize(dest), mul_parent(dest), Size(A), Size(B), A, B, NoMulAdd{TMul, TDest}()) + end +else + @inline function LinearAlgebra.mul!( + dest::StaticVecOrMatLike{TDest}, + A::StaticVecOrMatLike{TA}, + B::StaticVecOrMatLike{TB}, + ) where {TDest,TA,TB} + TMul = promote_op(matprod, TA, TB) + return _mul!(TSize(dest), mul_parent(dest), Size(A), Size(B), A, B, NoMulAdd{TMul, TDest}()) + end end - "Calculate the product of the dimensions being multiplied. Useful as a heuristic for unrolling." @inline multiplied_dimension(A::Type{<:StaticVecOrMatLike}, B::Type{<:StaticVecOrMatLike}) = prod(size(A)) * size(B,2) @@ -310,7 +342,7 @@ function uplo_access(sa, asym, k, j, uplo) elseif uplo == :unit_lower_triangular if k > j return :($asym[$(LinearIndices(sa)[k, j])]) - elseif k == j + elseif k == j return :(oneunit($TAsym)) else return :(zero($TAsym)) @@ -439,7 +471,7 @@ end else ab = [:(a[$i] * transpose(b[$j])) for i = 1:sa[1], j = 1:sb[2]] end - + exprs = _muladd_expr(lhs, ab, _add) return quote @@ -558,7 +590,7 @@ end @inbounds $(Expr(:block, exprs...)) end end - + return quote @_inline_meta α = alpha(_add) From 314f3bbdcc1c9417fdf738710c79343ad4318fc5 Mon Sep 17 00:00:00 2001 From: odow Date: Sat, 5 Dec 2020 16:35:55 +1300 Subject: [PATCH 2/2] Remove Julia 1.0 branch in favor of single implementation --- Project.toml | 2 +- src/matrix_multiply_add.jl | 62 +++++++++++++++----------------------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/Project.toml b/Project.toml index 78120df1..7673c672 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "StaticArrays" uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.0.0" +version = "1.0.1" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/src/matrix_multiply_add.jl b/src/matrix_multiply_add.jl index 3805de7b..d04af8a1 100644 --- a/src/matrix_multiply_add.jl +++ b/src/matrix_multiply_add.jl @@ -218,43 +218,31 @@ const StaticVecOrMatLikeForFiveArgMulDest{T} = Union{ α::Number, β::Number) = _mul!(TSize(dest), mul_parent(dest), Size(A), Size(B), A, B, AlphaBeta(α,β)) -if VERSION < v"1.1" - # See https://github.com/JuliaArrays/StaticArrays.jl/issues/857. - # `StaticVecOrMatLike` is a very large union, and this caused Julia 1.0.x to - # use a large amount of memory when compiling StaticArrays in the presence - # of other packages that also extend `LinearAlgebra.mul!` in a similar - # fashion. As an example, this led to JuMP using more than 4 GB of RAM when - # running `using JuMP`, causing its CI to crash. - # - # Computing the eltypes within the function, rather than specifying them in - # the type arguments greatly improves the issue, with `using JuMP` going - # from: - # julia> @time using JuMP - # [ Info: Precompiling JuMP [4076af6c-e467-56ae-b986-b466b2749572] - # Killed - # to: - # julia> @time using JuMP - # [ Info: Precompiling JuMP [4076af6c-e467-56ae-b986-b466b2749572] - # 97.868305 seconds (12.75 M allocations: 805.413 MiB, 0.30% gc time) - @inline _eltype(::StaticVecOrMatLike{T}) where {T} = T - @inline function LinearAlgebra.mul!( - dest::StaticVecOrMatLike, - A::StaticVecOrMatLike, - B::StaticVecOrMatLike, - ) - TDest, TA, TB = _eltype(dest), _eltype(A), _eltype(B) - TMul = promote_op(matprod, TA, TB) - return _mul!(TSize(dest), mul_parent(dest), Size(A), Size(B), A, B, NoMulAdd{TMul, TDest}()) - end -else - @inline function LinearAlgebra.mul!( - dest::StaticVecOrMatLike{TDest}, - A::StaticVecOrMatLike{TA}, - B::StaticVecOrMatLike{TB}, - ) where {TDest,TA,TB} - TMul = promote_op(matprod, TA, TB) - return _mul!(TSize(dest), mul_parent(dest), Size(A), Size(B), A, B, NoMulAdd{TMul, TDest}()) - end +# See https://github.com/JuliaArrays/StaticArrays.jl/issues/857. +# `StaticVecOrMatLike` is a very large union, and this caused Julia 1.0.x to +# use a large amount of memory when compiling StaticArrays in the presence +# of other packages that also extend `LinearAlgebra.mul!` in a similar +# fashion. As an example, this led to JuMP using more than 4 GB of RAM when +# running `using JuMP`, causing its CI to crash. +# +# Computing the eltypes within the function, rather than specifying them in +# the type arguments greatly improves the issue, with `using JuMP` going +# from: +# julia> @time using JuMP +# [ Info: Precompiling JuMP [4076af6c-e467-56ae-b986-b466b2749572] +# Killed +# to: +# julia> @time using JuMP +# [ Info: Precompiling JuMP [4076af6c-e467-56ae-b986-b466b2749572] +# 101.723598 seconds (12.85 M allocations: 812.902 MiB, 0.31% gc time) +@inline function LinearAlgebra.mul!( + dest::StaticVecOrMatLike, + A::StaticVecOrMatLike, + B::StaticVecOrMatLike, +) + TDest, TA, TB = eltype(dest), eltype(A), eltype(B) + TMul = promote_op(matprod, TA, TB) + return _mul!(TSize(dest), mul_parent(dest), Size(A), Size(B), A, B, NoMulAdd{TMul, TDest}()) end "Calculate the product of the dimensions being multiplied. Useful as a heuristic for unrolling."