Julia 特化与类型推断
Julia 之所以快,并不是因为采用了即时编译(JIT),而是因为函数特化以及类型推断能力。否则,无法解释某些使用了即时编译的函数仍然非常慢。
阐述
每一个 Julia 函数都是一系列不同方法的组合,在调用时会采用根据它的类型采取多重派发机制选择一个最合适的函数调用,并且即时编译生成一个函数,这称为「特化」。当函数嵌套调用的时候,内部函数如果能成功执行类型推断,那么这个函数调用之后的部分也能够静态编译,从而提高效率;反之,如果不能推断类型,就会效率较低。
位于 REPL 顶层的代码无法推断类型。
函数屏障
如果程序在某些地方存在不可避免的类型不稳定情况,那么为了避免它影响密集运算,通常把密集运算包裹在函数之内。由于进入函数的时候肯定会利用类型来特化,这样就可以获得类型稳定的代码。
isbits
函数
isbits
函数可以判断类型是否为纯粹的数据(不包含指针)。编译器通常对这样的类型有比较好的优化。
- 如果 Julia 复合类型里有抽象类型,那它就不再满足这个条件了,所以一般会写成参数化类型,这样每一个类型都满足
- Julia 可变复合类型不满足这个条件
实例
检查类型不稳定问题
可以帮助检验一个函数调用是否发生了类型不稳定的问题。它的输出包括两部分:一部分是局部命名变量的类型,一部分是注释了类型的 Julia SSA IR。
- 具象类型用绿色标注
- Nullable 的 Union 类型(例 如
Union{T, Nothing}
或者Union{T, Missing}
)用黄色标注 - 其他 Julia 抽象类型用红色标注