胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

豐色 發自 凹非寺

量子位 | 公眾號 QbitAI

眾所周知,Python的簡單和易讀性是

靠犧牲效能

為代價的——

尤其是在計算密集的情況下,比如多重for迴圈。

不過現在,大佬

胡淵鳴

說了:

只需import 一個叫做“Taichi”的庫,就可以把程式碼速度

提升100倍

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

不信?

來看三個例子。

計算素數的個數,速度x120

第一個例子非常非常簡單,求所有小於給定正整數N的素數。

標準答案如下:

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

我們將上面的程式碼儲存,執行。

當N為100萬時,需要2。235s得到結果:

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

現在,我們開始施魔法。

不用更改任何函式體,import“taichi”庫,然後再加兩個裝飾器:

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

Bingo!

同樣的結果只要0.363s,快了將近6倍。

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

如果N=1000萬,則只要0。8s;要知道,不加它可是55s,一下子又快了

70倍

不止如此,我們還可以在ti。init()中加個引數變為ti。init(arch=ti。gpu) ,讓taich在

GPU

上進行計算。

那麼此時,計算所有小於1000萬的素數就只耗時0。45s了,與原來的Python程式碼相比速度就

提高了120倍

厲不厲害?

什麼?你覺得這個例子太簡單了,說服力不夠?我們再來看一個稍微複雜一點的。

動態規劃,速度x500

動態規劃不用多說,作為一種最佳化演算法,透過動態儲存中間計算結果來減少計算時間。

我們以經典教材《演算法導論》中的經典動態規劃案例

“最長公共子序列問題(LCS)”

為例。

比如對於序列a = [0, 1, 0, 2, 4, 3, 1, 2, 1]和序列b = [4, 0, 1, 4, 5, 3, 1, 2],它們的LCS就是:

LCS(a, b) = [0, 1, 4, 3, 1, 2]。

用動態規劃的思路計算LCS,就是先求解序列a的前i個元素和序列b的前j個元素的最長公共子序列的長度,然後逐步增加i或j的值,重複過程,得到結果。

我們用f[i, j]來指代這個子序列的長度,即LCS((prefix(a, i), prefix(b, j)。其中prefix(a, i) 表示序列a的前i個元素,即a[0], a[1], …, a[i - 1],得到如下遞迴關係:

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

完整程式碼如下:

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

現在,我們用Taichi來加速:

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

結果如下:

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

胡淵鳴電腦上的程式

最快做到了0.9秒內

完成,而

換成用NumPy來實現,則需要476秒,差異達到了超500倍!

最後,我們再來一個不一樣的例子。

反應 - 擴散方程,效果驚人

自然界中,總有一些動物身上長著一些看起來無序但實則並非完全隨機的花紋。

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

圖靈機的發明者艾倫·圖靈是第一個提出模型來描述這種現象的人。

在該模型中,兩種化學物質

(U和V)

來模擬圖案的生成。這兩者之間的關係類似於獵物和捕食者,它們自行移動並有互動:

最初,U和V隨機分佈在一個域上;

在每個時間步,它們逐漸擴散到鄰近空間;

當U和V相遇時,一部分U被V吞噬。因此,V的濃度增加;

為了避免U被V根除,我們在每個時間步新增一定百分比 (f) 的U並刪除一定百分比 (k) 的V。

上面這個過程被概述為“反應-擴散方程”:

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

其中有四個關鍵引數:Du

(U的擴散速度)

,Dv

(V的擴散速度)

,f

(feed的縮寫,控制U的加入)

和k

(kill的縮寫,控制V的去除)

如果Taichi中實現這個方程,首先建立網格來表示域,用vec2表示每個網格中U, V的濃度值。

拉普拉斯運算元數值的計算需要訪問相鄰網格。為了避免在同一迴圈中更新和讀取資料,我們應該建立兩個形狀相同的網格W×H×2。

每次從一個網格訪問資料時,我們將更新的資料寫入另一個網格,然後切換下一個網格。那麼資料結構設計就是這樣:

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

一開始,我們將U在網格中的濃度設定為 1,並將V放置在50個隨機選擇的位置:

胡淵鳴:import一個“太極”庫,讓Python程式碼提速100倍

那麼實際計算就可以用不到10行程式碼完成: