Cython 三分钟入门教程
作者: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 模块。
现在我们需要将其转换为C代码再编译为Python扩展。完成这一部的最好的办法是编写一个名为setup.py发布脚本。但是,现在我们用手工方式 ,以了解其中的巫术:
# this will create a c1.c file - the C source code to build a python extension
cython c1.pyx
# Compile the object file
gcc -c -fPIC -I/usr/include/python2.5/ c1.c
# Link it into a shared library
gcc -shared c1.o -o c1.so
现在你应该有一个c1.so(或.dll)文件,它可以被Python import。现在运行一下:
t = timeit.Timer("c1.great_circle(%f,%f,%f,%f)" % (lon1,lat1,lon2,lat2),
"import c1")
print "Cython function (still using python math)", t.timeit(num), "s
约1.8秒 。并没有我们一开始期望的那种大大的性能提升。使用 python 的 match 模块应该是瓶颈。现在让我们使用C标准库替代之:
c2.pyx
cdef extern from "math.h":
float cosf(float theta)
float sinf(float theta)
float acosf(float theta)
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 = acosf((cosf(a)*cosf(b)) + (sinf(a)*sinf(b)*cosf(theta)))
return radius*cec"
与 import math 相应,我们使用cdef extern 的方式使用从指定头文件声明函数(在此就是使用C标准库的math.h)。我们替代了代价高昂的的Python函数,然后建立新的共享库,并重新测试:
t = timeit.Timer("c2.great_circle(%f,%f,%f,%f)" % (lon1,lat1,lon2,lat2),
"import c2")
print "Cython function (using trig function from math.h)", t.timeit(num), "sec"
现在有点喜欢它了吧?0.4秒 -比纯Python函数有5倍的速度增长。我们还有什么方法可以再提高速度?c2.great_circle()仍是一个Python函数调用,这意味着它产生Python的API的开销(构建参数元组等),如果我们可以写一个纯粹的C函数的话,我们也许能够加快速度。
c3.pyx
cdef extern from "math.h":
float cosf(float theta)
float sinf(float theta)
float acosf(float theta)
cdef float _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 = acosf((cosf(a)*cosf(b)) + (sinf(a)*sinf(b)*cosf(theta)))
return radius*c
def great_circle(float lon1,float lat1,float lon2,float lat2,int num):
cdef int i
cdef float x
for i from 0
x = _great_circle(lon1,lat1,lon2,lat2)
return x
请注意,我们仍然有一个Python函数( def ),它接受一个额外的参数 num。这个函数里的循环使用for i from 0
为了证明我们所做的已经足够优化,可以用纯C写一个小应用,然后测定时间:
#include
#include
#define NUM 500000
float great_circle(float lon1, float lat1, float lon2, float lat2){
float radius = 3956.0;
float pi = 3.14159265;
float x = pi/180.0;
float a,b,theta,c;
a = (90.0-lat1)*(x);
b = (90.0-lat2)*(x);
theta = (lon2-lon1)*(x);
c = acos((cos(a)*cos(b)) + (sin(a)*sin(b)*cos(theta)));
return radius*c;
}
int main() {
int i;
float x;
for (i=0; i
x = great_circle(-72.345, 34.323, -61.823, 54.826);
printf("%f", x);
}
用gcc -lm -o ctest ctest.c编译它,测试用time ./ctest ...大约0.2秒 。这使我有信心,我Cython扩展相对于我的C代码也极有效率(这并不是说我的C编程能力很弱)。
能够用 cython 优化多少性能通常取决于有多少循环,数字运算和Python函数调用,这些都会让程序变慢。已经有一些人报告说在某些案例上 100 至 1000 倍的速度提升。至于其他的任务,可能不会那么有用。在疯狂地用 Cython 重写 Python 代码之前,记住这一点:
"我们应该忘记小的效率,过早的优化是一切罪恶的根源,有 97% 的案例如此。"——Donald Knuth
换句话说,先用 Python 编写程序,然后看它是否能够满足需要。大多数情况下,它的性能已经足够好了……但有时候真的觉得慢了,那就使用分析器找到瓶颈函数,然后用cython重写,很快就能够得到更高的性能。
外部链接
WorldMill(http://trac.gispython.org/projects/PCL/wiki/WorldMill)——由Sean Gillies 用 Cython 编写的一个快速的,提供简洁的 python 接口的模块,封装了用以处理矢量地理空间数据的 libgdal 库。
编写更快的 Pyrex 代码(http://www.sagemath.org:9001/WritingFastPyrexCode)——Pyrex,是 Cython 的前身,它们有类似的目标和语法。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











이 튜토리얼은 Python을 사용하여 Zipf의 법칙의 통계 개념을 처리하는 방법을 보여주고 법을 처리 할 때 Python의 읽기 및 대형 텍스트 파일을 정렬하는 효율성을 보여줍니다. ZIPF 분포라는 용어가 무엇을 의미하는지 궁금 할 것입니다. 이 용어를 이해하려면 먼저 Zipf의 법칙을 정의해야합니다. 걱정하지 마세요. 지침을 단순화하려고 노력할 것입니다. Zipf의 법칙 Zipf의 법칙은 단순히 : 큰 자연어 코퍼스에서 가장 자주 발생하는 단어는 두 번째 빈번한 단어, 세 번째 빈번한 단어보다 세 번, 네 번째 빈번한 단어 등 4 배나 자주 발생합니다. 예를 살펴 보겠습니다. 미국 영어로 브라운 코퍼스를 보면 가장 빈번한 단어는 "TH입니다.

이 기사에서는 HTML을 구문 분석하기 위해 파이썬 라이브러리 인 아름다운 수프를 사용하는 방법을 설명합니다. 데이터 추출, 다양한 HTML 구조 및 오류 처리 및 대안 (SEL과 같은 Find (), find_all (), select () 및 get_text ()와 같은 일반적인 방법을 자세히 설명합니다.

시끄러운 이미지를 다루는 것은 특히 휴대폰 또는 저해상도 카메라 사진에서 일반적인 문제입니다. 이 튜토리얼은 OpenCV를 사용 하여이 문제를 해결하기 위해 Python의 이미지 필터링 기술을 탐구합니다. 이미지 필터링 : 강력한 도구 이미지 필터

데이터 과학 및 처리가 가장 좋아하는 Python은 고성능 컴퓨팅을위한 풍부한 생태계를 제공합니다. 그러나 Python의 병렬 프로그래밍은 독특한 과제를 제시합니다. 이 튜토리얼은 이러한 과제를 탐구하며 전 세계 해석에 중점을 둡니다.

이 기사는 딥 러닝을 위해 텐서 플로와 Pytorch를 비교합니다. 데이터 준비, 모델 구축, 교육, 평가 및 배포와 관련된 단계에 대해 자세히 설명합니다. 프레임 워크, 특히 계산 포도와 관련하여 주요 차이점

이 튜토리얼은 Python 3에서 사용자 정의 파이프 라인 데이터 구조를 작성하여 클래스 및 작업자 과부하를 활용하여 향상된 기능을 보여줍니다. 파이프 라인의 유연성은 일련의 기능을 데이터 세트, GE에 적용하는 능력에 있습니다.

파이썬 객체의 직렬화 및 사막화는 사소한 프로그램의 주요 측면입니다. 무언가를 Python 파일에 저장하면 구성 파일을 읽거나 HTTP 요청에 응답하는 경우 객체 직렬화 및 사태화를 수행합니다. 어떤 의미에서, 직렬화와 사제화는 세계에서 가장 지루한 것들입니다. 이 모든 형식과 프로토콜에 대해 누가 걱정합니까? 일부 파이썬 객체를 지속하거나 스트리밍하여 나중에 완전히 검색하려고합니다. 이것은 세상을 개념적 차원에서 볼 수있는 좋은 방법입니다. 그러나 실제 수준에서 선택한 직렬화 체계, 형식 또는 프로토콜은 속도, 보안, 유지 보수 상태 및 프로그램의 기타 측면을 결정할 수 있습니다.

Python의 통계 모듈은 강력한 데이터 통계 분석 기능을 제공하여 생물 통계 및 비즈니스 분석과 같은 데이터의 전반적인 특성을 빠르게 이해할 수 있도록 도와줍니다. 데이터 포인트를 하나씩 보는 대신 평균 또는 분산과 같은 통계를보고 무시할 수있는 원래 데이터에서 트렌드와 기능을 발견하고 대형 데이터 세트를보다 쉽고 효과적으로 비교하십시오. 이 튜토리얼은 평균을 계산하고 데이터 세트의 분산 정도를 측정하는 방법을 설명합니다. 달리 명시되지 않는 한,이 모듈의 모든 함수는 단순히 평균을 합산하는 대신 평균 () 함수의 계산을 지원합니다. 부동 소수점 번호도 사용할 수 있습니다. 무작위로 가져옵니다 수입 통계 Fracti에서
