以聪明的方式对Python进行编码

描述

我们利用Percepio的Tracealyzer来深入了解同一算法的两种不同实现的性能。具体来说,我们确定使用迭代函数而不是递归函数实现生成斐波那契数列的算法性能更高。我们不需要在序列中生成大量条目并测量时间来识别性能差异;相反,我们能够使用 Tracealyzer 让我们深入了解实现的性能,同时在序列中仅生成 10 个条目。

由于斐波那契序列生成器是在 Python 中实现的,让我们进一步扩展一下。关于StackOverflow的一些主要问题与特定算法的最有效和“Pythonic”实现有关。在本文中,我们将研究一个流行的操作:反转列表。

根据以下关于 StackOverflow 的问题,在反转列表时,关于一个实现相对于另一个实现的性能存在一些争论。为了深入了解差异,我们可以在一个简单的应用程序中实现这两种技术,如下面的列表所示;我们还包括必要的源代码,以捕获 Tracealyzer 评估每个实现的性能所需的标记:

import logging

def example():

list_basis = list(range(10))

logging.basicConfig()

logger = logging.getLogger(‘my-logger’)

logger.info(‘Start’)

reverse_list = reversed(list_basis)

logger.info(‘Stop’)

logger.info(‘Start’)

reverse_list = list_basis[::-1]

logger.info(‘Stop’)

if __name__ == ‘__main__’:

example()

我们创建了一个包含 10 个元素的列表,并使用内置的“反转”函数以及 Python 中称为“切片”的技术来反转列表。切片只是获取列表中的某些元素并将它们返回到新列表;在我们的例子中,我们正在切片整个列表,但向后遍历。

与上一篇博客文章一样,我们可以创建一个 LTTng 会话,运行我们的 Python 脚本,在 Tracealyzer 中打开生成的跟踪,并评估结果:

python

我们可以看到,使用反向函数的实现大约需要 475 微秒,使用切片的实现大约需要 360 微秒。

让我们看看当我们将初始列表中的元素数量增加 10 倍时会发生什么,从而得到一个由 100 个元素组成的列表:

import lttngust

import logging

def example():

list_basis = list(range(100))

logging.basicConfig()

logger = logging.getLogger(‘my-logger’)

logger.info(‘Start’)

reverse_list = reversed(list_basis)

logger.info(‘Stop’)

logger.info(‘Start’)

reverse_list = list_basis[::-1]

logger.info(‘Stop’)

if __name__ == ‘__main__’:

example()

同样,我们重新运行必要的步骤来创建 LTTng 会话,运行我们的应用程序,并在 Tracealyzer 中打开生成的跟踪,它向我们显示了下图:

python

虽然我们看到与以前相同的模式,其中切片技术比反向函数表现更好,但我们可以看到,与只有 10 个元素的结果相比,这两种机制的绝对时间几乎减少了一半。这很有趣,因为我们预计,与 100 个元素的情况相比,在 10 个元素的情况下,这两种技术所花费的时间应该更少。让我们通过首先更新 Python 脚本来收集更多数据,以允许我们以自动方式收集更多数据:

import lttngust

import logging

import sys

def example(list_size):

list_basis = list(range(list_size))

logging.basicConfig()

logger = logging.getLogger(“my-logger”)

logger.info(“Start”)

reverse_list = reversed(list_basis)

logger.info(“Stop”)

logger.info(“Start”)

reverse_list = list_basis[::-1]

logger.info(“Stop”)

if __name__ == ‘__main__’:

example(int(sys.argv[-1]))

在上面的例子中,我们只是允许自己在列表中传入我们想要的元素数量。然后我们可以创建以下 bash 脚本,这将允许我们执行 Python 应用程序,连续给它一个 10 和 100 的参数,收集使用反向函数和切片方法反转列表所需的时间,并存储该数据;脚本将循环浏览每个测试 10 次。

#!/bin/bash

set -e

list_compare() {

echo “Running test with a list size of $1 elements”

lttng create

lttng enable-event --kernel sched_switch

lttng enable-event --python my-logger

lttng start

python3 list_compare.py $1

lttng stop

lttng destroy

}

for i in {1..10}

do

list_compare 10

cp -r ~/lttng-traces/auto* “/home/pi/percepio/elements_10_trace_$i”

chown -R pi: “/home/pi/percepio/elements_10_trace_$i”

mv ~/lttng-traces/auto* ~/lttng-traces/archive/

list_compare 100

cp -r ~/lttng-traces/auto* “/home/pi/percepio/elements_100_trace_$i”

chown -R pi: “/home/pi/percepio/elements_100_trace_$i”

mv ~/lttng-traces/auto* ~/lttng-traces/archive/

done

当我们在 Tracealyzer 中打开生成的迹线并绘制图表时,我们会看到以下趋势:

 

python

黄色和橙色图表示 10 个元素列表的反转时间,绿色和深红色图表示 100 个元素列表的反转时间相同。我们可以看到一些实例,其中 10 个元素列表反转的执行时间与 100 个元素结果的执行时间一致。类似地,我们可以看到,有一个实例减少了反转 100 个元素列表的执行时间,并且与反转 10 个元素列表的执行时间相同。但是,总的来说,我们可以看到反转 10 个元素列表的执行时间大约是反转 100 个元素列表所需时间的一半。

也许我们在前一个案例中观察到了这些异常之一?让我们分析包含 1000 个元素的结果:

 

python

同样,我们看到相同的模式,与使用反向功能相比,使用切片技术花费的时间更少。但是,即使我们再次将列表中的元素数量增加了 10 倍(达到惊人的 1000 个元素),每个实现的时间与 100 个元素的时间大致相同,与只有 10 个元素相比,时间仍然是一半的时间。

让我们将列表大小增加到 100k 个元素并观察结果:

 

python

以前我们观察到切片技术花费的时间大约是反向函数的一半,而在这里我们可以看到相反的情况。事实上,对于 100k 个元素的列表大小,切片技术花费的时间大约延长了 15 倍!

总之,我们从这个简单的练习中获得了一些宝贵的见解。首先,与反向函数相比,切片技术似乎花费的时间更少,对于“几个”元素的列表大小(最多 1000)。但是,当我们将列表大小增加到 100k 个元素时,我们可以看到切片技术比反向函数花费大约 15 倍的时间。其次,当我们运行较小大小列表的多次迭代时,我们确实注意到反转包含 100 个元素的列表的时间与反转包含 10 个元素的列表的时间大致相同的实例;然而,总体趋势是,反转包含 10 个元素的列表比反转包含 100 个元素的列表花费的时间更少,这是意料之中的!我们可以更详细地分析Tracealyzer捕获的痕迹,以了解观察到的异常的原因。

这里的关键要点是,Percepio 的 Tracealyzer 使我们能够在没有太多仪器基础设施的情况下执行这种详细的分析;我们能够辨别出大约 100 微秒的性能数字!

由于Python一直是机器学习的流行语言,因此我们必须拥有一个工具,可以快速将一种算法的性能与另一种算法的性能进行比较。我们可以开发一些小函数来隔离我们要评估的算法,并使用 Tracealyzer 为我们提供有关算法在不同维度的性能的必要见解。Tracealyzer还可以快速发现可能需要进一步分析的异常行为。

审核编辑:郭婷

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分