-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
typeof(...) in Core failed to infer error in @code_warntype
#49197
Comments
@code_warntype
@code_warntype
. Native float instruction allocates 16-bytes?
Ok, the problem with allocations are due to the missing interpolation in the
is still strange to me. julia> foo(x) = x
foo (generic function with 1 method)
julia> @code_warntype typeof(foo(1))
typeof(...) in Core
failed to infer
julia> bar(x) = typeof(foo(x))
bar (generic function with 1 method)
julia> @code_warntype bar(1)
MethodInstance for bar(::Int64)
from bar(x) in Main at REPL[8]:1
Arguments
#self#::Core.Const(bar)
x::Int64
Body::Type{Int64}
1 ─ %1 = Main.foo(x)::Int64
│ %2 = Main.typeof(%1)::Core.Const(Int64)
└── return %2 |
@code_warntype
. Native float instruction allocates 16-bytes?@code_warntype
typeof is a builtin function, so it can't be "inferred". The error message text for that is awkward though, since it is the same for anything that fails here for any reason |
Yeah, the error message misleaded me, and it combined with the fact that I forgot converter = TypeConverter(Float32)
@test @inferred(typeof(converter(T)(1.0))) === T shows me
So I called the |
I don't see how this is related to #15276 or #47760. However, what motivated your issue is that julia> foo(::Type{T}, x) where T = map(e -> convert(T, e), x)
foo(x) = map(e -> convert(Float64, e), x)
foo (generic function with 2 methods)
julia> x = ones(100)
@btime foo($x)
@btime foo(Float64, $x);
49.011 ns (1 allocation: 896 bytes)
49.848 ns (1 allocation: 896 bytes) Of course, it makes more sense to define |
I agree with you. That indeed fixes the problem, but the motivation for my issue was from a larger context and I only showed a minimal working example. In the real code it is more closer (though still not exactly) to: function foo(x, y)
T = eltype(y)
return map(e -> convert(T, e), x)
end
foo(x) = map(e -> convert(Float64, e), x) julia> @btime foo($x);
34.072 ns (1 allocation: 896 bytes)
julia> @btime foo($x, $y);
7.583 μs (104 allocations: 2.52 KiB) It's just too much of a footgun for many Julia developers and I still think it is related. In simple cases yes, I can fix it easily with explicit type specialization. Even in the code above I can replace The real issue here was that I couldn't really test my implementation because in the process |
Okay, I see what's going on. Yes, it's a type system performance footgun relating to closures, but it's not related to unnecessary boxing (the anonymous function's When constructing the anonymous function, the struct's type parameter is julia> f = let T=Float64
e -> convert(T, e)
end
typeof(f)
var"#31#32"{DataType} As you can see, you cannot tell One workaround is to construct a julia> foo(x, y) = let T=Returns(eltype(y))
map(e -> convert(T(), e), x)
end
foo(x) = foo(x, Vector{Float64})
foo (generic function with 2 methods)
julia> x = ones(100)
y = ones(100)
@btime foo($x)
@btime foo($x, $y);
47.720 ns (1 allocation: 896 bytes)
47.533 ns (1 allocation: 896 bytes) |
Maybe the question to ask here is: When a closure captures a local variable, should its constructor call the default vanilla |
I think that this question is out of the scope of the issue here. It has been and is being discussed in many places. |
The issue after the discussion
The
@code_warntype typeof(1)
gives an uninformative error message.The original issue
Consider we write a structure:
Works perfectly fine at first glance:
EDIT: missing
$
.The problem is that this code does not really work as I would expect it to and it does allocates (type-instability?):But if I call
@code_warntype
I get this cryptic error message:Interestingly enough,
@code_warntype
does not show any error if I call it directly onconverter(1.0)
and it does inferFloat32
. Why does nottypeof
work in a combination with@code_warntype
?And why does theconverter
call allocates something?If I look at the
@code_native
I also do not see any place where it could allocate:but it does and the code is slow. How could it be that single
fcvt s0, d0
instruction allocate 16 bytes?Motivation
There are a couple of famous issues like #15276 and #47760.
Basically the issue itself slowdowns a code of the form
map(e -> convert(T, e), collection)
.The structure above is an attempt to circumvent this related issue.
Version
I checked on Julia 1.9-rc1. The issue is present there as well.
The text was updated successfully, but these errors were encountered: