【发布时间】:2021-08-21 16:14:01
【问题描述】:
我有一个任务是使用贪婪的方法来满足 TSP。问题有33708个城市。因为我在之前的作业中有很多有用的工具,所以我决定重用这种方法并预先计算距离。
所以这仅超过十亿个条目(33708 选择 2),每个条目都非常适合 float32。 x 和 y 坐标同样是数字 $|n|
我的蟒蛇是:
def get_distance(left, right):
""" return the euclidean distance between tuples left and right, which are coordinates"""
return ((left[0] - right[0]) ** 2 + (left[1] - right[1]) ** 2) ** 0.5
# precompute all distances
distances = {}
for i in range(len(cities)):
for j in range(i + 1, len(cities)):
d = get_distance(cities[i], cities[j])
distances[frozenset((i, j)))] = d
我预计这会占用 (3 * 32b) * 568m ≈ 6.7 GB 的内存。但事实上,在我的 jupyter notebook 中观看实时运行时,它似乎甚至超过了 35GB。 (442s 和计数)我不得不杀死它,因为我很好地进入了我的交换空间并且它减慢了很多。有谁知道为什么这么大?
更新:再次尝试使用 tuple(sorted((i,j))) -- 但在 110 秒时它已经是 15GB 并且还在计数
尺寸
>>> import sys
>>> a = frozenset((1,2))
>>> sys.getsizeof(a)
216
>>> sys.getsizeof(tuple(sorted((1,2))))
56
>>> sys.getsizeof(1)
28
python 中是否有类似 float32 和 int16 的东西? -- ans: numpy 有它们
更新尝试:
from numpy import float32, int16
from itertools import combinations
import sys
def get_distance(left, right):
""" return the euclidean distance between tuples left and right, which are coordinates"""
return float32(((left[0] - right[0]) ** 2 + (left[1] - right[1]) ** 2) ** 0.5)
# precompute all distances
distances = {}
for i, j in combinations(range(len(cities)), 2):
distances[tuple(sorted((int16(i), int16(j))))] = get_distance(cities[i], cities[j])
print(sys.getsizeof(distances))
观察到的尺寸:
- 与
cities = cities[:2]:232 - 与
cities = cities[:3]:也是232 - 与
cities = cities[:10]:2272 - 与
cities = cities[:100]:147552 -
cities = cities[:1000]:20971608 (20MB) -
cities = cities[:10000]: 2684354656 (2.6GB)
请注意,即使我们接近 5000 万个条目,即 10000 个选择 2(占数据总大小的 10%),增长率也不会随数据成比例:
- 2684354656/(1000 选择 2 / 100 选择 2 * 20971608) ≈ 1.27
- 20971608/(1000 选 2 / 100 选 2 * 147552) ≈ 1.4
我决定停止对完整城市列表的尝试,因为我的操作系统快照内存增长到超过 30GB 并且我要进行交换。这意味着,即使最终对象最终有那么大,笔记本所需的内存量仍然要大得多。
【问题讨论】:
-
什么是 3 * 32b?
-
1x32b 是距离。还有 2 个是 x 和 y 坐标。 (更新了问题描述)。在分配时,它们是
d、i和j。 -
试试
sys.getsizeof(frozenset((1, 2)))。 -
与实际键/值对象足迹相比,是的,字典足迹可能微不足道。但它比你最初的想法要大。例如,
sys.getsizeof(dict.fromkeys(range(10**6))) / 1e6给了我41.943136,所以每个项目大约 42 字节的字典占用空间。 -
所有
i和j对象的内存可以通过重用相同的对象来减少很多,例如没有很多对象都具有相同的值3141。就像for i, j in itertools.combinations(range(len(cities)), 2):.但是无论如何,集合/元组/字典仍然会花费很多。
标签: python jupyter-notebook np-complete