2019年10月10日 星期四

Python 學習筆記 : math 與 Numpy 的效能比較

最近中午都抽空看 Paul A. Nakroshis 寫的計算物理學 "Introductory  Computational Physics Using Python", 短短 100 多頁, 一天看一點, 滴水穿石不知不覺就快看完了.

我在第一章看到一個出乎我意料的比較, 通常我們都認為 Numpy 計算速度比 Python 內建的函數要快, 但如果是比較單一的數學運算, 使用內建的 math 函式庫效能要比 Numpy 好, 例如進行 cos(3.4) 餘弦運算, 用 math.cos() 的話比用 Numpy.cos() 快上 2.7 倍, 程式如下 :

D:\test\python>python
Python 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from timeit import timeit 
>>> import math as m 
>>> import numpy as np 
>>> def mfunc():   
...     return m.cos(3.4) 
...
>>> def npfunc(): 
...     return np.cos(3.4) 
...
>>> timeit(stmt=mfunc, number=10000) 
0.003971100000001115
>>> timeit(stmt=npfunc, number=10000)     
0.010628900000000385

計算 1 萬次結果 math 花了 3.9711 ms; 而 Numpy 卻花了 10.6289 ms, 快了約 2.7 倍. 關於 timeit 內建模組用法參考 :

https://www.geeksforgeeks.org/timeit-python-examples/

但是如果是進行大數據計算, 使用 math 模組與串列需遍歷迴圈, 而 Numpy 則可直接對 ndarray 做向量運算, 效能就看得出來了, 例如對 [0, 10) 的整數陣列進行餘弦運算 :

>>> def mfunc2():   
...     for x in range(10):   
...         y=m.cos(x) 
...
>>> def npfunc2():   
...     np.cos(np.arange(0,10))   
...
>>> timeit(stmt=mfunc2, number=10000)   
0.03124800000000505
>>> timeit(stmt=npfunc2, number=10000)   
0.017304199999671255

使用 Python 迴圈遍歷串列元素做十個 cos() 計算 10000 次花了 31.248ms; 使用 Numpy 以向量進行運算則只花了 17.304ms, 可見用 Numpy 速度快了近 2 倍, 所以大數據運算非使用 Numpy 不可.

沒有留言 :