如何在Cython中运行我的python代码?

时间:2014-05-08 01:02:31

标签: python time cython

我目前在python中编写了相当大的代码,当我运行它时,它需要大约3分钟来完成全部计算。最后,我想将我的N增加到大约400并将for循环中的m更改为更大的数字 - 这可能需要数小时才能计算出我想减少的数量。

步骤1-6需要很长时间。

尝试使用cython运行时(I.E.导入pyximport然后导入我的文件) 我得到以下错误FDC.pyx:49:19:'range'不是有效的cython语言结构和 FDC.pyx:49:19:'range'不是有效的cython属性或使用不正确

from physics import *
from operator import add, sub
import pylab




################ PRODUCING CHARGES AT RANDOM IN r #############

N=11 #Number of point charges

x = zeros(N,float) #grid
y = zeros(N,float)

i=0
while i < N: #code to produce values of x and y within r 
    x[i] = random.uniform(0,1)
    y[i] = random.uniform(0,1)
    if x[i] ** 2 + y[i] ** 2 <= 1:
        i+=1


print x, y

def r(x,y): #distance between particles
    return sqrt(x**2 + y**2)   

o = 0; k = 0; W=0        #sum of energy for initial charges 
for o in range(0, N):
    for k in range(0, N):
        if o==k:
            continue
        xdist=x[o]-x[k]
        ydist=y[o]-y[k]
        W+= 0.5/(r(xdist,ydist))

print "Initial Energy:", W


##################### STEPS 1-6 ######################

d=0.01 #fixed change in length
charge=(x,y)
l=0; m=0; n=0
prevsW = 0.
T=100
for q in range(0,100):
    T=0.9*T
    for m in range(0, 4000): #steps 1 - 6 in notes looped over

        xRef = random.randint(0,1)      #Choosing x or y
        yRef = random.randint(0,N-1)      #choosing the element of xRef
        j = charge[xRef][yRef]           #Chooses specific axis of a charge and stores it as 'j'

        prevops = None #assigns prevops as having no variable
        while True: #code to randomly change charge positions and ensure they do not leave the disc
            ops =(add, sub); op=random.choice(ops)
            tempJ = op(j, d)
            #print xRef, yRef, n, tempJ
            charge[xRef][yRef] = tempJ
            ret = r(charge[0][yRef],charge[1][yRef])
            if ret<=1.0:
                j=tempJ
                #print "working", n
                break

            elif prevops != ops and prevops != None: #!= is 'not equal to' so that if both addition and subtraction operations dont work the code breaks 
                break

            prevops = ops #####

        o = 0; k = 0; sW=0        #New energy with altered x coordinate
        for o in range(0, N):
            for k in range(0, N):
                if o==k:
                    continue
                xdist = x[o] - x[k]
                ydist = y[o] - y[k]
                sW+=0.5/(r( xdist , ydist )) 


        difference = sW - prevsW
        prevsW = sW

        #Conditions:
        p=0

        if difference < 0: #accept change
            charge[xRef][yRef] = j
            #print 'step 5'
        randomnum = random.uniform(0,1) #r
        if difference > 0: #acceptance with a probability 
            p = exp( -difference / T )
            #print 'step 6', p
            if randomnum >= p:
                charge[xRef][yRef] = op(tempJ, -d) #revert coordinate to original if r>p
                #print charge[xRef][yRef], 'r>p'

        #print m, charge, difference   

o = 0; k = 0; DW=0        #sum of energy for initial charges 
for o in range(0, N):
    for k in range(0, N):
        if o==k:
            continue
        xdist=x[o]-x[k]
        ydist=y[o]-y[k]
        DW+= 0.5/(r(xdist,ydist))

print charge
print 'Final Energy:', DW

################### plotting circle ###################

# use radians instead of degrees
list_radians = [0]


for i in range(0,360):
    float_div = 180.0/(i+1)
    list_radians.append(pi/float_div)

# list of coordinates for each point
list_x2_axis = []
list_y2_axis = []

# calculate coordinates 
# and append to above list
for a in list_radians:
    list_x2_axis.append(cos(a))
    list_y2_axis.append(sin(a))



# plot the coordinates
pylab.plot(list_x2_axis,list_y2_axis,c='r')

########################################################
pylab.title('Distribution of Charges on a Disc') 
pylab.scatter(x,y)
    pylab.show()

1 个答案:

答案 0 :(得分:0)

花时间似乎是这样:

for q in range(0,100):
    ...
    for m in range(0, 4000): #steps 1 - 6 in notes looped over
        while True: #code to randomly change charge positions and ensure they do not leave the disc
            ....
        for o in range(0, N):      # <----- N will be brought up to 400
            for k in range(0, N):
                ....
            ....            
        ....
    ....

100 x 4000 x(while loop)+ 100 x 4000 x 400 x 400 = [400,000 x while loop] + [64,000,000,000]

在研究更快的语言之前,也许有更好的方法来构建模拟?

除此之外,如果您符合以下条件,您可能会立即获得业绩增长: - 转移到numpy数组i / o python列表。 - 使用xrange i / o范围

[编辑试图回答评论中的问题]:

import numpy as np, random
N=11 #Number of point charges

x = np.random.uniform(0,1,N)  
y = np.random.uniform(0,1,N)
z = np.zeros(N)
z = np.sqrt(x**2 + y**2)   # <--- this could maybe replace r(x,y) (called quite often in your code)
print x, y, z

您还可以查看在主循环(上述内容)中多次分配或重新计算的所有变量,并将所有变量拉出循环外部,以便不重复分配或重新计算。< / p>

例如,

ops =(add, sub); op=random.choice(ops)

可能会被

取代
ops = random.choice(add, sub)

最后,在这里我处于困境,因为我自己从未使用它,但是使用像Numba或Jit这样的包而不是cython可能会更简单一些;它们允许您装饰代码的关键部分,并在执行之前对其进行预编译,不进行任何修改或进行非常小的修改。