学习笔记 | 如何测试自己写的函数程序慢在哪里

文摘   2024-08-22 10:03   北京  

如何测试自己写的函数程序慢在哪里

前言

在开发过程中,优化程序性能是一项至关重要的任务。尤其是在处理大量数据或复杂算法时,找出程序中的瓶颈对于提高效率至关重要。本文将介绍如何使用 line_profiler 这一强大的工具来定位 Python 函数中的耗时点。通过具体的例子,我们将演示如何安装和使用 line_profiler,并展示它如何帮助我们识别并优化那些导致程序运行缓慢的部分。

安装

!pip install line_profiler -i https://pypi.mirrors.ustc.edu.cn/simple/
Looking in indexes: https://pypi.mirrors.ustc.edu.cn/simple/
Collecting line_profiler
  Downloading https://mirrors.ustc.edu.cn/pypi/packages/82/ad/06f4321260d709c5503bff79a41141b5725e3a1055151649ccbace98f663/line_profiler-4.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (718 kB)
[2K     [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m718.1/718.1 kB[0m [31m4.8 MB/s[0m eta [36m0:00:00[0ma [36m0:00:01[0m
[?25hInstalling collected packages: line_profiler
Successfully installed line_profiler-4.1.3

运行测试程序

测试程序为之前编写的计算经纬度距离的函数,已放入 project 中

!head /home/mw/project/test.py

你需要做的仅仅是在函数前增加一个装饰器@profiler

eee

!kernprof -l -v test.py

    Distances (first few elements):

    [[ 3159.18918786 14643.10185207  7650.32449848  8573.73083237

      12650.20642209]

     [ 7037.54644113  3080.23896724 14975.47890911 11841.96330602

       8743.0463527 ]

     [10295.70808389  7033.29073201  4083.76761385 19282.7567062

      18171.59151038]

     [ 2907.8340534   9900.53032942 13261.30789668  9773.43351035

       7203.35265715]

     [13257.5275834   6853.12299363 11334.78737952 19004.35542823

      11065.46618589]]

    Wrote profile results to test.py.lprof

    Timer unit: 1e-06 s



    Total time: 0.000883144 s

    File: test.py

    Function: haversine at line 3



    Line #      Hits         Time  Per Hit   % Time  Line Contents

    ==============================================================

         3                                           @profile

         4                                           def haversine(lat1, lon1, lat2, lon2, R=6371):

         5                                               # 将角度转换成弧度

         6         1         77.2     77.2      8.7      lat1_rad, lon1_rad = np.radians(lat1), np.radians(lon1)

         7         1         71.2     71.2      8.1      lat2_rad, lon2_rad = np.radians(lat2), np.radians(lon2)

         8

         9                                               # 计算差值

        10         1         32.6     32.6      3.7      dLat = lat2_rad - lat1_rad

        11         1         27.7     27.7      3.1      dLon = lon2_rad - lon1_rad

        12

        13                                               # Haversine 公式

        14         1        585.7    585.7     66.3      a = np.sin(dLat / 2.0)**2 + np.cos(lat1_rad) * np.cos(lat2_rad) * np.sin(dLon / 2.0)**2

        15         1         84.9     84.9      9.6      c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))

        16

        17                                               # 返回距离

        18         1          3.8      3.8      0.4      return R * c

运行之后会发现 project 目录多了一个文件,是分析结果的记录

/home/mw/project/test.py.lprof

可以用以下语句查看

```python
!python -m line_profiler test.py.lprof
Timer unit: 1e-06 s



Total time: 0.000883144 s

File: test.py

Function: haversine at line 3



Line #      Hits         Time  Per Hit   % Time  Line Contents

==============================================================

     3                                           @profile

     4                                           def haversine(lat1, lon1, lat2, lon2, R=6371):

     5                                               # 将角度转换成弧度

     6         1         77.2     77.2      8.7      lat1_rad, lon1_rad = np.radians(lat1), np.radians(lon1)

     7         1         71.2     71.2      8.1      lat2_rad, lon2_rad = np.radians(lat2), np.radians(lon2)

     8

     9                                               # 计算差值

    10         1         32.6     32.6      3.7      dLat = lat2_rad - lat1_rad

    11         1         27.7     27.7      3.1      dLon = lon2_rad - lon1_rad

    12

    13                                               # Haversine 公式

    14         1        585.7    585.7     66.3      a = np.sin(dLat / 2.0)**2 + np.cos(lat1_rad) * np.cos(lat2_rad) * np.sin(dLon / 2.0)**2

    15         1         84.9     84.9      9.6      c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))

    16

    17                                               # 返回距离

    18         1          3.8      3.8      0.4      return R * c

从提供的 line_profiler 输出来看,我们可以清楚地看到函数 calculate_qv_divergence 中每一行代码的执行时间。下面是对关键数据点的分析:

最耗时的部分是在 ha 公式的主要计算上 (Line # 14),占用了总执行时间的 64.7%。
转换纬度和经度为弧度 (Line # 6 和 Line # 7) 也消耗了一定的时间,分别占用了总执行时间的 8.8% 和 8.7%。
计算大圆弧的中心角 (Line # 15) 占用了总执行时间的 10.3%。。

执行上述代码后,line_profiler 将输出每个函数调用的时间统计信息。通过观察这些统计数据,我们可以发现哪些行或哪些部分消耗了最多的时间,从而找到优化的目标。

小结

通过使用 line_profiler,我们能够轻松地识别出程序中耗时较长的部分。这对于优化代码执行效率非常有用,特别是在处理大型数据集或执行密集型计算时。在实践中,我们建议定期使用这类工具来审查代码,以便及时发现并解决性能问题

参考链接:https://www.cnblogs.com/fnng/p/14702535.html
https://www.jianshu.com/p/a06a715b5a52


气python风雨
主要发一些涉及大气科学的Python文章与个人学习备忘录
 最新文章