我如何知道我的代码是否运行得足够快?有没有一种可测量的方法来测试我的代码的速度和性能?
例如,我有一个脚本,它在使用Numpy计算统计数据时读取CSV文件和编写新的CSV文件。下面,我使用cProfiler来编写我的Python,但是在看到结果之后,接下来怎么办?在这种情况下,我可以看到方法意味着,从numpy减少,从csv和python列表的方法附加的方法占用了相当一部分时间。
我如何知道我的代码是否可以改进?
python -m cProfile -s cumulative OBSparser.py
176657699 function calls (176651606 primitive calls) in 528.419 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.003 0.003 528.421 528.421 OBSparser.py:1(<module>)
1 0.000 0.000 526.874 526.874 OBSparser.py:45(start)
1 165.767 165.767 526.874 526.874 OBSparser.py:48(parse)
7638018 6.895 0.000 179.890 0.000 {method 'mean' of 'numpy.ndarray' objects}
7638018 56.780 0.000 172.995 0.000 _methods.py:53(_mean)
7628171 57.232 0.000 57.232 0.000 {method 'writerow' of '_csv.writer' objects}
7700878 52.580 0.000 52.580 0.000 {method 'reduce' of 'numpy.ufunc' objects}
7615219 50.640 0.000 50.640 0.000 {method 'astype' of 'numpy.ndarray' objects}
7668436 28.595 0.000 36.853 0.000 _methods.py:43(_count_reduce_items)
15323753 31.503 0.000 31.503 0.000 {numpy.core.multiarray.array}
45751805 13.439 0.000 13.439 0.000 {method 'append' of 'list' objects}有人能解释一下最佳做法吗?
发布于 2016-07-17 04:38:01
我如何知道我的代码是否运行得足够快?
这在很大程度上取决于您的用例--您的程序运行1.4小时,速度可能足够快,也可能不够快。如果这是一个一次性的过程,那么1.4小时并不多--花在优化上的任何时间都不值得投资。另一方面,如果这是一个应该运行的过程,例如每小时一次,显然值得找到一种更省时的方法。
有没有一种可测量的方法来测试我的代码的速度和性能?
是的,侧写-你已经做过了。这是个很好的开始。
接下来我该怎么办?
最佳做法包括:
你已经做了1,所以让我们转到2。
在您的示例中,程序将大部分时间用于在线OBSparser.py:48,其中三分之一的时间用于计算平均7638018次。
正如分析器输出所显示的,这是在ndarray上进行的,即使用numpy,而且在每次调用的基础上似乎不需要花费很多时间。快速计算证实:
179‘/ 7.638.018 =每次通话23.6微秒
因为这已经在C代码(numpy)中实现了,所以通过更改实际的mean代码(或者使用另一个库),您很可能没有什么办法来提高每次调用的性能。
然而,问自己几个问题:
.mean()的调用数量?.mean()的调用能否更有效地实现?其他值得考虑的调用是对.astype() and reduce的调用,我只是为了说明而专注于.mean()。
不知道您的代码实际上是做什么的,这里是我的5分钱的细节,无论如何:
在2.对我的i7内核进行快速检查后发现,对于ndarray.mean()来说,要花费20微秒左右,这需要大约50个值。因此,我猜您的是分组值,然后调用每个组的.mean()。可能有更有效的方法--搜索numpy组的聚合性能或其中的一些变体,可能会找到一些有用的指针。
在这里,我猜多处理不太可能是一个解决方案,因为您的计算似乎主要是CPU限制的,并且启动独立任务和交换数据的开销可能比好处更大。
然而,可能有一些使用SIMD-方法,即矢量化。再说一次,只是个预感。
的比较
为了减少重新配置文件所需的时间,请考虑对数据进行细分,使性能行为仍然是可见的(即每次调用.mean() 23 us ),但是总运行时间可能在1-2分钟以下,甚至更少。这将帮助您评估几种方法,然后再将它们完全应用到您的程序中。为了测试一些小的优化,一遍又一遍地运行整个过程是没有用的。
发布于 2016-07-16 07:18:45
你已经忘记了一个最基本的问题:
用例的速度满意吗?
但是老实说,它看起来并不十分有用,因为几乎所有的时间都花在OBSparser.py:48(解析)上,这需要很长的时间。我建议您将该方法重构为几个单独的方法。您可以使用可视化工具来可视化结果,py魅力对该用例有很好的支持。
发布于 2016-07-16 07:19:32
这就是性能的非功能性需求。
足够快的概念本身并没有什么技术意义。这取决于用户对您的产品的感知,并且应该通过需求进行翻译。这是判断实际实现是否足够快的唯一客观方法。
如果你没有这些要求,其他的都是猜测和非建设性的。
我如何知道我的代码是否可以改进?
假设它总是可以的。其中一些技术包括:
https://softwareengineering.stackexchange.com/questions/324987
复制相似问题