作者:perrygeo
譯者:賴勇浩(http://laiyonghao.com)
原文:http://www.perrygeo.net/wordpress/?p=116
我最喜歡的是Python,它的代碼優雅而實用,可惜純粹從速度上來看它比大多數語言都要慢。大多數人也認為的速度和易于使用是兩極對立的——編寫C代碼的確非常痛苦。而 Cython 試圖消除這種兩重性,并讓你同時擁有 Python 的語法和 C 數據類型和函數——它們兩個都是世界上最好的。請記住,我絕不是我在這方面的專家,這是我的第一次Cython真實體驗的筆記:
編輯:根據一些我收到的反饋,大家似乎有點混淆——Cython是用來生成 C 擴展到而不是獨立的程序的。所有的加速都是針對一個已經存在的 Python 應用的一個函數進行的。沒有使用 C 或 Lisp 重寫整個應用程序,也沒有手寫C擴展 。只是用一個簡單的方法來整合C的速度和C數據類型到 Python 函數中去。
現在可以說,我們能使下文的 great_circle 函數更快。所謂 great_circle 是計算沿地球表面兩點之間的距離的問題:
p1.py
import math
def great_circle(lon1,lat1,lon2,lat2):
radius = 3956 #miles
x = math.pi/180.0
a = (90.0-lat1)*(x)
b = (90.0-lat2)*(x)
theta = (lon2-lon1)*(x)
c = math.acos((math.cos(a)*math.cos(b)) +
(math.sin(a)*math.sin(b)*math.cos(theta)))
return radius*c
讓我們調用它 50 萬次并測定它的時間 :
import timeit
lon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826
num = 500000
t = timeit.Timer("p1.great_circle(%f,%f,%f,%f)" % (lon1,lat1,lon2,lat2),
"import p1")
print "Pure python function", t.timeit(num), "sec"
約2.2秒 。它太慢了!
讓我們試著快速地用Cython改寫它,然后看看是否有差別:
c1.pyx
import math
def great_circle(float lon1,float lat1,float lon2,float lat2):
cdef float radius = 3956.0
cdef float pi = 3.14159265
cdef float x = pi/180.0
cdef float a,b,theta,c
a = (90.0-lat1)*(x)
b = (90.0-lat2)*(x)
theta = (lon2-lon1)*(x)
c = math.acos((math.cos(a)*math.cos(b)) + (math.sin(a)*math.sin(b)*math.cos(theta)))
return radius*c
請注意,我們仍然import math——cython讓您在一定程度上混搭Python和C數據類型在。轉換是自動的,但并非沒有代價。在這個例子中我們所做的就是定義一個Python函數,聲明它的輸入參數是浮點數類型,并為所有變量聲明類型為C浮點數據類型。計算部分它仍然使用了Python的 math 模塊。
新聞熱點
疑難解答