ctypes与C扩展的区别

27

我有几个用于游戏项目的C函数。这些函数被频繁调用(约每秒2000-4000次)。这些函数采用C语言编写以获得更快的速度。

现在,将这些函数包含到Python中最简单的方法是使用ctypes。另一种选择是围绕这些函数编写一个C扩展到Python中(需要额外的努力)。因此,我想知道,在不包括DLL的初始加载的情况下,ctypes的开销有多大?


我使用的是Python 2.7(标准的CPython版本),我不想使用像Cython这样的外部库。

我知道这个问题以前已经被问过,但我没有看到关于两个选项之间性能比较的更多信息。


嗯,PyPy的JIT自发布以来就可以为“ctypes”调用生成相当不错的代码。你可能想要试一试。我没有把这个作为答案发表,因为我手头没有硬数据,并且是否切换解释器对你是否可行也不是很清楚。 - user395760
我预计开销会相似。 - David Heffernan
@Delnan:这是我要发布的游戏 - 也要发布到Linux。我不能要求我的用户安装PyPy。 - orlp
1
请注意,如果您的用例是调用C库函数或系统调用,则应考虑使用ctypes模块而不是编写自定义C代码。 ctypes不仅可以让您编写Python代码以与C代码进行交互,而且在Python的实现之间更具可移植性,而编写和编译扩展模块通常会将您绑定到CPython。 - baco
2个回答

18

我比较了一个C扩展和ctypes包装器的性能。在我的特定测试中,差异约为250倍。由于多次调用了C库,因此ctypes包装器还执行了Python代码。C库的运行时间非常短,这使得Python代码的额外开销更加显著。因此,比率在您的情况下可能会有所不同,但在我的情况下是显著的。


13
哪一个慢了 250 倍? - user395760
2
从他的回答中,我可以看出 ctypes 包装器速度较慢。 - orlp

9
直接使用C编写的接口具有更快的潜力。瓶颈在于Python与C之间的接口,以及参数和结果的整合,例如复制字符串或将Python列表转换为/从C数组。如果您有一个循环,需要进行数百次这些调用,并且某些数据不必为每个调用单独进行整合,那么您所要做的就是在C中重新编码循环,您可能可以大量减少瓶颈。ctypes并没有给您这个选择:您只能直接调用现有的函数。
当然,这一切取决于您正在调用什么类型的函数以及传递什么类型的数据。如果您无法减少开销,那么我仍然期望ctypes会更慢,但也许不会显著。
您最好的选择是编写两种方式的代码示例并进行基准测试。否则,变量太多了,无法得出明确的答案。

1
我们所讨论的数据是一个位掩码(用于碰撞检测)。我已经准备好了一个C语言实现,Python代码中传递的唯一数据是布尔值、坐标和新的Python位掩码类(它只包含指向实际数据本身的指针,该数据存储在C代码中)。 - orlp
对于位图,也许可以尝试使用numpy。内置的Python位图支持除了底层本机类型之外,其他都相当缓慢。 - tripleee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接