天天看點

簡單聊聊py的高性能程式設計

高性能程式設計的含義是通過編寫更為高效的代碼或者改變操作方式,也就是找到更合适的算法去降低時間上的開銷。

計算機的模型可以分為三種,分别是計算單元(CPU,GPU),存儲單元(硬碟,記憶體之類的)還有它們之間的連接配接。計算單元給我們的是我們能有

多塊的速度去解決問題,它可以将接受到的輸入變成對應的輸出以及改變狀态的能力。存儲單元一方面是能存多少資料,另一方面是對這些資料的讀寫有多快,越靠近CPU的存儲速度越快

,其包含的資料量也越少。計算單元和存儲單元之間的連接配接則是決定了資料移動的資料有多快,光速是有限的,它決定着實體的極限,總線帶寬也決定着一次傳輸能有多少資料。

#一個簡單計算質數的代碼,按照其實還有更好的優化方法,具體請看《程式設計珠玑》

import math

import time

def check_prime(number):

sqrt_number = math.sqrt(number)

start = time.time()

for i in range(2, int(sqrt_number) + 1):

if (number / i).is_integer():

return False

end = time.time()

print('sum_time',end-start)

return True

check_prime(10000000)

check_prime(10000019)

理想的計算模型:(以下不是真實的python計算過程,隻是為了講解)

1.number的值會存放在随機存儲器上,為了計算sqrt_number,需要将number傳入到CPU當中去。在傳入的時候應該盡可能的利用靠近

CPU的緩存,而不是如下的寫法:

sqrt_number = math.sqrt(number)

number_float = float(sqrt_number)

這樣意味着将資料兩次經過總線傳輸,将資料盡可能的少移動,保持在需要的地方是必須的。也就是說移動計算,而不是移動資料。

2.python的虛拟機為了盡可能的抽象做了很多工作,但是相應的犧牲了性能,比如

快:

for i in haystack:

if (exp):

return False

return True

慢:

value = True

for i in haystack:

if (exp):

value = False

return True

雖然結果是一樣,但是運作時間在足夠大的資料量就會發生巨大的差别,這也是上述所說的盡可能的少移動資料

3.為了可以矢量操作,也就是在循環時将循環值也就是i值盡可能的一次性讀入CPU,在CPU内進行計算,傳回相應的值,需要借助numpy這樣的用C寫的庫區實作,

4.抽象的代價也意味着python的對象不再是記憶體中的最優化布局,因為記憶體需要自動處理并且釋放,這就影響了向CPU緩存的效率。

5.動态語言不可避免的代價就是,沒有編譯器從全局角度去優化對象的記憶體布局和CPU指令

6.最後一個則是臭名昭著的GIL了。