如何讓python運行速度提高30倍
GIF
隨著機器學習領域的研究越來越火熱,python的人氣也水漲船高。上個月,python甚至第一次超過Java成為熱門編程語言第一位。但有一個領域,python卻不被看好,那就是編程競賽(Competitive Programming)。
運行速度是python常常被詬病的最大缺點。然而,作為一門設計精美的語言,小小的優化就可以讓代碼運行速度提高數十倍。上周,一道codeforces A類題困擾了我兩個小時。我非常確定我的演算法已經是最優解,但是因為題目涉及到10^5量級的讀寫,那只有可能是python的速度是程序的瓶頸。經過一番research,我發現了一個可以讓python提速30倍的方法。
Mycode1是第一次TLE(Time Limit Exceeded)時運行的代碼,運行時間為2.661秒。而第二段代碼print出完全一樣的東西只需要0.943秒,剛剛好進入1s的時間要求。
不難看出,第二段代碼和第一段的區別在於使用了列表推導式(List Comprehension)。使用列表推導式,python的解釋器只需要查找一次 print() method,而在使用第一種方法的時候,解釋器需要在每次執行循環時都要都查找一遍print函數對應的代碼。
且慢,故事到這還沒完。有沒有什麼方法可以讓str()函數也只用被查找一遍?答案是有的。在使用隱循環(Implied Loop)如map的時候,map調用的函數也只會被查找一遍。
使用mycode3的代碼,運行時間只有驚人的0.09秒。
最後,總結一下第二篇文章作者的幾個建議:
- Rule number one: only optimize when there is a proven speed bottleneck. Only optimize the innermost loop.
- Use intrinsic operations. An implied loop in map() is faster than an explicit for loop; a while loop with an explicit loop counter is even slower.
- Avoid calling functions written in Python in your inner loop. This includes lambdas. In-lining the inner loop can save a lot of time.
- Local variables are faster than globals; if you use a global constant in a loop, copy it to a local variable before the loop. And in Python, function names (global or built-in) are also global constants!
最重要的法則:只有當出現了運行速度瓶頸的時候才選擇優化,並且只優化最裡層循環;
使用python的內置函數,比如用map而不是循環;while循環比for需要更多的時間;
盡量避免在最內層的循環內調用函數;
局部變數要比全局變數更省時;如果要在最內層函數使用全局變數,可以在循環內複製一份變數。
GIF
TAG:python熱愛者 |