偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

教你幾招,Python性能提升30%!

開發(fā) 后端
優(yōu)化之前,首先要找到是哪部分代碼拖慢了整個(gè)程序的運(yùn)行。有時(shí)候程序的"瓶頸"不是很明顯,如果找不到,以下是一些建議以供參考。

本文主要分享如何提升Python性能的幾個(gè)使用方法! 

時(shí)序分析

優(yōu)化之前,首先要找到是哪部分代碼拖慢了整個(gè)程序的運(yùn)行。有時(shí)候程序的"瓶頸"不是很明顯,如果找不到,以下是一些建議以供參考: 

注意:這是一個(gè)計(jì)算e的x次冪的演示程序(出自Python文檔): 

  1. # slow_program.py  
  2. from decimal import*  
  3. defexp(x):  
  4.     getcontext().prec +=2  
  5.     i, lasts, s, fact, num =0, 0, 1, 1, 1  
  6.     while s != lasts:  
  7.         lasts = s  
  8.         i +=1  
  9.         fact *= i  
  10.         num *= x  
  11.         s += num / fact  
  12.     getcontext().prec -=2  
  13.     return+s  
  14. exp(Decimal(150))  
  15. exp(Decimal(400))  
  16. exp(Decimal(3000)) 

在GitHub上查看rawslow_program.py全部代碼

最省力的“性能分析”

首先,最簡單且最省力的解決方案是使用Unix的time命令:  

  1. ~ $ time python3.8  slow_program.py  
  2. real     0m11,058s  
  3. user     0m11,050s  
  4. sys      0m0,008s 

在GitHub上查看rawbase_time.shell全部代碼

如果只是給整個(gè)程序計(jì)時(shí),它很有用,但還不足夠…… 

最詳細(xì)的性能分析

性能分析的另一方法是cProfile,從中能得到很大的信息量: 

  1. ~ $ python3.8 -m  cProfile -s time slow_program.py  
  2.          1297 function calls (1272 primitive  calls) in 11.081 seconds  
  3.    Ordered by: internal time  
  4.    ncalls   tottime  percall  cumtime   percall filename:lineno(function)  
  5.         3    11.079    3.693   11.079     3.693 slow_program.py:4(exp)  
  6.         1     0.000    0.000    0.002     0.002 {built-in method _imp.create_dynamic}  
  7.       4/1     0.000    0.000   11.081    11.081 {built-in method builtins.exec}  
  8.         6     0.000    0.000    0.000     0.000 {built-in method __new__ of type object at 0x9d12c0}  
  9.         6     0.000    0.000    0.000     0.000 abc.py:132(__new__)  
  10.        23     0.000    0.000    0.000     0.000 _weakrefset.py:36(__init__)  
  11.       245     0.000    0.000    0.000     0.000 {built-in method builtins.getattr}  
  12.         2     0.000    0.000    0.000     0.000 {built-in method marshal.loads}  
  13.        10     0.000    0.000    0.000     0.000 <frozen importlib._bootstrap_external>:1233(find_spec)  
  14.       8/4     0.000    0.000    0.000     0.000 abc.py:196(__subclasscheck__)  
  15.        15     0.000    0.000    0.000     0.000 {built-in method posix.stat}  
  16.         6     0.000    0.000    0.000     0.000 {built-in method builtins.__build_class__}  
  17.         1     0.000    0.000    0.000     0.000 __init__.py:357(namedtuple)  
  18.        48     0.000    0.000    0.000     0.000 <frozen importlib._bootstrap_external>:57(_path_join)  
  19.        48     0.000    0.000    0.000     0.000 <frozen importlib._bootstrap_external>:59(<listcomp> 
  20.         1     0.000    0.000   11.081    11.081 slow_program.py:1(<module> 
  21. ... 

在GitHub上查看rawcprofile.shell全部代碼

這里用cProfile模塊和time參數(shù)運(yùn)行測試腳本,以便按內(nèi)部時(shí)間(cumtime)對(duì)行進(jìn)行排序。從中可以得到很多信息,以上所列結(jié)果約為實(shí)際輸出的10%。由此可見,exp函數(shù)就是拖慢程序的“罪魁禍?zhǔn)?rdquo;(太神奇啦?。?,現(xiàn)在看看更詳盡的時(shí)序和性能分析...... 

對(duì)特定函數(shù)計(jì)時(shí)

已經(jīng)知道拖慢程序運(yùn)行的函數(shù),下一步可使用簡單的修飾器,專門對(duì)該函數(shù)計(jì)時(shí),不測量其余代碼。如下所示: 

  1. deftimeit_wrapper(func):  
  2.     @wraps(func)  
  3.     defwrapper(*args, **kwargs):  
  4.         start =  time.perf_counter()  # Alternatively, you  can use time.process_time()  
  5.         funcfunc_return_val = func(*args, **kwargs)  
  6.         end = time.perf_counter()  
  7.         print( {0:<10}.{1:<8} : {2:<8} .format(func.__module__, func.__name__, end - start))  
  8.         return func_return_val  
  9.     return wrapper 

在GitHub上查看rawtimeit_decorator.py全部代碼

該修飾器可以應(yīng)用于功能測試,如下所示: 

  1. @timeit_wrapper  
  2. defexp(x):  
  3.     ...  
  4. print( {0:<10}{1:<8}{2:^8} .format( module ,  function ,  time ))  
  5. exp(Decimal(150))  
  6. exp(Decimal(400))  
  7. exp(Decimal(3000)) 

在GitHub上查看rawtimeit_decorator_usage.py全部代碼

輸出如下:  

  1. ~ $ python3.8  slow_program.py  
  2. module     function   time     
  3. __main__  .exp       :0.003267502994276583  
  4. __main__  .exp       :0.038535295985639095  
  5. __main__  .exp       : 11.728486061969306 

在GitHub上查看rawrun_with_timeit_decorator.shell全部代碼

要考慮的一個(gè)問題是實(shí)際/想要測量的時(shí)間類型是什么。Time程序包提供了time.perf_counter和time.process_time。兩者的區(qū)別是:perf_counter返回絕對(duì)值,其中包括Python程序進(jìn)程未運(yùn)行時(shí)的時(shí)間,因此可能會(huì)受計(jì)算機(jī)負(fù)載的影響;而process_time僅返回用戶時(shí)間(不包括系統(tǒng)時(shí)間),這僅是程序的運(yùn)行時(shí)間。 

加快程序運(yùn)行速度

[[314114]]

圖源:Unsplash

這是全文有趣的部分,關(guān)于如何加快Python的程序運(yùn)行速度。我并沒有列出一些可以奇妙解決性能問題的小技巧或代碼段,而是涉及一般性的構(gòu)想和策略,它們能極大地提高性能,某些情況下甚至能將性能提高30%。 

使用內(nèi)置數(shù)據(jù)類型

顯而易見,內(nèi)置數(shù)據(jù)類型運(yùn)行很快,尤其是與自定義類型(例如樹或鏈表)相比。主要是因?yàn)閮?nèi)置程序是用C語言實(shí)現(xiàn)的,遠(yuǎn)超過用Python編碼的運(yùn)行速度。 

使用lru_cache緩存/記憶 

我已經(jīng)在上一篇博文中講過這塊內(nèi)容,但在此還是要用簡單的示例說明: 

  1. import functools  
  2. import time  
  3. # caching up to 12  different results  
  4. @functools.lru_cache(maxsize=12 
  5. defslow_func(x):  
  6.     time.sleep(2)  # Simulate long computation  
  7.     return x  
  8. slow_func(1)  # ... waiting for 2 sec before getting  result  
  9. slow_func(1)  # already cached - result returned  instantaneously!  
  10. slow_func(3)  # ... waiting for 2 sec before getting  result 

在GitHub上查看rawlru_cache.py全部代碼

以上函數(shù)使用time.sleep模擬大量運(yùn)算。第一次使用參數(shù)1調(diào)用該函數(shù)時(shí),返回結(jié)果需要2秒。再次調(diào)用時(shí),結(jié)果已被緩存,因此會(huì)跳過函數(shù)主體并立即返回結(jié)果。更多內(nèi)容請參見此處。 

使用局部變量

這與在每個(gè)作用域中查找變量的速度有關(guān)。我用了“每個(gè)作用域”這個(gè)字眼,因?yàn)樗粌H僅是“使用局部變量還是全局變量”的問題。實(shí)際上,即使在函數(shù)的局部變量(最快)、類級(jí)屬性(如self.name-較慢)和全局變量(如導(dǎo)入的函數(shù),time.time-最慢)之間,查找速度也有所不同。 

可以通過運(yùn)行無用的任務(wù)來提高性能,如下所示: 

  1. #  Example #1  
  2. classFastClass:  
  3.     defdo_stuff(self):  
  4.         temp =self.value  # this speeds up lookup in loop  
  5.         for i inrange(10000):  
  6.             ...  # Do something with `temp` here  
  7. #  Example #2  
  8. import random  
  9. deffast_function():  
  10.     r = random.random  
  11.     for i inrange(10000):  
  12.         print(r())  # calling `r()` here, is faster than  global random.random() 

在GitHub上查看rawlocal_vars.py全部代碼

使用函數(shù)(Function)

這怎么和假想的不同?理論上調(diào)用函數(shù)不是會(huì)將更多的東西放到堆棧上,加大返回結(jié)果的負(fù)擔(dān)嗎?但實(shí)際上,使用函數(shù)確實(shí)能加快運(yùn)行速度,這與前一點(diǎn)有關(guān)。將整個(gè)代碼放在一個(gè)文件中而非函數(shù)中,它是全局變量而非局部變量,運(yùn)行速度就會(huì)慢得多。因此,可以將整個(gè)代碼包裹在main函數(shù)中并通過一次調(diào)用來加速代碼,如下所示: 

  1. defmain():  
  2.     ...  # All your previously global code  
  3. main() 

在GitHub上查看rawglobal_vars.py全部代碼

避免訪問屬性(Attribute)

可能拖慢程序的一個(gè)原因是使用點(diǎn)運(yùn)算符(.)訪問對(duì)象屬性。該運(yùn)算符通過使用__getattribute__方法觸發(fā)了字典查找,使代碼產(chǎn)生額外負(fù)擔(dān)。那么,如何避免或減少屬性訪問?  

  1. #  Slow:  
  2. import re  
  3. defslow_func():  
  4.     for i inrange(10000):  
  5.         re.findall(regex, line)  # Slow!  
  6. #  Fast:  
  7. from re import findall  
  8. deffast_func():  
  9.     for i inrange(10000):  
  10.         findall(regex, line)  # Faster! 

在GitHub上查看rawimports.py全部代碼

當(dāng)心使用字符串

在循環(huán)里使用格式符(%s)或.format()時(shí),字符串操作可能會(huì)變得非常慢。有沒有更好的選擇?Raymond Hettinger在最近發(fā)布的推文中提到:唯一應(yīng)該使用的是f-string(格式化字符串常量),它是最易讀、最簡潔且最快捷的方法。根據(jù)這篇推文,下面列出了可用的方法(由快到慢): 

  1. f {s}{t}   # Fast!  
  2. s +    + t  
  3.    .join((s, t))  
  4.  %s %s % (s, t)  
  5.  {} {} .format(s, t)  
  6. Template( $s $t ).substitute(ss=s, tt=t)  # Slow! 

在GitHub上查看rawstrings.py全部代碼

本質(zhì)上,生成器并沒有變得更快,因?yàn)樗谠O(shè)計(jì)上允許延遲計(jì)算以節(jié)省內(nèi)存而非節(jié)約時(shí)間。然而節(jié)省的內(nèi)存也可以加快程序?qū)嶋H運(yùn)行速度。怎么做?如果有一個(gè)很大的數(shù)據(jù)集且不使用生成器(迭代器),那么數(shù)據(jù)可能會(huì)溢出CPU的L1 cache(1級(jí)緩存),這將大大減慢內(nèi)存的查找速度。 

在性能方面,極重要的一點(diǎn)是:CPU可以將正在處理的所有數(shù)據(jù)盡可能地保存在緩存中。

[[314115]]

圖源:Unsplash

結(jié)語 

優(yōu)化的首要規(guī)則就是“不優(yōu)化”。 

若真的有必要優(yōu)化,那我希望這些技巧會(huì)有所幫助。 

但是,優(yōu)化代碼時(shí)一定要小心,因?yàn)閮?yōu)化的結(jié)果可能是代碼難以閱讀進(jìn)而難以維護(hù),這就得不償失了。 

最后,希望大家能搭上python號(hào)火箭,編碼越來越快! 

 

 

責(zé)任編輯:龐桂玉 來源: 機(jī)器學(xué)習(xí)算法與Python學(xué)習(xí)
相關(guān)推薦

2020-10-09 17:43:25

計(jì)算機(jī)CPU技術(shù)

2018-04-18 14:05:53

解鎖隱藏實(shí)力

2020-04-13 19:10:03

電腦噪音電競

2011-02-22 13:46:27

微軟SQL.NET

2013-10-25 09:14:55

2021-10-29 10:32:45

數(shù)據(jù) Navicat方法

2022-05-16 09:48:30

Google性能優(yōu)化LCP

2022-09-13 16:01:13

購物車京東接口

2021-09-27 20:22:37

Massive MIMAAU天線

2021-09-27 21:07:40

華為MetaAAU

2024-12-30 09:03:09

2022-08-29 08:41:52

異步ControllerrunAsync

2010-01-22 09:01:02

2018-10-29 15:35:19

路由器寬帶PC端

2010-09-14 14:21:47

無線網(wǎng)絡(luò)升級(jí)設(shè)置

2015-08-14 09:56:23

防蹭網(wǎng)

2024-06-03 08:52:40

2023-03-27 18:18:47

GPT-4AI

2011-01-07 17:21:01

2021-04-08 05:58:45

Excel數(shù)據(jù)技巧
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)