当类型推断失败时(::Any
在@code_warntype
打印输出中),我的理解是函数调用是动态调度的。换句话说,在运行时,会检查参数的类型以找到MethodInstance
具体参数类型的特化 ( )。需要在运行时而不是编译时执行此操作会导致性能成本。
(编辑:最初,我在类型检查和专业化查找之间说“多次调度找到合适的方法”,但我实际上不知道这部分是否在运行时发生。似乎只有在没有有效的情况下才需要发生存在专业化,需要编译。)
在只需要检查一个参数的具体类型的情况下,是否可以进行更快的动态单次调度,例如在某种专业化查找表中?我只是找不到MethodInstance
像函数一样访问和调用 s 的方法。
当谈到改变调度或专业化时,我想到了invoke
and @nospecialize
。invoke
看起来它可能会直接跳到指定的方法,但仍然必须检查多个参数类型和专业化。@nospecialize
不会跳过调度过程的任何部分,只会导致不同的专业化。
编辑:一个带有评论的最小示例,希望能描述我在说什么。
struct Foo end
struct Bar end
# want to dispatch only on 1st argument
# still want to specialize on 2nd argument
baz(::Foo, ::Integer) = 1
baz(::Foo, ::AbstractFloat) = 1.0
baz(::Bar, ::Integer) = 1im
baz(::Bar, ::AbstractFloat) = 1.0im
x = Any[Foo(), Bar(), Foo()]
# run test1(x, 1) or test1(x, 1.0)
function test1(x, second)
# first::Any in @code_warntype printout
for first in x
# first::Any requires dynamic dispatch of baz
println(baz(first, second))
# Is it possible to only dispatch -baz- on -first- given
# the concrete types of the other arguments -second-?
end
end