借助Cython编写C代码

编辑:光环大数据 来源: 互联网 时间: 2017-10-31 13:19 阅读:

  借助Cython编写C代码,在过去两年,我使用Cython来完成大部分的工作。当然我并不是指先编写Python的代码,然后再通过各种类型声明等来“Cythonize”化。我是直接编写Cython代码,使用”原生“的C数据结构和数组,偶尔也有C++的容器,借助于我自己编写的一个malloc/free的装饰函数。编写的代码能达到C/C++的性能,因为它本质上就是C/C++的代码,只不过加了些Python中的语法糖。

这基本上不再遵循Python语言所遵守的旧规则:你将会使用Python语言来编写整个项目,但是针对其中的”热点“问题使用C语言进行优化,得到的结果就是同时拥有C的性能和Python的便捷性,而且非常可靠。

通常,理论比实践会更加优美。在实际过程中,你的数据结果会很大地影响到代码的性能,以及编写的难易性。数组虽然痛苦但比较快,而列表比较便捷,但是比较慢。Python的循环和函数调用也比较慢,所以你应该将这部分代码用C语言来编写。

今天在HN上有一篇文章,作者同时编写了纯粹的Python实现和C实现,使用NumpyCAPI。这看起来是展示二者不同的好机会,所以我编写了一个Cython的实现以作对比:

importrandom

fromcymem.cymemcimportPool

fromlibc.mathcimportsqrt

cimportcython

cdefstructPoint:

doublex

doubley

cdefclassWorld:

cdefPoolmem

cdefintN

cdefdouble*m

cdefPoint*r

cdefPoint*v

cdefPoint*F

cdefreadonlydoubledt

def__init__(self,N,threads=1,m_min=1,m_max=30.0,r_max=50.0,v_max=4.0,dt=1e-3):

self.mem=Pool()

self.N=N

self.m=<double*>self.mem.alloc(N,sizeof(double))

self.r=<Point*>self.mem.alloc(N,sizeof(Point))

self.v=<Point*>self.mem.alloc(N,sizeof(Point))

self.F=<Point*>self.mem.alloc(N,sizeof(Point))

foriinrange(N):

self.m[i]=random.uniform(m_min,m_max)

self.r[i].x=random.uniform(-r_max,r_max)

self.r[i].y=random.uniform(-r_max,r_max)

self.v[i].x=random.uniform(-v_max,v_max)

self.v[i].y=random.uniform(-v_max,v_max)

self.F[i].x=0

self.F[i].y=0

self.dt=dt

@cython.cdivision(True)

defcompute_F(Worldw):

"""Computetheforceoneachbodyintheworld,w."""

cdefinti,j

cdefdoubles3,tmp

cdefPoints

cdefPointF

foriinrange(w.N):

#Setallforcestozero.

w.F[i].x=0

w.F[i].y=0

forjinrange(i+1,w.N):

s.x=w.r[j].x-w.r[i].x

s.y=w.r[j].y-w.r[i].y

s3=sqrt(s.x*s.x+s.y*s.y)

s3*=s3*s3;

tmp=w.m[i]*w.m[j]/s3

F.x=tmp*s.x

F.y=tmp*s.y

w.F[i].x+=F.x

w.F[i].y+=F.y

w.F[j].x-=F.x

w.F[j].y-=F.y

@cython.cdivision(True)

defevolve(Worldw,intsteps):

"""Evolvetheworld,w,throughthegivennumberofsteps."""

cdefint_,i

for_inrange(steps):

compute_F(w)

foriinrange(w.N):

w.v[i].x+=w.F[i].x*w.dt/w.m[i]

w.v[i].y+=w.F[i].y*w.dt/w.m[i]

w.r[i].x+=w.v[i].x*w.dt

w.r[i].y+=w.v[i].y*w.dt

Cython的代码花费了大概30分钟来编写,而且它运行的速度和C代码一样快。因为它本质上就是C代码,只不过加了一些语法糖而已,甚至你不需要学习或了解外部的复杂的CAPI,你只需要编写C或C++代码。Cython和C版本的代码都比纯粹的Python版本快了大概70倍,它们都使用了Numpy数组。

和C语言的不同之处在于:关于malloc/free我编写了一段装饰代码——cymem,它的作用就是记录它所占用的地址,当垃圾回收器工作时,它会释放掉分配的内存空间。目前为止,我还没有遇到过内存泄漏的问题。

另一种编写Cython的方式就是借助于使用Numpy多维度的数组特性,然而这对我来说更加复杂了,而且我所尝试解决的问题很少会涉及数组问题,所以我都会使用自己定义的数据结构。

 

  Python培训Python培训班Python培训机构,就选光环大数据!

  还不够过瘾?想学习更多?点击 http://hadoop.aura.cn/python/ 进行Python学习!


大数据培训、人工智能培训、Python培训、大数据培训机构、大数据培训班、数据分析培训、大数据可视化培训,就选光环大数据!光环大数据,聘请专业的大数据领域知名讲师,确保教学的整体质量与教学水准。讲师团及时掌握时代潮流技术,将前沿技能融入教学中,确保学生所学知识顺应时代所需。通过深入浅出、通俗易懂的教学方式,指导学生更快的掌握技能知识,成就上万个高薪就业学子。 更多问题咨询,欢迎点击------>>>>在线客服

你可能也喜欢这些

在线客服咨询

领取资料

X
立即免费领取

请准确填写您的信息

点击领取
#第三方统计代码(模版变量) '); })();
'); })();