使用line_profiler与numba即时编译功能

问题描述 投票:2回答:1

是否有可能使用line_profiler与Numba?

上饰有%lprun函数调用@numba.jit返回一个空的个人资料:

Timer unit: 1e-06 s

Total time: 0 s
File: <ipython-input-29-486f0a3cdf73>
Function: conv at line 1

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     1                                           @numba.jit
     2                                           def conv(f, w):
     3                                               f_full = np.zeros(np.int(f.size + (2 * w.size) - 2), dtype=np.float64)
     4                                               for i in range(0, f_full.size):
     5                                                   if i >= w.size - 1 and i < w.size + f.size - 1:
     6                                                       f_full[i] = f[i - w.size + 1]
     7                                               w = w[::-1]
     8                                               g = np.zeros(f_full.size-w.size + 1, dtype=np.float64)
     9                                               for i in range(0, f_full.size - w.size):
    10                                                   g[i] = np.sum(np.multiply(f_full[i:i+w.size], w))
    11                                               return g

还有的用Cython代码的方法,但找不到任何Numba。

python performance profiling numba line-profiler
1个回答
3
投票

TL; DR:线路配置的是numba功能可能不是(在技术上)可能的,但即使是可能的线轮廓A numba函数的结果可能不准确。

与分析器和编译/优化的语言问题

这是复杂的使用与“编译”语言分析器(甚至在一定程度上与这取决于运行时允许做非编译语言),因为编译器被允许重写代码。仅举几个例子:constant foldinginline function callsunroll loops(利用SIMD instructions的),hoisting,一般重新排序/重新排列表达式(甚至多行)。一般来说,编译器被允许,只要做任何事情的结果和副作用"as if"功能不是“优化”。

原理:

+---------------+       +-------------+      +----------+
|  Source file  |   ->  |  Optimizer  |  ->  |  Result  |
+---------------+       +-------------+      +----------+

这是一个问题,因为分析器需要插入语句插入代码,例如函数探查可能在开始和每个函数的开头插入一个说法,可能工作即使代码进行优化,内联函数 - 仅仅是因为在“探查声明”内联为好。但是如果一个编译器决定不内联,因为附加的探查语句的功能?那么你个人资料可能实际上是从如何“真实计划”将执行不同的。

例如,如果你有(我在这里,即使它不是编译使用Python,只是假设我在C写这样的程序或左右):

 def give_me_ten():
     return 10

 def main():
     n = give_me_ten()
     ...

然后,优化可以改写为:

 def main():
     n = 10  # <-- inline the function

但是,如果您插入探查语句:

 def give_me_ten():
     profile_start('give_me_ten')
     n = 10
     profile_end('give_me_ten')
     return n

 def main():
     profile_start('main')
     n = give_me_ten()
     ...
     profile_end('main')

优化器可能只是发出相同的代码,因为它不内联函数。

一条线廓竟插入代码中的很多“探查声明”。比赛一开始,并在每个行的末尾。这可能会阻止很多编译器优化。我不是太熟悉的“为假设”规则,但我的猜测是,很多优化工作是不可能的呢。所以你用分析器编译的程序的行为从编译的程序显著不同而不探查。

例如,如果你有这样的程序:

 def main():
     n = 1
     for _ in range(1000):
         n += 1
     ...

优化器可以(不知道任何编译器会做到这一点),重写为:

 def main():
     n = 1001  # all statements are compile-time constants and no side-effects visible

但是,如果你有行剖析陈述,则:

 def main():
     profile_start('main', line=1)
     n = 1
     profile_end('main', line=1)
     profile_start('main', line=2)
     for _ in range(1000):
         profile_end('main', line=2)
         profile_start('main', line=3)
         n += 1
         profile_end('main', line=3)
         profile_start('main', line=2)
     ...

再由“为假设”统治循环有副作用,不能凝结为单个语句(也许代码仍然可以优化,但不是作为一个单独的语句)。

请注意,这些都是简单的例子,编译器/优化通常是真正成熟,有很多可能的优化。

根据不同的语言,编译器和分析器有可能减轻这些影响。但是,这是不可能的面向Python的分析器(如线分析器)针对C / C ++编译器。

还要注意因为Python只是执行,这不是与Python一个真正的问题的程序真的一步一步(不是真的但是Python非常,很少改变你的“编写的代码”,然后仅在小的方面)。

请问这个适用于Numba和用Cython?

  • 用Cython转换Python代码到C(或C ++)代码,然后使用C(或C ++)编译器编译它。原理: +-------------+ +--------+ +----------+ +-----------+ +--------+ | Source file | -> | Cython | -> | C source | -> | Optimizer | -> | Result | +-------------+ +--------+ +----------+ +-----------+ +--------+
  • Numba转换取决于参数类型Python代码,并使用LLVM编译代码。原理: +-------------+ +-------+ +------------------+ +--------+ | Source file | -> | Numba | -> | LLVM / Optimizer | -> | Result | +-------------+ +-------+ +------------------+ +--------+

两者有一个编译器,可以进行广泛的优化。如果您将剖析语句到你的代码编译它之前很多优化将是不可能的。因此,即使它有可能行分析代码的结果可能不准确(在那个真正的程序将执行这样的意义上准确)。

线路分析器是为纯Python编写的,所以我不一定会相信对于用Cython / Numba输出,如果它的工作。它可能会提供一些提示,但总体而言,它可能只是太不精确。

特别是Numba可能是非常棘手的,因为numba翻译需要支持的分析报表(否则你最终会得到一个对象的模式numba功能,会产生完全不准确的结果),你的即时编译功能不只是一个功能了。它实际上是取决于参数的类型委托给一个“隐藏”功能的调度。所以,当你调用相同的“调度员”与int或者它可以执行一个完全不同的功能float。有趣的事实:与功能探查剖析的行为已经规定显著的开销,因为numba开发商想使这项工作(见cProfile adds significant overhead when calling numba jit functions)。

好了,如何分析呢?

你应该有一个分析器,它可与翻译代码编译器的工作设定档。这些可以(可能)产生比Python代码编写的分析器更准确的结果。这将是更为复杂,因为这些廓线仪将返回有再次手动转移到原代码翻译代码的结果。此外,它可能甚至是不可能的 - 通常用Cython / Numba管理结果的翻译和编译和执行,所以你需要检查,如果他们提供额外的探查挂钩。我没有经验在那里。

而作为一个一般的规则:如果你有优化则始终将成型部作为“指南”并不一定是“事实”。并始终使用而设计的编译器/优化廓线仪,否则你会失去大量的可靠性和/或准确性。

© www.soinside.com 2019 - 2024. All rights reserved.