2011-01-27 51 views

回答

5

编辑:混合PyMem_MallocPyObject_Malloc更正;他们是两个不同的电话。

没有PYMALLOC_DEBUG宏激活,PyMem_Malloc是libc中的malloc()的别名,有一个特殊情况:调用PyMem_Malloc分配零个字节会返回一个非NULL指针,而的malloc(zero_bytes)可能返回NULL值或养系统错误(source code reference):

/* malloc。请注意,nbytes == 0尝试使用 来从其他所有当前活动的指针返回非NULL指针,不同的 *。这可能是不可能的。 */

此外,还有对pymem.h header file的咨询说明:

决不调用PyMem_与 呼叫平台的malloc/realloc的/ 释放calloc /自由搭配。例如,在Windows 上,不同的DLL最终可能会使用 不同的堆,并且如果使用 PyMem_Malloc,则会从Python DLL使用的堆中获取内存 ;它可能是一个灾难,如果你直接在你自己的 扩展名中免费()。使用PyMem_Free代替 确保Python可以将 内存返回到适当的堆。作为另一个 例如,在PYMALLOC_DEBUG模式, 的Python包在 特殊的调试包装是增加 额外的调试信息,以 动态内存块的所有PyMem_ 和PyObject_记忆功能的所有调用。系统 例程不知道该怎么做 与该东西,和Python 包装不知道该怎么做 与原始块直接通过 系统例程然后。

然后,里面有 PyMem_Malloc PyObject_Malloc一些Python特定的调音,使用的功能不仅为C扩展,但对于所有的动态分配运行Python程序,同时,像100*234str(100)10 + 4j

>>> id(10 + 4j) 
139721697591440 
>>> id(10 + 4j) 
139721697591504 
>>> id(10 + 4j) 
139721697591440 

以前的complex()实例是在专用池上分配的小对象。因为它是从池中完成对准块8个字节,现有的对于每个块大小为一个池 PyMem_Malloc PyObject_Malloc

小物件(< 256字节)分配是相当有效的。还有Pages和Arenas块用于更大的分配。

source code这一评论解释了PyObject_Malloc呼叫如何优化:

/* 
* The basic blocks are ordered by decreasing execution frequency, 
* which minimizes the number of jumps in the most common cases, 
* improves branching prediction and instruction scheduling (small 
* block allocations typically result in a couple of instructions). 
* Unless the optimizer reorders everything, being too smart... 
*/ 

池,Pages和阿里纳斯都是为了降低长期运行的Python程序的external memory fragmentation优化。

查看the source code了解关于Python内存内部的完整详细文档。

1

从我写MATLAB MATLAB函数的经验来看,我认为使用malloc或不使用malloc的最大决定因素是可移植性。假设你有一个头文件,它只使用内部的c数据类型来执行一些有用的函数(没有必要的Python对象交互,所以使用malloc没有问题),并且你突然意识到你想要将该头文件移植到不同的代码库与Python无关(也许这是一个纯粹用C编写的项目),使用malloc显然是一个更便携的解决方案。

但是对于纯粹是Python扩展的代码,我最初的反应是希望本机c函数的执行速度更快。我没有证据可以支持:)

+2

对于期望本机C函数执行得更好,您是正确的。问题是它们都是本地C函数。 :-) – 2011-01-27 23:59:11

+1

嗯,我想他们是......很好的技术性:)我想我的意思是说,我希望C的本地内存分配系统比为Python的内存分配系统实现的本地C更快:P – William 2011-01-28 00:22:41

6

扩展使用malloc或其他系统分配器分配内存是完全可以的。对于许多类型的模块来说,这是正常的和不可避免的 - 大多数包装其他库的模块(它们本身对Python一无所知)会在库中发生本地分配。 (有些库允许您控制分配,以防止出现这种情况;大多数情况下不会)。

使用PyMem_Malloc存在一个严重缺陷:您需要在使用GIL时保留GIL。本地库通常希望在执行CPU密集型计算或进行任何可能阻塞的调用(如I/O)时释放GIL。在分配之前需要锁定GIL可能会非常不方便和性能问题之间。

使用Python的包装进行内存分配可以使用Python的内存调试代码。但是,像Valgrind这样的工具,我怀疑它的实际价值。

如果API需要它,您将需要使用这些函数;例如,如果API传递了一个必须用这些函数分配的指针,所以它可以与它们一起被释放。除了使用它们这样的明确理由之外,我坚持正常分配。

相关问题