Python,高效地清除大列表

Python,高效地清除大列表,python,list,data-structures,Python,List,Data Structures,我需要清除一个巨大的列表,其中包含大约350k复杂阵列。基本上只用了2分钟就可以用所有3种方式清除列表del data_list[:]、data_list.clear或data_list=[] 正如评论中所建议的,我将详细阐述这个案例。所谓复数数组,我指的是复数数组。以下代码再现了该情况 将numpy作为np导入 数据列表=[np.zeros4408,dtype=范围350000的复杂数据] data_list=[]这需要相当长的时间 我能想到的一种解决方法是将列表设置为局部变量,但由于需要在代

我需要清除一个巨大的列表,其中包含大约350k复杂阵列。基本上只用了2分钟就可以用所有3种方式清除列表del data_list[:]、data_list.clear或data_list=[]

正如评论中所建议的,我将详细阐述这个案例。所谓复数数组,我指的是复数数组。以下代码再现了该情况

将numpy作为np导入 数据列表=[np.zeros4408,dtype=范围350000的复杂数据] data_list=[]这需要相当长的时间 我能想到的一种解决方法是将列表设置为局部变量,但由于需要在代码中动态读取日志,所以这有点困难

那么,有没有一种有效的方法来清理一张大名单

任何建议都会有帮助。非常感谢


你能把它做成一个小数组吗

由于数组的数量可能会有所不同,所以我认为动态追加数据最好使用列表。如果我错了,请纠正我。 使现代化
在@6502的帮助下,我们发现这个问题实际上是Windows上核心Python的一个潜在错误。

您的代码片段中最长的部分是在我的系统0.56s上进行分配,而不是在我的系统0.07s上取消分配

import numpy as np, time, gc 
print("1") 
start = time.time() 
#gc.disable() 
data_list = [np.zeros((4, 408), dtype=complex) for _ in range(350000)] 
mid = time.time() 
#gc.enable() 
print("2") 
data_list = []  # "this takes fairly long time" (doesn't for me)
end = time.time() 
print("3") 
print(mid-start, end-mid) 
我的猜测是,因为元素很大,所以在分配循环中多次触发垃圾收集器,但没有验证;即使禁用分配周围的垃圾收集也不会加快系统上的代码速度

使其成为一个具有

 data = np.zeros((350000, 4, 408), dtype=complex)
 data = []
是即时的,因为它是一次性分配和释放的单个大内存对象。当然,它不是一个列表对象,因此其行为并不完全相同

如果您的代码在释放时占用了大量内存,那么问题可能是内存损坏,即分页。350000x4x408大约是5亿,这个数量的双精度复数将包含一个大约9Gb的numpy数组,作为复杂的Python对象要多得多

如果您没有那么多的可用RAM,那么依靠虚拟内存来管理它将是一件痛苦的事情,事实上,可以观察到的症状可能是,当处理终止时,需要花很多时间将所有被释放的内容重新分页,以便为数据腾出空间

如果是这样的话,那么即使将所有数据放在一个内存块中也不会有太大的速度,因为时间是用来恢复被丢弃的9Gb数据的,而不是释放本身

在Windows系统上,如果进入垃圾箱模式,对系统性能的损害甚至可能是永久性的:换句话说,在下次重新启动之前,系统可能无法恢复到正常速度。这是发生在很多年前的Windows XP,我不经常使用Windows。。。可能是最新版本修复了该问题

使现代化 当您测试脚本时,释放仍然需要2分钟,我认为可以在python或numpy发行版中进行解释。 要检查问题所在,您可以更换

 np.zeros((4, 408), dtype=complex)


仅使用标准Python对象分配相同数量的内存;如果问题仍然存在,那么问题在核心python中,否则在numpy中。在这两种情况下,我都会提交错误报告。。。这可能是windows上的一个已知问题,答案将是wontfix,但似乎很奇怪,因为在我的Linux系统上解除分配只需不到1秒,而且我的系统似乎没有你的120倍强大。

你能把它做成numpy阵列吗?我认为清除numpy阵列比普通内置阵列快得多。请提供一个更具体的示例说明您正在做什么。你说的复杂数组到底是什么意思?注意,350k不算什么。如果是do my_list=[object for u in range350000],那么my_list.clear是即时的。注意,data_list=[]并不等同于data_list.clear,虽然两者都可能导致data_list中引用的对象被垃圾收集,但为什么需要这么长时间取决于该列表中的内容,而不是列表本身,它很小,清除它实际上不需要时间,这将是其他的东西happens@juanpa.arrivillaga谢谢。你是对的。现在添加了更多详细信息。这相当于9个完整千兆字节的阵列。我希望您有足够的内存。即使这样,2分钟似乎也很长,因为释放数组并不涉及遍历其缓冲区,但如果ndarray类型的释放例程比我预期的慢,那么这似乎是合理的。在计时之后,我可以确认,解除分配远没有那么慢。在一个比我测试的速度慢的系统上创建一个大的阵列列表可能需要很长时间,但不会破坏它。谢谢你的回答。但是,正如问题中所提到的,阵列的数量可能会有所不同,这意味着在开始的示例中,我无法获得350k阵列的确切数量。我的系统有32GB的RAM,所以我想虚拟内存不会是这里的问题。@MrCrHaM:关键点不是RAM的数量,这是你的可用内存量。我一直在监控整个ti的内存使用情况
对我来说,这还远远没有达到极限。峰值内存使用量约为20GB。@MrCrHaM:在这2分钟内,计算机在做什么?是100%CPU吗?
 array.array("d", [0.0]) * (2*4*408))