cython 也可以优化 python 字典内存和查找速度吗?
Can cython optimize python dictionary memory and lookup speed as well?
我有一个 class 主要包含三个字典:
class KB(object):
def __init__(self):
# key:str value: list of str
linear_patterns = defaultdict(list)
# key:str value: list of str
nonlinear_patterns = defaultdict(list)
# key: str value: dict
pattern_meta_info = {}
...
self.__initialize()
def __initialize(self):
# the 3 dicts are populated
...
3 个字典的大小如下:
linear_patterns: 100,000
non_linear_patterns: 900,000
pattern_meta_info: 700,000
程序运行完成后,释放内存大约需要15秒。当我在初始化时通过加载较少的数据来减少上面的dict sizes的数量时,内存释放更快,所以我判断是由于这些dict sizes导致内存释放变慢。整个程序大约需要8G内存。另外,dicts构建后,所有操作都是查找,没有修改。
有没有办法用cython来优化上面的3种数据结构,尤其是在内存占用方面?是否有类似的 cython 字典可以替代 python 字典?
不同的字典或对象类型似乎不太可能发生太大变化。析构函数的性能由内存分配器决定。除非您切换到不同的 malloc 实现,否则这将大致相同。
如果这只是关于在程序结束时销毁对象,大多数语言(但 Python 除外)将允许您使用调用 exit
,同时保持 KB 对象处于活动状态。 OS 将在进程终止时更快地释放内存。那么为什么要打扰呢?不幸的是,这不适用于 Python 的 sys.exit()
,因为这只会引发异常。
其他一切都依赖于更改数据结构或算法。您的字符串是否高度冗余?也许您可以通过实习来重用字符串对象。将它们保存在一个共享集中,以便在多个地方使用相同的字符串。对 string = sys.intern(string)
的简单调用就足够了。与 Python 的早期版本不同,这不会使字符串对象在其使用之外保持活动状态,因此您不会 运行 在 long-running 进程中泄漏内存的风险。
您还可以将字符串集中在一个大的分配中。如果访问相对较少,您可以将 class 更改为其包含的字符串使用一个大的 io.StringIO
对象,所有字典只处理 (offset, length)
元组到该缓冲区。
这仍然留下许多元组和整数对象,但那些使用可能更快的专用分配器。此外,长度整数将来自小整数的公共池,并且不会分配新对象。
最后一个想法:8 GB 的字符串数据。您确定不需要小型 sqlite 或 dbm 数据库吗?可能是一个临时文件
我有一个 class 主要包含三个字典:
class KB(object):
def __init__(self):
# key:str value: list of str
linear_patterns = defaultdict(list)
# key:str value: list of str
nonlinear_patterns = defaultdict(list)
# key: str value: dict
pattern_meta_info = {}
...
self.__initialize()
def __initialize(self):
# the 3 dicts are populated
...
3 个字典的大小如下:
linear_patterns: 100,000
non_linear_patterns: 900,000
pattern_meta_info: 700,000
程序运行完成后,释放内存大约需要15秒。当我在初始化时通过加载较少的数据来减少上面的dict sizes的数量时,内存释放更快,所以我判断是由于这些dict sizes导致内存释放变慢。整个程序大约需要8G内存。另外,dicts构建后,所有操作都是查找,没有修改。
有没有办法用cython来优化上面的3种数据结构,尤其是在内存占用方面?是否有类似的 cython 字典可以替代 python 字典?
不同的字典或对象类型似乎不太可能发生太大变化。析构函数的性能由内存分配器决定。除非您切换到不同的 malloc 实现,否则这将大致相同。
如果这只是关于在程序结束时销毁对象,大多数语言(但 Python 除外)将允许您使用调用 exit
,同时保持 KB 对象处于活动状态。 OS 将在进程终止时更快地释放内存。那么为什么要打扰呢?不幸的是,这不适用于 Python 的 sys.exit()
,因为这只会引发异常。
其他一切都依赖于更改数据结构或算法。您的字符串是否高度冗余?也许您可以通过实习来重用字符串对象。将它们保存在一个共享集中,以便在多个地方使用相同的字符串。对 string = sys.intern(string)
的简单调用就足够了。与 Python 的早期版本不同,这不会使字符串对象在其使用之外保持活动状态,因此您不会 运行 在 long-running 进程中泄漏内存的风险。
您还可以将字符串集中在一个大的分配中。如果访问相对较少,您可以将 class 更改为其包含的字符串使用一个大的 io.StringIO
对象,所有字典只处理 (offset, length)
元组到该缓冲区。
这仍然留下许多元组和整数对象,但那些使用可能更快的专用分配器。此外,长度整数将来自小整数的公共池,并且不会分配新对象。
最后一个想法:8 GB 的字符串数据。您确定不需要小型 sqlite 或 dbm 数据库吗?可能是一个临时文件