JuliaPhysics / JuliaPhysics/Unitful.jl
u"A^(3/2)" fails to infer
- Dominant language
- Julia
- Stars
- 675
- Forks
- 124
- Avg merge
- 3h 38m
- Merged PRs (30d)
- 1
Description
I need to work with some values with non-integer powers, and ran into some issue getting code to run without allocations. I think it's due to an inference failure. In the following example (with Unitful 1.3) I call `Base.literal_pow` explicitly to try to make sure the exponent is known at compile time, and despite this the output of `@code_warntype` shows the return value as `::Any` and `@btime` shows 3 allocation.
Related discourse post: https://discourse.julialang.org/t/calculate-i-a-2-3-with-no-allocations-with-unitful/42998/2
```
julia> I = 1u"A"
1 A
julia> A = 1.0u"A/K^(3/2)"
1.0 A K⁻³ᐟ²
julia> f(I, A) = Base.literal_pow(^,I/A, Val(2//3))
f (generic function with 1 method)
julia> @code_warntype f(I, A)
Variables
#self#::Core.Compiler.Const(f, false)
I::Quantity{Int64,𝐈,Unitful.FreeUnits{(A,),𝐈,nothing}}
A::Quantity{Float64,𝐈 𝚯⁻³ᐟ²,Unitful.FreeUnits{(A, K⁻³ᐟ²),𝐈 𝚯⁻³ᐟ²,nothing}}
Body::Any
1 ─ %1 = Base.literal_pow::Core.Compiler.Const(Base.literal_pow, false)
│ %2 = (I / A)::Quantity{Float64,𝚯³ᐟ²,Unitful.FreeUnits{(K³ᐟ²,),𝚯³ᐟ²,nothing}}
│ %3 = (2 // 3)::Rational{Int64}
│ %4 = Main.Val(%3)::Val{_A} where _A
│ %5 = (%1)(Main.:^, %2, %4)::Any
└── return %5
julia> @btime f($I, $A)
7.500 μs (3 allocations: 64 bytes)
1.0 K
julia> @which Base.literal_pow(^, A, Val(3//2))
literal_pow(::typeof(^), x::Unitful.AbstractQuantity, ::Val{v}) where v in Unitful at /Users/user/.julia/packages/Unitful/MOEUx/src/quantities.jl:461
julia> versioninfo()
Julia Version 1.4.0
Commit b8e9a9ecc6 (2020-03-21 16:36 UTC)
Platform Info:
OS: macOS (x86_64-apple-darwin18.6.0)
CPU: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-8.0.1 (ORCJIT, skylake)
```
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with Unitful/src/quantities.jl around the literal_pow method at line 461, then reproduce the example using Julia 1.4 with @code_warntype and @btime. Trace why Base.literal_pow(^, I/A, Val(2//3)) returns Any and allocations; done means the reported expression has inferred output and no unexpected allocations, with regression coverage if the existing tests provide a suitable location.
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