Argument-type declarations normally have no impact on performance: regardless of what argument types (if any) are declared, Julia compiles a specialized version of the function for the actual argument types passed by the caller. For example, calling fib(1) will trigger the compilation of specialized version of fib optimized specifically for Int arguments, which is then re-used if fib(7) or fib(15) are called.
The provided example:
fib(n::Integer) = n ≤ 2 ? one(n) : fib(n-1) fib(n-2)
but then in the Performance Tips:
# This will not specialize:
function f_type(t) # or t::Type
x = ones(t, 10)
return sum(map(sin, x))
end
From my understanding of the performance tips, with or without type annotations fib(b::Integer)
or fib(b)
shouldn't specialize specifically for Int
arguments.
It seems with or without the type annotation no specialization will happen, but why does the manual seem to indicate that it will specialize?
CodePudding user response:
The example in the Performance Tips page is about the specific case where you pass the type itself as the argument to the function. As the beginning of that section says:
Julia avoids automatically specializing on argument type parameters in three specific cases:
Type
,Function
, andVararg
f_type
in that example is a function that accepts a Type
t, and will be called as, for eg., f_type(Int)
. The section says that type specialization isn't done based on the Int
type in this case, where the Int
is passed as a value of the parameter itself (and then passed through to another function).
This doesn't apply to the fib
method (or most methods we normally define). fib
accepts a value whose type is (a subtype of) Integer
, not the type itself. In such cases, a call like fib(1)
or fib(UInt8(2))
does create type-specialized compiled versions of the function.
CodePudding user response:
In layman words, Julia will always specialize on function arguments either with or without annotation, except in three cases. One of them is when the arguments are passed to another function, since specializing twice will slow compilation down, and it will finally be specialized at the inner function call, so no performance hit occurs.
So, fib(n:Int)
is equivalent to fib(n)
and both will use a specialized compiled version of the function for the Int64
type unless n
is already of a different type than Int64
, it will specialize for that type.