找到你要的答案

Q:Cython: simple function with 2 lists, what is the fastest way?

Q:Cython:2列表功能简单,最快的方法是什么?

What I want to do - transform my pure Python code into Cython.

Pure Python code:

def conflicts(list1,list2):
    numIt = 10
    for i in list1:
        for j in list2:
            if i == j and i < numIt:
                return True
    return False
conflicts([1,2,3], [6,9,8])

My Cython code so far:

cdef char conflicts(int [] list1,int [] list2):
    cdef int numIt = 10
        for i in list1:
            for j in list2:
                if i == j and i < numIt:
                    return True
    return False
conflicts([1,2,3], [6,9,8])

Since I am completely new to Cython (and not really a pro in Python) I would like to get some feedback about my transformation. Am I doing the right thing? Is there anything else I should do in order to make the function even faster?

Update:

Does anyone know how i can add types in the header of the function for the input (list1, list2)? I tried "int [:]" which compiles without error but when i try to call the function with two lists i get the message "TypeError: 'list' does not have the buffer interface".

我想做的事-变换我的纯Python代码到Cython。

Pure Python code:

def conflicts(list1,list2):
    numIt = 10
    for i in list1:
        for j in list2:
            if i == j and i < numIt:
                return True
    return False
conflicts([1,2,3], [6,9,8])

My Cython code so far:

cdef char conflicts(int [] list1,int [] list2):
    cdef int numIt = 10
        for i in list1:
            for j in list2:
                if i == j and i < numIt:
                    return True
    return False
conflicts([1,2,3], [6,9,8])

因为我是全新的(不是真的Cython亲在Python)我想我转型的一些反馈。我做得对吗?还有什么我应该做的,以便使功能更快?

更新:

没有人知道我可以添加类型在函数头的输入(表、清单)?我试着“int [:]”编译没有错误,但是当我尝试调用函数有两个列表我得到消息”列表的列表,没有缓冲接口”。

answer1: 回答1:

"i" and "j" could be declared for optimize your code. First optimization with cython is accomplished using explicit declaration.

You can use

cython -a yourcode.py

and see some automatic suggestion of possible changes for optimize your python code with cython (yellow lines). You can work with c module generated (work perfect!).

Some handwrite cython optimization:
+ Using type list for list1 and list2.
+ bint type for conflicts functions because that return boolean value.
+ Get lenght of lists because for loop requiere end index.
+ Map lists in int arrays (because lists has only integer values).

cdef bint conflicts(list list1, list list2):
    cdef int numIt = 10
    cdef int i, j
    cdef int end_index = len(list1)
    cdef int[:] my_list1 = list1
    cdef int[:] my_list2 = list2

    for i in range(end_index):
        for j in range(end_index):
            if my_list1[i] == my_list2[j] and my_list1[i] < numIt:
                return True
    return False
conflicts([1,2,3], [6,9,8])

“I”和“j”可以声明为优化代码。用Cython第一优化是使用显式声明完成。

你可以使用

cython -a yourcode.py

看一些自动建议可能的变化与Cython优化你的Python代码(黄色线)。你可以用C模块生成(工作完美!)。

Some handwrite cython optimization:
+ Using type list for list1 and list2.
+ bint type for conflicts functions because that return boolean value.
+ Get lenght of lists because for loop requiere end index.
+ Map lists in int arrays (because lists has only integer values).

cdef bint conflicts(list list1, list list2):
    cdef int numIt = 10
    cdef int i, j
    cdef int end_index = len(list1)
    cdef int[:] my_list1 = list1
    cdef int[:] my_list2 = list2

    for i in range(end_index):
        for j in range(end_index):
            if my_list1[i] == my_list2[j] and my_list1[i] < numIt:
                return True
    return False
conflicts([1,2,3], [6,9,8])
answer2: 回答2:

As I commented, you should be able to get a pretty substantial improvement by changing your algorithm, without messing with cython at all. Your current code is O(len(list1)*len(list2)), but you can reduce this to O(len(list1)+len(list2)) by using a set. You can also simplify the code by using the builtin any function:

def conflicts(list1,list2):
    numIt = 10
    s1 = set(list1)
    return any(x in s1 and x < numIt for x in list2)

Depending on how many numbers in each list you expect to be less than 10, you might try moving the x < numIt test around a bit to see what is fastest (filtering list1 before you turn it into a set, for instance, or putting if x < numIt after the for in the generator expression inside any).

我说,你可以通过改变你的算法得到一个相当大的改进,不搞乱Cython所有。你当前的代码是O(len(表)*莱恩(清单)),但你可以降低到O(len(表)+ len(清单))通过使用一组。你也可以通过内置的任何函数简化代码:

def conflicts(list1,list2):
    numIt = 10
    s1 = set(list1)
    return any(x in s1 and x < numIt for x in list2)

这取决于有多少数字在每个列表你会小于10,你可能会尝试移动X & lt;鑫美得测试一下看看什么是最快的(过滤表之前,你把它变成一个集,例如,或者如果X & lt;后在内的任何发电机鑫美得表达)。

python  performance  optimization  cython