Python代码优化LineProfiler
我的函数获取数字的组合,根据用户的输入可以是小的也可以是大的,并且将循环通过每个组合来执行一些操作 下面是我在函数上运行的一行评测,运行需要0.336秒。虽然速度很快,但这只是更大框架的一个子集。在这个更大的框架中,我需要运行这个函数50-20000次,当乘以0.336时,需要16.8到6720秒(我希望这是正确的)。之前它需要0.996秒,但我通过避免函数调用成功地将它减少了一半 时间的主要贡献者是两个Python代码优化LineProfiler,python,Python,我的函数获取数字的组合,根据用户的输入可以是小的也可以是大的,并且将循环通过每个组合来执行一些操作 下面是我在函数上运行的一行评测,运行需要0.336秒。虽然速度很快,但这只是更大框架的一个子集。在这个更大的框架中,我需要运行这个函数50-20000次,当乘以0.336时,需要16.8到6720秒(我希望这是正确的)。之前它需要0.996秒,但我通过避免函数调用成功地将它减少了一半 时间的主要贡献者是两个\uuuu getitem\uuuu,它根据组合的数量访问字典N次以获取信息。我的字典是一
\uuuu getitem\uuuu
,它根据组合的数量访问字典N次以获取信息。我的字典是一个数据集合,它看起来像这样:
dic = {"array1", a,
"array2", b,
"array3", c,
"listofarray", [ [list of 5 array], [list of 5 array], [list of 5 2d Array ] ]
}
当我将字典回溯放在循环之外时,我能够将它再缩短约0.01秒
x = dic['listofarray']['list of 5 2d array']
因此,当我循环访问5个不同的元素时,我只做了x[I]
除此之外,我不知道在哪里可以增加更多的性能提升
注意:很抱歉,我没有提供任何代码。我很想展示,但它是专有的。我只是想了解一下我是否在寻找合适的加速地点
我愿意学习和应用新事物,所以如果cython或其他数据结构可以加快速度,我会洗耳恭听。非常感谢
附言:
在我的第一个\uuu getitem\uuuu
中:
在我的第二个\uuuu getitem\uuuu
中:
编辑:
我正在使用iter工具产品(xrange(10),repeat=len(食物选择))
并对其进行迭代。我将所有内容转换为numpy数组np.array(I).astype(float)
时间的主要贡献者是两个\uuuu getitem\uuuu
,它根据组合的数量访问字典N次以获取信息
不,不是。您发布的两个配置文件跟踪清楚地显示它们是NumPy/Pandas\uuuuu getitem\uuuuuu
函数,而不是dict.\uuuuu getitem\uuuu
。所以,你试图优化错误的位置
这就解释了为什么将所有的dict
内容移出循环只会产生一小部分的差异
最有可能的问题是,您正在某个NumPy对象上循环,或者使用了一些伪矢量化函数(例如,通过
vectorize
),而不是执行一些NumPy优化的广播操作。这就是你需要解决的问题
例如,如果比较以下各项:
np.vectorize(lambda x: x*2)(a)
a * 2
…在任何规模较大的数组中,第二个将至少快10倍,这主要是因为所有的时间都花在了\uuuuu getitem\uuuuu
——其中包括将数字装箱以供Python函数使用。(无法使用CPU矢量化操作、可缓存的紧循环等也会带来一些额外的成本,但即使您将事情安排得足够复杂,以至于这些操作无法进入,您仍然可以获得更快的代码。)
同时: 我正在使用
itertools.product(xrange(10),repeat=len(food_choices))
并对其进行迭代。我将所有内容转换为numpy数组np.array(I).astype(float)
那么您正在创建独立的n元素数组?那不是明智地使用NumPy。每个阵列都很小,很可能您在构建和拆分阵列时花费的时间与实际工作中花费的时间相同。您是否有足够的内存来构建一个带有额外10**n
长轴的巨型阵列?或者,也许,把它分成10万组?因为这样您就可以用本机NumPy矢量化代码实际构建和处理整个数组
但是,您可能想尝试的第一件事是用PyPy而不是CPython运行代码。有些NumPy代码不能与PyPy/NumPyPy一起正常工作,但是每个版本的问题都比较少,所以您一定要尝试一下 如果幸运的话(很有可能),PyPy将在循环中JIT重复的
\uuuu getitem\uuuu
调用,并使其速度更快,而不会更改代码
如果这有帮助的话(或者如果NumPyPy无法处理您的代码),Cython可能会提供更多帮助。但只有在您完成了所有适当的静态类型声明等之后,PyPy通常已经帮了您很多忙了
时间的主要贡献者是两个\uuuu getitem\uuuu
,它根据组合的数量访问字典N次以获取信息
不,不是。您发布的两个配置文件跟踪清楚地显示它们是NumPy/Pandas\uuuuu getitem\uuuuuu
函数,而不是dict.\uuuuu getitem\uuuu
。所以,你试图优化错误的位置
这就解释了为什么将所有的dict
内容移出循环只会产生一小部分的差异
最有可能的问题是,您正在某个NumPy对象上循环,或者使用了一些伪矢量化函数(例如,通过
vectorize
),而不是执行一些NumPy优化的广播操作。这就是你需要解决的问题
例如,如果比较以下各项:
np.vectorize(lambda x: x*2)(a)
a * 2
…在任何规模较大的数组中,第二个将至少快10倍,这主要是因为所有的时间都花在了\uuuuu getitem\uuuuu
——其中包括将数字装箱以供Python函数使用。(无法使用CPU矢量化操作、可缓存的紧循环等也会带来一些额外的成本,但即使您将事情安排得足够复杂,以至于这些操作无法进入,您仍然可以获得更快的代码。)
同时: 我正在使用
itertools.product(xrange(10),repeat=len(food_choices))
并对其进行迭代。我将所有内容转换为numpy数组np.array(I).astype(float)
所以你是