Python代碼優化之內存、運行時間

Python數據優化

  在使用Jupyter NoteBook或者Jupyter Lab處理數據的過程中,我們可以使用python的各種方法來查看代碼的 循行效率,如所用時間、內存佔用等等。

一、測試運行時間

魔法命令%%time、%%timeit

  在處理數據量級較大的數據中,特別是存在循環情況下,我們想知道大約多久能運行結束。這時我們可以使用這兩個命令對代碼進行測試。

%%time—測試當前cell中的代碼運行一次所需的時間

%%time
list = []
for i in range(1000):
    list.append(i)

輸出:

Wall time: 997 µs

  但是,只測試一次並不可靠,所以我們可以使用%%timeit,他會將該cell中的代碼執行10000次,並給一個運行時間的平均值±標準差

%%timeit—測試當前cell中的代碼所需的平均時間

%%timeit
list = []
for i in range(1000):
    list.append(i)

輸出:

121 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

二、測試每一行代碼所耗費時間

  當我們知道了我們的一段代碼運行完成所需要的時間並對其並不滿意的情況下,我們就需要找到導致這一部分代碼運行速度慢的“罪魁禍首”到底在哪一行,這時我們可以使用line_profiler模塊來測試每一行代碼所耗費的時間比。

模塊安裝:

>>> pip install line_profiler

引包:

%load_ext line_profiler

測試代碼:

%load_ext line_profiler
def test():
    a = 1
    b = 2/5
    c = (1+2)/5
%lprun -f test test()

輸出:

Timer unit: 1e-07 s

Total time: 9.4e-06 s
File: <ipython-input-16-986077aa9db9>
Function: test at line 2

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     2                                           def test():
     3         1         41.0     41.0     43.6      a = 1
     4         1         29.0     29.0     30.9      b = 2/5
     5         1         24.0     24.0     25.5      c = (1+2)/5
The line_profiler extension is already loaded. To reload it, use:
  %reload_ext line_profiler

  在輸出中,Total time指代碼運行總時間,Line指代碼行數,Hits表示每行代碼運行的次數,Time表示每行代碼運行的總時間,Per Hits指每行代碼運行一次的時間,% Time指每行代碼運行時間的百分比。
  這樣我們就可以知道,到底時間主要耗費在哪行代碼從而優化。

三、測試一個變量在內存中的所佔大小

在運行過程中,由於我電腦太low,內存經常會出現不夠用的情況。所以需要小心是否會出現MemoryError的情況。在Python中有兩種方式可以查看變量所佔內存。

  • 原生Python 在 sys 模塊中提供函數 getsizeof 來計算 Python 對象的大小
  • 使用pympler模塊中的asizeof計算Python對象的大小(推薦)

模塊安裝:

>>> pip install pympler

引包:

from pympler import asizeof

使用:

list = []
for i in range(1000):
    list.append(i)
asizeof.asizeof(list) 

輸出:單位爲字節,1kb=1024b

41016

當我們使用原生Python的 getsizeof 進行計算時:

from sys import getsizeof
a = []
for i in range(1000):
    a.append(i)
getsizeof(a) 

輸出:

9024

個人認爲asizeof更準確一下,至於爲什麼會出現差異,暫時還不理解。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章