JuliaSIMD / JuliaSIMD/StrideArrays.jl
Type instability for `PtrArray`s with `--check-bounds=no` and StrideArrays.jl (but not with StrideArraysCore.jl)
- Dominant language
- Julia
- Stars
- 59
- Forks
- 9
- PR merge metrics
- No merged PRs in 30d
Description
When using StrideArrays.jl with Julia v1.11 and `--check-bounds=no`, `PtrArray`s will cause a type instability that only manifests when loading StrideArrays.jl, but not when loading StrideArraysCore.jl.
I know all the arguments for and against `--check-bounds=no`, but this seems to me like it _should_ work (or at least be fixable), which would likely mean that `--check-bounds=no` becomes usable again for us in Trixi-land...
### MWE
For this I used Julia v1.11.3 on a Linux machine.
Install packages first with (only needed once)
```shell
julia --project=. --check-bounds=no -e 'using Pkg; Pkg.add(["StrideArrays", "StrideArraysCore"])'
```
This currently install StrideArrays.jl v0.1.29 with StrideArraysCore.jl v0.5.7.
Then, start the Julia REPL with `julia --project=. --check-bounds=no` and execute either
```julia
using StrideArraysCore: PtrArray, StaticInt
_u = zeros(1)
u = PtrArray(pointer(_u), (StaticInt(1),))
@code_warntype u[1]
```
or
```julia
using StrideArrays: PtrArray, StaticInt
_u = zeros(1)
u = PtrArray(pointer(_u), (StaticInt(1),))
@code_warntype u[1]
```
The first one (with StrideArraysCore.jl) will give you
```julia-repl
MethodInstance for getindex(::PtrArray{Float64, 1, (1,), Tuple{StaticInt{1}}, Tuple{Nothing}, Tuple{StaticInt{1}}}, ::Int64)
from getindex(A::PtrArray{T, 1}, i::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8, StaticInt}) where T @ StrideArraysCore ~/.julia/packages/StrideArraysCore/Yyyvt/src/ptr_array.jl:1035
Static Parameters
T = Float64
Arguments
#self#::Core.Const(getindex)
A::PtrArray{Float64, 1, (1,), Tuple{StaticInt{1}}, Tuple{Nothing}, Tuple{StaticInt{1}}}
i::Int64
Body::Float64
1 ─ nothing
│ %2 = $(Expr(:boundscheck))::Bool
└── goto #3 if not %2
2 ─ %4 = StrideArraysCore.checkbounds::Core.Const(checkbounds)
└── (%4)(A, i)
3 ┄ %6 = StrideArraysCore.unsafe_getindex(A, i)::Float64
└── return %6
```
while the second one will give you
```julia-repl
MethodInstance for getindex(::PtrArray{Float64, 1, (1,), Tuple{StaticInt{1}}, Tuple{Nothing}, Tuple{StaticInt{1}}}, ::Int64)
from getindex(A::PtrArray{T, 1}, i::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8, StaticInt}) where T @ StrideArraysCore ~/.julia/packages/StrideArraysCore/Yyyvt/src/ptr_array.jl:1035
Static Parameters
T = Float64
Arguments
#self#::Core.Const(getindex)
A::PtrArray{Float64, 1, (1,), Tuple{StaticInt{1}}, Tuple{Nothing}, Tuple{StaticInt{1}}}
i::Int64
Body::Any
1 ─ nothing
│ %2 = $(Expr(:boundscheck))::Bool
└── goto #3 if not %2
2 ─ %4 = StrideArraysCore.checkbounds::Core.Const(checkbounds)
└── (%4)(A, i)
3 ┄ %6 = StrideArraysCore.unsafe_getindex(A, i)::Any
└── return %6
```
That is, in the second version `StrideArraysCore.unsafe_getindex(A, i)::Any` is type unstable.
Note that you need to execute Julia in between, since once you've loaded StrideArrays.jl, there's no going back.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reproducing the two MWE variants with Julia 1.11 and --check-bounds=no, then compare the StrideArrays and StrideArraysCore loading paths. Inspect ptr_array.jl around line 1035 and the unsafe_getindex call shown by @code_warntype. Done means the StrideArrays variant retains a concrete inferred result like the StrideArraysCore variant.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- julia
- Domain
- performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100