Cython包装不够快,如何加快速度?

时间:2015-11-03 14:21:07

标签: python performance cython

我有一个C ++库,我想在python中包含它的一些功能。

该函数将给定的字符数组拆分为5个部分,而不是实际的拆分,但是我们传递指针的结构,包含函数返回后的部分信息。 5个结构每个包含2个整数,一个表示零件的开头,另一个表示零件的长度。

python包装器应该接受一个python字符串并返回5个部分的字典或元组(也作为python字符串)。

我当前调用函数然后使用python切片语法基于子部分信息拆分python字符串的方法并没有产生任何显着的速度增益。我意识到有很多类似的问题,但这些案例都没有对我有所帮助。

Cython定义代码是 -

cdef extern from "parse.h" namespace util
    ctypedef struct part:
        int begin;
        int len;

    ctypedef struct Parsed:
        part part1;
        part part2;
        part part3;
        part part4;
        part part5;

    void ParseFunc(const char* url, int url_len, Parsed* parsed)

Cython代码是 -

cimport parseDef

def parse(url, url_len):
    cdef parseDef.Parsed parsed
    parseDef.parseFunc(url, url_len, &parsed)

    part1 = url[parsed.part1.begin:parsed.part1.begin+parsed.part1.len]
    #similar code for other parts

    return (part1, part2, part3, part4, part5)

此包装器的典型字符串大小通常为10-50。

1 个答案:

答案 0 :(得分:1)

通过const char*而不是字符串

进行索引可以获得一些好处
cimport parseDef

def parse(url, url_len):
    cdef const char* url_as_char_ptr = url # automatic conversion
    cdef parseDef.Parsed parsed
    parseDef.parseFunc(url, url_len, &parsed)

    part1 = url_as_char_ptr[parsed.part1.begin:parsed.part1.begin+parsed.part1.len]
    #similar code for other parts

    return (part1, part2, part3, part4, part5)

我认为你不能打败这个,主要是因为生成的c代码实际上非常有效。索引行转换为类似

的内容
__pyx_t_2 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_url_as_char_ptr + idx1, idx2 - idx1)

(注意我已将parsed.part1.begin替换为idx1只是为了便于阅读,因为我使用稍微不同的代码对此进行测试,因为我没有parseFunc。您可以使用cython -a yourfile.pyx检查确切的代码并查看html输出。

这基本上只是调用Python c-api字符串构造函数。这必然会传递它传递的字符串的副本,但你无法避免(Python字符串构造函数总是复制)。这不会留下很多开销。