c python函数中带有python类的数组

时间:2017-10-25 15:44:19

标签: python arrays cython

我在Cython工作。我怎样才能声明一个python类实例的C数组,然后将数组传递给python函数并对其进行处理?

cdef int n=100
class particle:
    def __init__(self):
        self.x=uniform(1,99)
        self.y=uniform(1,99)
        self.pot=0
cdef particle parlist[n]
def CalPot(parlist[]):
    for i in range(N-1):
        pot=0
        for j in range(i,N):
            dx=parlist[j].x-parlist[i].x
            dy=parlist[j].y-parlist[j].y
            r2=dx**2+dy**2
            pot=pot+4*ep*r2*((sig/r2)**12 - (sig/r2)**6)
        parlist[i].pot=pot

2 个答案:

答案 0 :(得分:0)

Python类的实例是Python对象,在Python中处理得更好(它们不是C类型,我没有看到在Cython源代码中为它们创建某种形式的C表示的任何理由)。此外,更好地避免使用nparlist等全局变量(在此示例中,它们不是必需的)。

class particle:
    def __init__(self):
        self.x = uniform(1, 99)
        self.y = uniform(1, 99)
        self.pot = 0


def CalPot(parlist):
    N = len(parlist)
    for i in range(N):
        pot = 0
        for j in range(i, N):
            dx = parlist[j].x - parlist[i].x
            dy = parlist[j].y - parlist[j].y
            r2 = dx**2 + dy**2
            pot = pot + 4 * ep * r2 * ((sig / r2)**12 - (sig / r2)**6)
        parlist[i].pot = pot

所以这个Cython代码恰好是纯Python。

答案 1 :(得分:0)

正如Ioannis和DavidW告诉你的那样,你不应该创建一个python对象的c数组,而应该使用python列表。

对产生的纯Python进行Cyton化会带来大约2倍的速度,因为cython会删除解释器部分。但是,如果你还要摆脱引用计数和动态调度,那么还有更多的潜力 - 速度提升到100倍是很常见的。前段时间我回答a question说明了这一点。

你应该怎样做才能加快速度?你需要用"裸金属"替换python-multiplication。乘法。

第一步:不要为particle使用(python)类,使用简单的c-struct - 它只是一个数据集合 - 仅此而已:

cdef struct particle:
   double x
   double y
   double pot

第一个好处:可以定义这些结构的全局c数组(另一个问题是,在一个更大的项目中是否非常聪明):

DEF n=2000 # known at compile time
cdef particle parlist[n] 

在数组初始化之后(有关详细信息,请参阅附件列表),我们可以在calcpot - 函数中使用它(我略微更改了您的定义):

def calcpot():
   cdef double pot,dX,dY
   cdef int i,j
   for i in range(n):
     pot=0.0
     for j in range(i+1, n):
         dX=parlist[i].x-parlist[j].x
         dY=parlist[i].y-parlist[j].y
         pot=pot+1.0/(dX*dX+dY*dY)
     parlist[i].pot=pot

与原始代码的主要区别:parlist[i].x和Co.不再是慢速python对象,而是简单快速的doubles。为了能够获得最大的加速速度,需要考虑许多微妙的事情 - 一个人应该阅读/重读cython documentation

麻烦值得吗?我的机器上有时间(通过%timeit calcpot()):

                                  Time            Speed-up
pure python + interpreter:   924 ms ± 14.1 ms       x1.0
pure python + cython:        609 ms ± 6.83 ms       x1.5
cython version:               4.1 ms ± 55.3 µs     x231.0

使用低姿势加速231

列出python代码:

import random

class particle:
    def __init__(self):
        self.x=random.uniform(1,99)
        self.y=random.uniform(1,99)
        self.pot=0

n=2000
parlist = [particle() for _ in range(n)]

def calcpot():
     for i in range(n):
       pot=0.0
       for j in range(i+1, n):
         dX=parlist[i].x-parlist[j].x
         dY=parlist[i].y-parlist[j].y
         pot=pot+1.0/(dX*dX+dY*dY)
       parlist[i].pot=pot

列出cython代码:

#call init_parlist prior to calcpot!
cdef struct particle:
   double x
   double y
   double pot

DEF n=2000 # known at compile time
cdef particle parlist[n] 

import random
def init_parlist():
  for i in range(n):
     parlist[i].x=random.uniform(1,99)
     parlist[i].y=random.uniform(1,99)
     parlist[i].pot=0.0

def calcpot():
   cdef double pot,dX,dY
   cdef int i,j
   for i in range(n):
     pot=0.0
     for j in range(i+1, n):
         dX=parlist[i].x-parlist[j].x
         dY=parlist[i].y-parlist[j].y
         pot=pot+1.0/(dX*dX+dY*dY)
     parlist[i].pot=pot