4

是低效的关于前一个问题我问的多,使用多个内核,使程序运行速度更快,有人告诉我:我如何找出我的代码部分在Python

更多通常情况下,你可以得到100倍+优化具有更好的代码相比提高了4倍和额外的复杂性与多处理

然后,他们建议我应该:

使用分析器了解什么是缓慢的,然后专注于优化。

所以我去了这样一个问题:How can you profile a script?

在这里,我发现cProfile并实现它变成一些测试代码,看看它是如何工作的。

这是我的代码:

import cProfile 

def foo(): 
    for i in range(10000): 
     a = i**i 
     if i % 1000 == 0: 
      print(i) 

cProfile.run('foo()') 

然而,它运行后,这是我得到了什么:

0 
1000 
2000 
3000 
4000 
5000 
6000 
7000 
8000 
9000 
     1018 function calls in 20.773 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 20.773 20.773 <string>:1(<module>) 
     147 0.000 0.000 0.000 0.000 rpc.py:150(debug) 
     21 0.000 0.000 0.050 0.002 rpc.py:213(remotecall) 
     21 0.000 0.000 0.002 0.000 rpc.py:223(asynccall) 
     21 0.000 0.000 0.048 0.002 rpc.py:243(asyncreturn) 
     21 0.000 0.000 0.000 0.000 rpc.py:249(decoderesponse) 
     21 0.000 0.000 0.048 0.002 rpc.py:287(getresponse) 
     21 0.000 0.000 0.000 0.000 rpc.py:295(_proxify) 
     21 0.001 0.000 0.048 0.002 rpc.py:303(_getresponse) 
     21 0.000 0.000 0.000 0.000 rpc.py:325(newseq) 
     21 0.000 0.000 0.002 0.000 rpc.py:329(putmessage) 
     21 0.000 0.000 0.000 0.000 rpc.py:55(dumps) 
     20 0.000 0.000 0.001 0.000 rpc.py:556(__getattr__) 
     1 0.000 0.000 0.001 0.001 rpc.py:574(__getmethods) 
     20 0.000 0.000 0.000 0.000 rpc.py:598(__init__) 
     20 0.000 0.000 0.050 0.002 rpc.py:603(__call__) 
     20 0.000 0.000 0.051 0.003 run.py:340(write) 
     1 20.722 20.722 20.773 20.773 test.py:3(foo) 
     42 0.000 0.000 0.000 0.000 threading.py:1226(current_thread) 
     21 0.000 0.000 0.000 0.000 threading.py:215(__init__) 
     21 0.000 0.000 0.047 0.002 threading.py:263(wait) 
     21 0.000 0.000 0.000 0.000 threading.py:74(RLock) 
     21 0.000 0.000 0.000 0.000 {built-in method _struct.pack} 
     21 0.000 0.000 0.000 0.000 {built-in method _thread.allocate_lock} 
     42 0.000 0.000 0.000 0.000 {built-in method _thread.get_ident} 
     1 0.000 0.000 20.773 20.773 {built-in method builtins.exec} 
     42 0.000 0.000 0.000 0.000 {built-in method builtins.isinstance} 
     63 0.000 0.000 0.000 0.000 {built-in method builtins.len} 
     10 0.000 0.000 0.051 0.005 {built-in method builtins.print} 
     21 0.000 0.000 0.000 0.000 {built-in method select.select} 
     21 0.000 0.000 0.000 0.000 {method '_acquire_restore' of '_thread.RLock' objects} 
     21 0.000 0.000 0.000 0.000 {method '_is_owned' of '_thread.RLock' objects} 
     21 0.000 0.000 0.000 0.000 {method '_release_save' of '_thread.RLock' objects} 
     21 0.000 0.000 0.000 0.000 {method 'acquire' of '_thread.RLock' objects} 
     42 0.047 0.001 0.047 0.001 {method 'acquire' of '_thread.lock' objects} 
     21 0.000 0.000 0.000 0.000 {method 'append' of 'collections.deque' objects} 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
     21 0.000 0.000 0.000 0.000 {method 'dump' of '_pickle.Pickler' objects} 
     20 0.000 0.000 0.000 0.000 {method 'get' of 'dict' objects} 
     21 0.000 0.000 0.000 0.000 {method 'getvalue' of '_io.BytesIO' objects} 
     21 0.000 0.000 0.000 0.000 {method 'release' of '_thread.RLock' objects} 
     21 0.001 0.000 0.001 0.000 {method 'send' of '_socket.socket' objects} 

我期待它给我看正在采取的部分我的代码最长的,例如它表明a = i**i计算时间最长,但是我所能告诉我的是,函数花费了最长的时间,但是从函数中获取的时间最长,我不知道数据。

此外,当我将其实现到我的实际代码中时,它会执行相同的操作。一切都在功能上,它只告诉我哪些功能花费的时间最长,而不是功能花费那么长时间。

因此,这里是我的主要问题:

  1. 如何查看里面的功能是什么使代码需要很长时间

  2. 是什么(应我甚至使用cProfile?)一旦我知道什么是使用最多的CPU,设置优化我的代码的最佳方法

注:我的内存和硬盘等都是精美绝伦,它只是被刷爆的CPU(12%的CPU,因为它仅在单核上运行)

+0

打印花费的时间比您想象的要长得多。考虑没有I/O的性能分析函数 –

+1

@ Jean-FrançoisFabre你的意思是没有I/O的性能分析函数是什么意思?而且它只打印10次,对吧? –

+0

你是对的。我的不好 –

回答

8

我怎么看到里面的功能使代码这么长的时间(应我甚至使用CPROFILE?)

是的,你可以使用cProfile但你问的问题的方式使我怀疑line_profiler(第三方模块,你需要安装它)止跌不是一个更好的工具。

我使用这个包的IPython的/ Jupyter绑定,当我要分析的功能:

%load_ext line_profiler 

要实际配置文件的功能:

%lprun -f foo foo() 
#    ^^^^^---- this call will be profiled 
#   ^^^-----------function to profile 

将会产生这样的输出:

Timer unit: 5.58547e-07 s 

Total time: 17.1189 s 
File: <ipython-input-1-21b5a5f52f66> 
Function: foo at line 1 

Line #  Hits   Time Per Hit % Time Line Contents 
============================================================== 
    1           def foo(): 
    2  10001  31906  3.2  0.1  for i in range(10000): 
    3  10000  30534065 3053.4  99.6   a = i**i 
    4  10000  75998  7.6  0.2   if i % 1000 == 0: 
    5  10   6953 695.3  0.0    print(i) 

这包括几个可能有趣的事情。例如99.6%的时间用在i**i行。

  • 什么是着手优化我的代码的最佳方式,一旦我知道什么是使用最CPU
  • 那要看情况。有时你需要使用不同的功能/数据结构/算法 - 有时你什么都做不了。但至少你知道你的瓶颈在哪里,你可以估计在瓶颈或别的地方会有什么变化。

    +0

    令人惊叹的答案!所以,当我调用函数%lprun -f foo foo() –

    +0

    @RulerOfTheWorld时,我将它放入代码中不确定你的意思。你的意思是如何在没有IPython/Jupyter的情况下进行配置文件? – MSeifert

    +1

    'line_profiler'不依赖于Ipython或Jupyter。你可以在想要分析的函数上使用'@ profile'装饰器,将'kernprof.py'和'line_profiler.py'文件复制/粘贴到脚本所在的文件夹并运行'python kernprof.py -l - v my_script.py> output_file.txt'。这将输出一个定时文本文件。我没有成功地做到这一点,没有复制/粘贴源文件,但它复制它们是微不足道的。 – roganjosh

    2

    正如您在分析日志中已经注意到的那样,cProfile的最大分辨率是函数

    所以:

    • 如果你的函数是小你可以找出哪些部分占用了很长的时间(尽管它有时像in内置通话困难)
    • 如果你的函数是大的,也许是时候把它缩减为更小的功能,这些功能变得“可配置”,但功能调用开销可能会减慢速度
    相关问题