本節書摘來自異步社群《python高性能程式設計》一書中的第2章,第2.2節,作者[美] 戈雷利克 (micha gorelick),胡世傑,徐旭彬 譯,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
讓我們從julia集合這個有趣的cpu密集型問題開始。這是一個可以産生複雜的輸出圖像的分形數列,以數學家gaston julia的名字命名。
函數的代碼相當長,你不會想要自己實作一個。它包含一個cpu密集型的元件和一個顯式的輸入集合。這一配置允許我們分析cpu和ram的使用情況以幫助我們了解代碼中哪部分過多地消耗了這兩項計算資源。将代碼故意做成非最優的實作,這樣我們就可以檢查耗記憶體的操作和慢的語句。我們在本章後面将修正一個慢的語句和一個耗記憶體的語句,然後在第7章,我們還将顯著提升整個函數的執行時間。
我們将分析一段能夠生成一個僞灰階圖(圖2-1)和一個純灰階變種(圖2-3)的代碼,設julia集合的複數點c=-0.62772-0.42193j。一個julia集合可以通過獨立計算每一個像素點得到,也就是說這是一個“完美并行計算的問題”,每個點之間沒有任何資料共享。

如果我們選擇一個不同的c,就會得到一個不同的圖像。根據我們的選擇,有些區域算起來較快而另一些會較慢,這有助于我們的分析。
問題的有趣之處在于我們對每一個像素的計算都需要進行一個次數不定的循環。每一次疊代都需要計算坐标值是趨于無窮,還是收斂。那些經過少數疊代就能算出結果的坐标在圖2-1上為黑色,而那些需要大量疊代才能算出結果的坐标為白色。白色區域需要更多計算,是以生成時間更長。
讓我們定義一個z的坐标函數進行計算。函數會計算複數z的平方加c:
我們疊代調用該函數并用abs計算逃逸條件。如果逃逸值為false,那麼我們終止循環并在該坐标上記錄下疊代的次數。如果逃逸條件始終不滿足,那麼我們在經過maxiter次疊代後終止,并将該z坐标轉化為一個彩色像素點。
僞代碼如下:
讓我們試算兩個坐标來解釋這個函數。
首先,我們将使用圖的左上角坐标-1.8-1.8j。在坐标更新前我們就必須首先計算逃逸條件abs(z) < 2:
我們可以看到第0次疊代逃逸條件即為false,于是我們不需要更新坐标。該坐标的輸出值就是0。
現在讓我們跳到圖中央的z = 0 + 0j并嘗試幾次疊代:
我們可以看到,每次疊代都令abs(z) < 2為true。我們可以對該坐标疊代300次依然為true。我們無法得知需要多少次疊代才能令條件為false,可能是個無窮數列。最大疊代次數(maxiter)會確定我們不至于永遠疊代下去。
我們在圖2-2中可以看到前50個疊代結果。0+0j的結果數列(帶圓形标記的實線)似乎每8個疊代出現一次循環,但是每個循環都跟前一個有微小的差別——我們無法得知該坐标是會永遠疊代下去,還是将要疊代很長時間,還是馬上就會超出邊界條件。短劃線cutoff表示+2的邊界線。
對于-0.82+0j的結果數列(帶菱形标記的短劃線),我們可以看到第9次疊代後絕對值結果就超出了+2的cutoff邊界線,于是疊代終止。