在Python中只需一行即可加快函数调用速度

2020-06-28 22:55:59

如果我们非常频繁地在程序中调用昂贵的函数,最好保存函数调用的结果以供将来使用,而不是每次都调用函数。这通常会加快程序的执行速度。

函数的开销可以是计算性的(CPU使用率)或延迟(磁盘读取、从网络获取资源)。

函数调用的保存结果通常称为缓存。进行缓存的天真方法是存储每个函数调用。但是,对于函数的参数数量和每个参数的范围来说,这不是很好的伸缩性。

因此,我们需要一种使用固定内存量进行缓存的智能方法。而且,根据我们可以获得的信息类型,有很多可用的缓存策略。

从低级(硬件/CPU)到高级(网络/CDN),缓存在很多领域都得到了大量使用。

在大多数语言中,我们将选择自己选择的缓存策略,并使用一些数据结构(哈希图、优先级队列)来实现它们。根据语言的不同,可能只需要几分钟到几个小时就可以实现我们需要的通用解决方案。

但是,Python的标准库函数工具已经附带了一种称为LRU(最近最少使用)的缓存策略。多亏了python中的装饰者,只需一行代码就可以集成到现有的代码库中。

导入时间为TT def fib(N):如果n<;=1,则返回n个返回fib(n-1)+fib(n-2)t1=TT。time()fib(30)打印(f";花费的时间:{tt.。time()-t1}";)#输出:#耗时:0.3209421634674072

将时间导入为TT import functools#保存所有函数调用@functools。lru_cache(maxSize=31)def fib(N):如果n<;=1:返回n个返回fib(n-1)+fib(n-2)t1=TT。time()fib(30)打印(f";花费的时间:{tt.。time()-t1}";)打印(图。cache_info())#输出:#花费的时间:1.7881393432617188e-05#CacheInfo(命中=28,未命中=31,最大大小=31,当前大小=31)。

在本例中,我们保存了所有函数调用。但是,我们知道斐波纳契可以使用DP来实现。

导入时间为tt定义fib_iterative(N):如果n<;=1:对于范围(n-1)内的i,返回n f,s=0,1:t=f+s f,s=s,t返回t t1=tt。time()fib_iterative(30)打印(f";所用时间:{tt.。time()-t1}";)#输出:#耗时:5.0067901611328125e-06。

导入时间为TT import functools def lru_size(Max_Lru):@functools。lru_cache(maxSize=max_lru,type=false)def fib_lru(N):if n<;=1:返回n,返回fib_lru(n-1)+fib_lru(n-2)为[1,2,5,10,31]:t1=TT中的i返回fib_lru。time()fib=lru_size(I)fib(10)打印(f";lru大小:{i}耗时:{tt.。time()-t1}";)打印(图。CACHE_INFO())#输出:#LRU大小:1所用时间:0.6930997371673584#缓存信息(命中=0,未命中=2692537,最大大小=1,当前大小=1)#LRU大小:2所用时间:0.012731075286865234#缓存信息(命中=8656,未命中=41641,最大大小=2,当前大小=2)#LRU大小:5所用时间:5.817413330078125E-05#缓存信息(命中=28。

由此可见,fib函数的最佳缓存大小为5,增加缓存大小不会带来很大的加速比。

在计算机科学中,确定性算法是一种算法,在给定特定输入的情况下,它将始终产生相同的输出,底层机器始终通过相同的状态序列。确定性算法是迄今为止研究最多、最熟悉的一种算法,也是最实用的算法之一,因为它们可以在真实的机器上高效地运行。