几周前,我问了一个关于如何提高用Python编写的函数的速度的问题。当时,TryPyPy提请我注意使用Cython进行此操作的可能性。他还好心地给出了一个例子,说明我如何将代码片段进行Cythonize化。我想对下面的代码做同样的操作,看看我通过声明变量类型可以达到多快。我有几个与此有关的问题。我已经看过cython.org上的教程了,但我仍然有一些问题。它们是密切相关的:
double来实现Python中的float。我该做些什么来处理清单?通常,在哪里可以找到给定Python类型的相应C类型。关于我如何将下面的代码进行Cythonize的任何示例都会非常有用。我在代码中插入了注释,这些注释提供了有关变量类型的信息。
class Some_class(object):
** Other attributes and functions **
def update_awareness_status(self, this_var, timePd):
'''Inputs: this_var (type: float)
timePd (type: int)
Output: None'''
max_number = len(self.possibilities)
# self.possibilities is a list of tuples.
# Each tuple is a pair of person objects.
k = int(math.ceil(0.3 * max_number))
actual_number = random.choice(range(k))
chosen_possibilities = random.sample(self.possibilities,
actual_number)
if len(chosen_possibilities) > 0:
# chosen_possibilities is a list of tuples, each tuple is a pair
# of person objects. I have included the code for the Person class
# below.
for p1,p2 in chosen_possibilities:
# awareness_status is a tuple (float, int)
if p1.awareness_status[1] < p2.awareness_status[1]:
if p1.value > p2.awareness_status[0]:
p1.awareness_status = (this_var, timePd)
else:
p1.awareness_status = p2.awareness_status
elif p1.awareness_status[1] > p2.awareness_status[1]:
if p2.value > p1.awareness_status[0]:
p2.awareness_status = (price, timePd)
else:
p2.awareness_status = p1.awareness_status
else:
pass
class Person(object):
def __init__(self,id, value):
self.value = value
self.id = id
self.max_val = 50000
## Initial awareness status.
self.awarenessStatus = (self.max_val, -1)发布于 2011-02-17 18:37:33
请注意,您可以通过运行带有cython“注释”选项的-a命令,准确地看到C代码Cython为每一行源行生成的内容。有关示例,请参阅Cython 文档。在试图查找函数体内的瓶颈时,这是非常有用的。
此外,当Cython您的代码时,有一个“速度的早期绑定”的概念。Python (就像下面Person类的实例)使用一般Python代码进行属性访问,这在内部循环中很慢。我怀疑如果您将Person类更改为cdef class,那么您将看到一些加速。此外,还需要在内环中键入p1和p2对象。
因为您的代码有很多Python调用(例如random.sample),除非您找到一种将这些代码行放入C中的方法,否则很可能不会得到巨大的加速,这需要很大的努力。
您可以将事物键入为tuple或list,但这通常并不意味着加速。最好在可能的情况下使用C数组;一些您需要查找的内容。
我得到了一个1.6的加速因子与以下琐碎的修改。请注意,为了让它编译,我必须在这里和那里更改一些东西。
ctypedef int ITYPE_t
cdef class CyPerson:
# These attributes are placed in the extension type's C-struct, so C-level
# access is _much_ faster.
cdef ITYPE_t value, id, max_val
cdef tuple awareness_status
def __init__(self, ITYPE_t id, ITYPE_t value):
# The __init__ function is much the same as before.
self.value = value
self.id = id
self.max_val = 50000
## Initial awareness status.
self.awareness_status = (self.max_val, -1)
NPERSONS = 10000
import math
import random
class Some_class(object):
def __init__(self):
ri = lambda: random.randint(0, 10)
self.possibilities = [(CyPerson(ri(), ri()), CyPerson(ri(), ri())) for i in range(NPERSONS)]
def update_awareness_status(self, this_var, timePd):
'''Inputs: this_var (type: float)
timePd (type: int)
Output: None'''
cdef CyPerson p1, p2
price = 10
max_number = len(self.possibilities)
# self.possibilities is a list of tuples.
# Each tuple is a pair of person objects.
k = int(math.ceil(0.3 * max_number))
actual_number = random.choice(range(k))
chosen_possibilities = random.sample(self.possibilities,
actual_number)
if len(chosen_possibilities) > 0:
# chosen_possibilities is a list of tuples, each tuple is a pair
# of person objects. I have included the code for the Person class
# below.
for persons in chosen_possibilities:
p1, p2 = persons
# awareness_status is a tuple (float, int)
if p1.awareness_status[1] < p2.awareness_status[1]:
if p1.value > p2.awareness_status[0]:
p1.awareness_status = (this_var, timePd)
else:
p1.awareness_status = p2.awareness_status
elif p1.awareness_status[1] > p2.awareness_status[1]:
if p2.value > p1.awareness_status[0]:
p2.awareness_status = (price, timePd)
else:
p2.awareness_status = p1.awareness_status发布于 2011-02-02 21:18:13
C不直接了解清单的概念。基本数据类型是int (char、short、long)、float/double (所有这些数据类型都有到python的非常直观的映射)和指针。如果指针的概念对您来说是新的,请查看:维基百科:指针
在某些情况下,指针可以用作元组/数组替换。字符指针是所有字符串的基础。假设您有一个整数数组,然后将其存储为具有起始地址的连续内存块,定义类型(int),并且它是一个指针(*):
cdef int * array;现在您可以访问数组的每个元素,如下所示:
array[0] = 1但是,必须分配内存(例如使用malloc),高级索引不能工作(例如,array[-1]将是内存中的随机数据,对于超过保留空间宽度的索引也是如此)。
更复杂的类型并不直接映射到C,但通常有一种C方式来完成可能不需要python类型的事情(例如,for循环不需要范围数组/迭代器)。
正如您自己注意到的,编写好的cython代码需要对C有更详细的了解,因此下一步可能是最好的方法。
https://stackoverflow.com/questions/4872715
复制相似问题