-
Notifications
You must be signed in to change notification settings - Fork 152
docfix reinterpret #502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docfix reinterpret #502
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -241,16 +241,62 @@ Another common way of storing the same data is as a 3×`N` `Matrix{Float64}`. | |
Rather conveniently, such types have *exactly* the same binary layout in memory, | ||
and therefore we can use `reinterpret` to convert between the two formats | ||
```julia | ||
function svectors(x::Matrix{Float64}) | ||
@assert size(x,1) == 3 | ||
reinterpret(SVector{3,Float64}, x, (size(x,2),)) | ||
function svectors(x::Matrix{T}, ::Val{N}) where {T,N} | ||
size(x,1) == N || throw("sizes mismatch") | ||
isbitstype(T) || throw("use for bitstypes only") | ||
reinterpret(SVector{N,T}, reshape(x, length(x))) | ||
end | ||
``` | ||
Such a conversion does not copy the data, rather it refers to the *same* memory | ||
referenced by two different Julia `Array`s. Arguably, a `Vector` of `SVector`s | ||
is preferable to a `Matrix` because (a) it provides a better abstraction of the | ||
objects contained in the array and (b) it allows the fast *StaticArrays* methods | ||
to act on elements. | ||
Such a conversion does not copy the data, rather it refers to the *same* memory. | ||
Arguably, a `Vector` of `SVector`s is often preferable to a `Matrix` because | ||
(a) it provides a better abstraction of the objects contained in the array and | ||
(b) it allows the fast *StaticArrays* methods to act on elements | ||
|
||
However, the resulting object is a Base.ReinterpretArray, not an Array, which may carry some | ||
runtime penalty on every single access. If you can afford the memory for a copy and can live with | ||
the non-shared mutation semantics, then it is better to pull a copy by e.g. | ||
```julia | ||
function svectorscopy(x::Matrix{T}, ::Val{N}) where {T,N} | ||
size(x,1) == N || throw("sizes mismatch") | ||
isbitstype(T) || throw("use for bitstypes only") | ||
res = Vector{SVector{N,T}}(undef, size(x,2)) | ||
GC.@preserve res x ccall(:memcpy, Ptr{Cvoid}, (Ptr{Cvoid}, Ptr{Cvoid}, Csize_t), pointer(res), pointer(x), sizeof(x)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems unnecessarily low level for the documentation. How about simply using
If you do think we need this low level optimization perhaps we should be providing some version of |
||
return res | ||
end | ||
``` | ||
For example: | ||
``` | ||
julia> M=reshape(collect(1:6), (2,3)) | ||
2×3 Array{Int64,2}: | ||
1 3 5 | ||
2 4 6 | ||
|
||
julia> svectors(M, Val{2}()) | ||
3-element reinterpret(SArray{Tuple{2},Int64,1,2}, ::Array{Int64,1}): | ||
[1, 2] | ||
[3, 4] | ||
[5, 6] | ||
|
||
julia> svectorscopy(M, Val{2}()) | ||
3-element Array{SArray{Tuple{2},Int64,1,2},1}: | ||
[1, 2] | ||
[3, 4] | ||
[5, 6] | ||
``` | ||
If applications absolutely insist on obtaining a `Vector{<:SVector}` referencing the same memory, | ||
then this is possible by directly calling into the runtime. However, starting from | ||
Julia 0.7 and 1.0, this violates the language specifications about aliasing | ||
(Arrays with different `eltype` must not share memory), and is to be considered a dirty hack. | ||
This is nevertheless safe on 1.0.* or earlier versions of the Julia compiler, but will violate | ||
compiler assumptions on Julia 1.1 or later, and cause subtle data-corrupting miscompilation bugs. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is so broken, let's not suggest doing it in the docs! (I suggest we just delete this section ;-) ) |
||
```julia | ||
function unmaintainable_svectors(x::Matrix{T}, ::Val{N}) where {T,N} | ||
size(x,1) == N || throw("sizes mismatch") | ||
isbitstype(T) || throw("use for bitstypes only") | ||
ccall(:jl_reshape_array, Vector{SVector{N,T}}, (Any,Any,Any), Vector{SVector{N,T}}, x, (size(x,2),)) | ||
end | ||
``` | ||
|
||
|
||
### Working with mutable and immutable arrays | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use
vec(x)
rather than reshape here.