Skip to content

Commit 7bd7cdb

Browse files
authored
Merge branch 'JuliaArrays:master' into master
2 parents 184150e + 563adeb commit 7bd7cdb

File tree

4 files changed

+33
-2
lines changed

4 files changed

+33
-2
lines changed

docs/src/index.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,18 @@ as [`SizedArray`](@ref) for annotating standard `Array`s with static size inform
1515
Further, the abstract [`FieldVector`](@ref) can be used to make fast static vectors
1616
out of any uniform Julia "struct".
1717

18+
## When Static Arrays may be useful
19+
20+
When a program uses many small ($\lesssim 100$ elements) fixed-sized arrays (whose size is known by the compiler, i.e. "statically," when the performance-critical code is compiled), then using Static Arrays can have several performance advantages:
21+
22+
1. Completely unrolling to loop-free code. e.g. `v3 = v1 + v2` is just implemented as 3 scalar additions, with no loop overhead at all, if these are all `SVector{3, Float64}`. The unrolled loops can also sometimes trigger SIMD optimizations.
23+
2. Avoiding heap (or even stack) allocations of temporary arrays. This is related to point (1) — working with static arrays as local variables is *as if* you had just written out all of the scalar operations by hand on all the components.
24+
3. Being stored "inline" in other data structures. e.g. a length-$N$ array `Vector{SVector{3, Float64}}`, such as `[v1, v2, v3]` from the `SVector`s in the previous example, is stored as $3N$ *consecutive* `Float64` values. This is *much* more efficient to access than a `Vector{Vector{Float64}}`, which is essentially an array of pointers to `Vector{Float64}` arrays, and is often faster and more convenient than a $3 \times N$ `Matrix{Float64}` (e.g. because the length 3 is stored in the type you get the benefits of (1) and (2) when accessing vectors in the array, and no "slicing" or "views" are needed). (There is also [HybridArrays.jl](https://github.com/JuliaArrays/HybridArrays.jl) for matrices with a static number of rows.)
25+
26+
## When Static Arrays may be less useful
27+
28+
You probably don't want to use Static Arrays if:
29+
30+
1. The size of the array is not static. For example, if it is changing too rapidly at runtime to make it worthwhile to recompile (and/or dynamically dispatch) the code every time the size changes. (Such as when you have a collection of vectors of many different lengths.)
31+
2. The size of the array is large ($\gg 100$ elements) You (1) don't want to unroll vector operations of long lengths because the code size explodes; (2) they need to be heap-allocated because you can't store them in registers or perhaps even on the stack; and (3) you can already get many of the benefits of "inline" storage in arrays by storing them as the columns of a `Matrix`, whereas you wouldn't want to store a large array inline in an arbitrary `struct`.
32+
3. Working with the array is not performance critical — static arrays are a little less convenient to work with than an ordinary `Array` (because the size of the former is a constant encoded in the type), and it may not be worth the inconvenience for cases where performance is not paramount.

src/SDiagonal.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ SDiagonal(x...) = Diagonal(SVector(x...))
1414
SDiagonal(a::SVector) = Diagonal(a)
1515
SDiagonal(a::StaticMatrix{N,N,T}) where {N,T} = Diagonal(diag(a))
1616

17-
size(::Type{<:SDiagonal{N}}) where {N} = (N,N)
18-
size(::Type{<:SDiagonal{N}}, d::Int) where {N} = d > 2 ? 1 : N
17+
size(::Type{SDiagonal{N}}) where {N} = (N,N)
18+
size(::Type{SDiagonal{N,T}}) where {N,T} = (N,N)
19+
size(::Type{SDiagonal{N}}, d::Int) where {N} = d > 2 ? 1 : N
20+
size(::Type{SDiagonal{N,T}}, d::Int) where {N,T} = d > 2 ? 1 : N
1921

2022
# define specific methods to avoid allocating mutable arrays
2123
\(D::SDiagonal, b::AbstractVector) = D.diag .\ b

src/mapreduce.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ enumerate_static(a::StaticArray) = StaticEnumerate(a)
110110
end
111111
end
112112

113+
if VERSION >= v"1.12.0-beta3"
114+
@inline function map!(f, dest::StaticArray)
115+
_map!(f, dest, Size(dest), dest)
116+
end
117+
end
118+
113119
@inline function map!(f, dest::StaticArray, a::StaticArray...)
114120
_map!(f, dest, same_size(dest, a...), a...)
115121
end

test/mapreduce.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ using Statistics: mean
3131
map!(+, mv3, v1, v2, v3)
3232
@test mv3 == @MVector [7, 9, 11, 13]
3333

34+
if VERSION >= v"1.12.0-beta3"
35+
@testset "map!(function, array)" begin
36+
local mv = MVector(1,2,3)
37+
map!(x->x^2, mv)
38+
@test mv == SA[1,4,9]
39+
end
40+
end
41+
3442
# Output eltype for empty cases #528
3543
@test @inferred(map(/, SVector{0,Int}(), SVector{0,Int}())) === SVector{0,Float64}()
3644
@test @inferred(map(+, SVector{0,Int}(), SVector{0,Float32}())) === SVector{0,Float32}()

0 commit comments

Comments
 (0)