几周前,我问了一个关于提高用Python编写的函数速度的问题。当时,锥虫引起了我的注意,有可能使用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)
一般来说,通过使用
-a
“annotate”选项运行cython
命令,您可以确切地看到Cython为每个源代码行生成的代码。请参见Cythondocumentation以获取示例。当试图发现函数体中的瓶颈时,这非常有帮助。另外,在计算代码时还有"early binding for speed"的概念。Python对象(如下面的
Person
类的实例)使用通用Python代码进行属性访问,这在内部循环中很慢。我怀疑如果将Person
类更改为cdef class
,那么您将看到一些加速。此外,还需要在内部循环中键入p1
和p2
对象。由于您的代码有很多Python调用(例如,
random.sample
),除非找到一种将这些行放入C中的方法,否则您可能不会获得巨大的加速,这需要大量的努力。你可以输入
tuple
或list
,但这并不意味着加速。最好尽可能使用C数组;有些东西你必须查找。我得到了一个1.6倍的加速系数与下面的小修改。请注意,我必须在这里和那里修改一些东西才能编译它。
C不直接知道列表的概念。 基本的数据类型是
int
(char
,short
,long
,float
/double
(所有这些都有到python的非常直接的映射)和指针。 如果指针的概念对您来说是新的,请查看:Wikipedia:Pointers在某些情况下,指针可以用作元组/数组替换。字符指针是所有字符串的基础。 假设您有一个整数数组,然后将其存储为具有起始地址的连续内存块,定义类型(
int
)和指针(*
):现在您可以像这样访问数组的每个元素:
但是,必须分配内存(例如使用
malloc
),高级索引将不起作用(例如array[-1]
将是内存中的随机数据,这也适用于超过保留空间宽度的索引)。更复杂的类型不直接映射到C,但通常有一种C方法来做一些不需要python类型的事情(例如for循环不需要范围数组/迭代器)。
正如您自己所注意到的,编写好的cython代码需要对C有更详细的了解,所以继续学习教程可能是最好的下一步。
相关问题 更多 >
编程相关推荐