首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >(JIT)用FFI库调用编译Python代码

(JIT)用FFI库调用编译Python代码
EN

Stack Overflow用户
提问于 2021-04-01 14:40:01
回答 1查看 178关注 0票数 0

我正在使用Python与一个使用cppyy的库一起使用Python来访问大量的C++函数。但是,对cppyy方法的调用需要很长时间,在Python中循环库调用意味着开销成为一个严重的问题。下面是我的一个例子:

代码语言:javascript
复制
import ROOT  # Library based on cppyy

def some_function():
    for i in range(10_000_000):
        ROOT.some_method(i)  # A little bit of overhead * 10_000_000 is a lot of overhead

如果我在C++中直接使用根库,这段代码会非常快,但是Python非常慢。

在编译版本不使用Python运行时(如numba nopython=True)的情况下,是否有一种方法可以将其编译为快速运行?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-01 16:58:14

some_method中只需做很少的工作就可以让日常开销变得重要.请注意,还存在方法查找的开销(即ROOT.位),如果cppyy开销不是可以忽略的,Python本身中的迭代器协议也是不可忽略的(给空循环计时,我发现它占总开销的20% )。

为了避免所有这些,如果这是一个紧密的内环,只需反转它并在C++中运行它。例如,比较以下几点:

代码语言:javascript
复制
import cppyy
import time

N = 10000000

cppyy.cppdef("""\
void cppmethod(int i) {
   /* empty */
}""")

f = cppyy.gbl.cppmethod

ts = time.perf_counter()
for i in range(N):
    f(i)
te = time.perf_counter()-ts
print("python loop:", te)

cppyy.cppdef("""\
template<typename T>
void call_cppmethod(T f, int N) {
    for (int i = 0; i < N; ++i) f(i);
}""")

ts = time.perf_counter()
cppyy.gbl.call_cppmethod(f, N)
te = time.perf_counter()-ts
print("callback loop:", te)

在我的笔记本电脑上,回调比Python循环快100倍。但是,如果我在cppmethod上做了什么,例如。调用三角函数时,差异已经下降到10倍(同样,一个很好的块只是python循环)。

可以肯定的是,上面使用的回调模板在cppyy中起作用。然而,根包含一个已经过时的分叉cppyy。在那里,您不能使用模板,必须对函数类型进行显式说明:

代码语言:javascript
复制
cppyy.cppdef("""\
void call_cppmethod(void (*f)(int), int N) {
    for (int i = 0; i < N; ++i) f(i);
}""")

如果/当ROOT更新他们的分叉时,这个问题可能会在将来的某个时候消失,但现在情况就是这样。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66906591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档