Cython wrapper 不够快,如何加快它的速度?
Cython wrapper not fast enough, how to speed it up?
我有一个 C++ 库,我想在 python 中包装它的一些功能。
该函数将给定的字符数组拆分为 5 个部分,不是实际拆分,而是我们传递给指针的结构,包含有关函数 returns 之后部分的信息。 5 个结构每个包含 2 个整数,一个表示部分的开始,另一个表示部分的长度。
python 包装器应该接受一个 python 字符串和 return 一个包含 5 个部分的字典或元组(也作为 python 字符串)。
我目前调用函数然后使用 python 切片语法根据子部分信息拆分 python 字符串的方法没有产生任何显着的速度提升。我意识到有很多类似的问题,但其中 none 个案例对我有所帮助。
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。
您可以通过对 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 字符串构造函数总是复制)。这不会留下很多开销需要删除。
我有一个 C++ 库,我想在 python 中包装它的一些功能。
该函数将给定的字符数组拆分为 5 个部分,不是实际拆分,而是我们传递给指针的结构,包含有关函数 returns 之后部分的信息。 5 个结构每个包含 2 个整数,一个表示部分的开始,另一个表示部分的长度。
python 包装器应该接受一个 python 字符串和 return 一个包含 5 个部分的字典或元组(也作为 python 字符串)。
我目前调用函数然后使用 python 切片语法根据子部分信息拆分 python 字符串的方法没有产生任何显着的速度提升。我意识到有很多类似的问题,但其中 none 个案例对我有所帮助。
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。
您可以通过对 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 字符串构造函数总是复制)。这不会留下很多开销需要删除。