我想看看我编写的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
)
@code_lowered
对于理解性能没有用。@code_warntype
最好
基本上是不同的步骤:
源代码->抽象语法树(就像一个人用宏操作的树),诸如循环和条件语句之类的块是树中的分支。您可以通过引用源代码来查看它。
quote
if x>1
x=x-1
end
end
抽象语法树->降低的中间表示形式,我认为最好将其描述为抽象语法列表,
基本上什么也没做,没有优化等。只是树形形式已成为一个列表,其中没有任何子表达式,并且每个临时变量都在自己的行上进行理解。循环和ifs变为各种类型的跳转(如标签和有条件的gotos)
[一些东西变为降低的表示形式,例如end
中的xs[end-1]
变为lastindex(xs)
此降低操作可以提前完成,不需要JIT。这只是语法的转换
对于带有参数@code_lowered f(x)
的某些功能f
,您可以通过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)
为您提供额外的有用的性能注释,突出显示类型不稳定性这是最有用的图层之一。可能仅次于源代码本身。
这是我们输入IR的地方,它变为LLVM。LLVM在内部像一堆中间表示一样经历。LLVM进行了大量自身的优化。例如在这一阶段,各种数学固有常数不断传播。
通过@code_llvm f(x)
访问此>
这是Typed
之后的下一个最有用的阶段。(与本机代码一起使用,取决于您阅读LLVM IR的语言是否比汇编更好或更糟。)>LLVM成为Assembly,基本上是人类可读的机器代码。通过@code_native f(x)
访问此>
此后仅包含机器代码。尽管我怀疑汇编程序通常会被绕过,因为它们是1-1,所以从LLVM转向机器代码。