使用`@ code_lowered`是解决Julia中性能问题的有效方法吗?

log*_*ick 4 julia

我想看看我编写的Julia代码是否存在任何性能问题。我知道@code_lowered可以很好地了解编译器如何解释代码,但是什么时候才是@code_lowered最有用的。是否有某些性能或其他问题可以很好地突出显示(如果您能理解打印输出),而在其他情况下则没什么用?

我也知道Julia中还有其他很棒的分析工具,我只是想大致了解每种工具的用例。

julia> @code_lowered Int(1.0)
CodeInfo(
1 ? %1  = -9.223372036854776e18 <= x
???       goto #3 if not %1
2 ?       @_3 = x < 9.223372036854776e18
???       goto #4
3 ?       @_3 = false
4 ?       goto #6 if not @_3
5 ? %7  = Base.round(x, Base.RoundToZero)
?         @_4 = %7 == x
???       goto #7
6 ?       @_4 = false
7 ?       goto #9 if not @_4
8 ? %12 = Base.unsafe_trunc(Int64, x)
???       return %12
9 ? %14 = Base.InexactError(:Int64, Int64, x)
?   %15 = Base.throw(%14)
???       return %15
)

Run Code Online (Sandbox Code Playgroud)

Lyn*_*ite 6

@code_lowered对理解性能没有帮助。 @code_warntype是最好的。

基本上是不同的步骤:

解析:

源代码->抽象语法树(就像一个人使用宏进行操作一样),诸如循环和条件语句之类的块是树中的分支。您可以通过引用源代码来查看它。

quote
    if x>1
       x=x-1
    end
end
Run Code Online (Sandbox Code Playgroud)

降低:

抽象同步树->低级中间表示(IR),我认为最好将其描述为抽象语法列表,

基本上没有做任何事情,也没有进行优化等。只是树形形式已经成为一个列表,其中没有任何子表达式,并且每个临时变量都在自己的行上理解。循环和ifs会变成各种类型的跳转(例如标签和有条件的getos)

像有几件事情改变为降低表示endxs[end-1]lastindex(xs)

降低可以完全提前完成,不需要JIT。这只是语法的一种转换

您可以通过@code_lowered f(x)使用farguments的某些函数来访问它x。或者,如果您有一个,Method那么您可以做Base.uncompressed_ast(method)

专业化

利用类型信息,优化器运行。内联事物,删除始终为true或false的条件(例如,检查类型)。降低的IR变为Typed IR。

  • @code_typed f(x) 给你这个。
  • @code_typed optimize=false f(x) 在不运行优化步骤的情况下为您提供了此功能。
  • @code_warntype f(x) 通过突出显示类型不稳定性的额外有用的性能注释为您提供帮助

这是最有用的图层之一。
可能仅次于源代码本身。

代码生成(LLVM)

这是我们输入IR成为LLVM的地方。LLVM在内部像一堆中间表示一样经历。LLVM进行了大量自身的优化。例如,各种数学内在常数在此阶段传播。

通过访问 @code_llvm f(x)

这是Typed之后的下一个最有用的阶段。(与本机代码一起使用,取决于您阅读LLVM IR的结果是否优于汇编语言)。

代码生成(汇编)

LLVM基本上变成了汇编,人类可读的机器代码。通过访问@code_native f(x)

在那之后,仅假设了机器代码。尽管我怀疑汇编程序通常会被绕过,因为它们是1-1,因此从LLVM转向机器代码。


另请参阅https : //stackoverflow.com/a/43456211/179081