Project Euler和其他编码竞赛通常有最长的运行时间,或者人们吹嘘他们的特定解决方案运行速度有多快。对于Python,有时方法有些笨拙——即向__main__添加计时代码。

描述Python程序运行时间的好方法是什么?


当前回答

一个很好的评测模块是line_profiler(使用kernprof.py脚本调用)。它可以在这里下载。

我的理解是,cProfile只提供每个函数花费的总时间的信息。因此,单独的代码行是不定时的。这是科学计算中的一个问题,因为通常一条线会花费很多时间。而且,我记得,cProfile没有抓住我在say numpy.dot上花费的时间。

其他回答

python wiki是一个用于分析资源的绝佳页面:http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code

python文档也是如此:http://docs.python.org/library/profile.html

如Chris Lawlor所示,cProfile是一个很棒的工具,可以很容易地打印到屏幕上:

python -m cProfile -s time mine.py <args>

或存档:

python -m cProfile -o output.file mine.py <args>

PS>如果您使用的是Ubuntu,请确保安装python配置文件

apt-get install python-profiler 

如果输出到文件,可以使用以下工具获得良好的可视化效果

PyCallGraph:创建调用图图像的工具安装:

 pip install pycallgraph

run:

 pycallgraph mine.py args

视图:

 gimp pycallgraph.png

你可以使用任何你喜欢的方式来查看png文件,我使用了gimp不幸的是,我经常

dot:graph对于cairo渲染器位图太大。缩放0.257079以适合

这使我的图像变得难以使用。所以我通常创建svg文件:

pycallgraph -f svg -o pycallgraph.svg mine.py <args>

PS>确保安装graphviz(提供点程序):

pip install graphviz

使用gprof2dot通过@maxy/@quodlibetor绘制替代图形:

pip install gprof2dot
python -m cProfile -o profile.pstats mine.py
gprof2dot -f pstats profile.pstats | dot -Tsvg -o mine.svg

获取IPython笔记本上的快速配置文件统计信息。人们可以将line_profiler和memory_profile直接嵌入到笔记本中。

另一个有用的包是Pympler。它是一个强大的评测包,能够跟踪类、对象、函数、内存泄漏等。

了解了!

!pip install line_profiler
!pip install memory_profiler
!pip install pympler

加载它!

%load_ext line_profiler
%load_ext memory_profiler

使用它!


%时间

%time print('Outputs CPU time,Wall Clock time') 
#CPU times: user 2 µs, sys: 0 ns, total: 2 µs Wall time: 5.96 µs

给予:

CPU时间:CPU级执行时间systimes:系统级执行时间总计:CPU时间+系统时间墙上时间:墙上时钟时间


%计时

%timeit -r 7 -n 1000 print('Outputs execution time of the snippet') 
#1000 loops, best of 7: 7.46 ns per loop

给出给定循环次数(n)中的最佳运行次数(r)。输出系统缓存的详细信息:当代码片段被多次执行时,系统会缓存一些操作并不再执行,这可能会影响概要文件报告的准确性。


%普鲁士人

%prun -s cumulative 'Code to profile' 

给予:

函数调用数(ncall)每个函数调用有个条目(不同)每次呼叫所用时间(百分比)到函数调用为止的时间(cumtime)调用的函数/模块的名称等。。。


%记忆,记忆

%memit 'Code to profile'
#peak memory: 199.45 MiB, increment: 0.00 MiB

给予:

内存使用情况


%低压运行

#Example function
def fun():
  for i in range(10):
    print(i)

#Usage: %lprun <name_of_the_function> function
%lprun -f fun fun()

给予:

按行统计


系统大小

sys.getsizeof('code to profile')
# 64 bytes

返回对象的大小(以字节为单位)。


来自pympler的asizeof()

from pympler import asizeof
obj = [1,2,("hey","ha"),3]
print(asizeof.asizeof(obj,stats=4))

pympler.asizeof可用于调查某些Python对象消耗多少内存。与sys.getsizeof不同,asizeof递归地调整对象大小


来自pympler的跟踪器

from pympler import tracker
tr = tracker.SummaryTracker()
def fun():
  li = [1,2,3]
  di = {"ha":"haha","duh":"Umm"}
fun()
tr.print_diff()

跟踪函数的生存期。

Pympler包包含大量用于评测代码的高实用函数。这里无法涵盖所有这些。有关详细的概要文件实现,请参阅随附的文档。

Pympler文档

值得指出的是,使用探查器仅在主线程上有效(默认情况下),如果使用它们,您将无法从其他线程获得任何信息。这可能有点棘手,因为探查器文档中完全没有提到它。

如果您还想评测线程,那么您需要查看文档中的threading.setprofile()函数。

您也可以创建自己的线程.Thread子类:

class ProfiledThread(threading.Thread):
    # Overrides threading.Thread.run()
    def run(self):
        profiler = cProfile.Profile()
        try:
            return profiler.runcall(threading.Thread.run, self)
        finally:
            profiler.dump_stats('myprofile-%d.profile' % (self.ident,))

并使用ProfiledThread类而不是标准类。它可能会给你更多的灵活性,但我不确定它是否值得,特别是如果你使用的是不使用你的类的第三方代码。

我刚刚从pypref_time中开发了自己的分析器:

https://github.com/modaresimr/auto_profiler

更新版本2

安装:

pip install auto_profiler

快速入门:

from auto_profiler import Profiler

with Profiler():
    your_function()

在Jupyter中使用,可以实时查看已用时间

更新版本1

通过添加装饰器,它将显示一个耗时的函数树

@探查器(深度=4)

Install by: pip install auto_profiler

实例

import time # line number 1
import random

from auto_profiler import Profiler, Tree

def f1():
    mysleep(.6+random.random())

def mysleep(t):
    time.sleep(t)

def fact(i):
    f1()
    if(i==1):
        return 1
    return i*fact(i-1)

def main():
    for i in range(5):
        f1()

    fact(3)


with Profiler(depth=4):
    main()

示例输出


Time   [Hits * PerHit] Function name [Called from] [function location]
-----------------------------------------------------------------------
8.974s [1 * 8.974]  main  [auto-profiler/profiler.py:267]  [/test/t2.py:30]
├── 5.954s [5 * 1.191]  f1  [/test/t2.py:34]  [/test/t2.py:14]
│   └── 5.954s [5 * 1.191]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
│       └── 5.954s [5 * 1.191]  <time.sleep>
|
|
|   # The rest is for the example recursive function call fact
└── 3.020s [1 * 3.020]  fact  [/test/t2.py:36]  [/test/t2.py:20]
    ├── 0.849s [1 * 0.849]  f1  [/test/t2.py:21]  [/test/t2.py:14]
    │   └── 0.849s [1 * 0.849]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
    │       └── 0.849s [1 * 0.849]  <time.sleep>
    └── 2.171s [1 * 2.171]  fact  [/test/t2.py:24]  [/test/t2.py:20]
        ├── 1.552s [1 * 1.552]  f1  [/test/t2.py:21]  [/test/t2.py:14]
        │   └── 1.552s [1 * 1.552]  mysleep  [/test/t2.py:15]  [/test/t2.py:17]
        └── 0.619s [1 * 0.619]  fact  [/test/t2.py:24]  [/test/t2.py:20]
            └── 0.619s [1 * 0.619]  f1  [/test/t2.py:21]  [/test/t2.py:14]

Scalene是一个新的python分析器,它涵盖了许多用例,对性能的影响最小:

https://github.com/plasma-umass/scalene

它可以在非常精细的水平上评测CPU、GPU和内存利用率。它还特别支持多线程/并行化的python代码。